#!/usr/bin/env python # Copyright (c) 2012 OpenStack, LLC. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # This script is designed to expire old code reviews that have not been touched # using the following rules: # 1. if open and no activity in 2 weeks, expire # 2. if negative comment and no activity in 1 week, expire import paramiko import json import logging import argparse logger = logging.getLogger('expire_reviews') logger.setLevel(logging.INFO) def expire_patch_set(ssh, patch_id, patch_subject, has_negative): if has_negative: message = ('code review expired after 1 week of no activity' ' after a negative review, it can be restored using' ' the \`Restore Change\` button under the Patch Set' ' on the web interface') else: message = ('code review expired after 2 weeks of no activity,' ' it can be restored using the \`Restore Change\` button ' ' under the Patch Set on the web interface') command = ('gerrit review --abandon' '--message="{message}" {patch_id}').format( message=message, patch_id=patch_id) logger.info('Expiring: %s - %s: %s', patch_id, patch_subject, message) stdin, stdout, stderr = ssh.exec_command(command) if stdout.channel.recv_exit_status() != 0: logger.error(stderr.read()) def main(): parser = argparse.ArgumentParser() parser.add_argument('user', help='The gerrit admin user') parser.add_argument('ssh_key', help='The gerrit admin SSH key file') options = parser.parse_args() GERRIT_USER = options.user GERRIT_SSH_KEY = options.ssh_key logging.basicConfig(format='%(asctime)-6s: %(name)s - %(levelname)s' ' - %(message)s', filename='/var/log/gerrit/expire_reviews.log') logger.info('Starting expire reviews') logger.info('Connecting to Gerrit') ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect('localhost', username=GERRIT_USER, key_filename=GERRIT_SSH_KEY, port=29418) # Query all open with no activity for 2 weeks logger.info('Searching no activity for 2 weeks') stdin, stdout, stderr = ssh.exec_command( 'gerrit query --current-patch-set --format JSON status:open age:2w') for line in stdout: row = json.loads(line) if 'rowCount' not in row: expire_patch_set(ssh, row['currentPatchSet']['revision'], row['subject'], False) # Query all reviewed with no activity for 1 week logger.info('Searching no activity on negative review for 1 week') stdin, stdout, stderr = ssh.exec_command( 'gerrit query --current-patch-set --all-approvals' ' --format JSON status:reviewed age:1w') for line in stdout: row = json.loads(line) if 'rowCount' not in row: # Search for negative approvals for approval in row['currentPatchSet']['approvals']: if approval['value'] == '-1': expire_patch_set(ssh, row['currentPatchSet']['revision'], row['subject'], True) break logger.info('End expire review')