blob: b5421234e47a888061ff1b7984eacb6d9216f5ab [file] [log] [blame]
Monty Taylorf45f6ca2012-05-01 17:11:48 -04001#!/usr/bin/env python
2# Copyright (c) 2012 OpenStack, LLC.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16# This script is designed to expire old code reviews that have not been touched
17# using the following rules:
18# 1. if open and no activity in 2 weeks, expire
19# 2. if negative comment and no activity in 1 week, expire
20
Monty Taylorf45f6ca2012-05-01 17:11:48 -040021import paramiko
22import json
23import logging
Andrew Hutchings6a178932012-05-17 14:53:01 +010024import argparse
Monty Taylorf45f6ca2012-05-01 17:11:48 -040025
Monty Taylorda3bada2012-11-22 09:38:22 -080026logger = logging.getLogger('expire_reviews')
Monty Taylorf45f6ca2012-05-01 17:11:48 -040027logger.setLevel(logging.INFO)
28
Monty Taylorf45f6ca2012-05-01 17:11:48 -040029
Monty Taylorda3bada2012-11-22 09:38:22 -080030def expire_patch_set(ssh, patch_id, patch_subject, has_negative):
31 if has_negative:
32 message = ('code review expired after 1 week of no activity'
33 ' after a negative review, it can be restored using'
34 ' the \`Restore Change\` button under the Patch Set'
35 ' on the web interface')
36 else:
37 message = ('code review expired after 2 weeks of no activity,'
38 ' it can be restored using the \`Restore Change\` button '
39 ' under the Patch Set on the web interface')
40 command = ('gerrit review --abandon'
41 '--message="{message}" {patch_id}').format(
42 message=message,
43 patch_id=patch_id)
Monty Taylorf45f6ca2012-05-01 17:11:48 -040044
Monty Taylorda3bada2012-11-22 09:38:22 -080045 logger.info('Expiring: %s - %s: %s', patch_id, patch_subject, message)
46 stdin, stdout, stderr = ssh.exec_command(command)
47 if stdout.channel.recv_exit_status() != 0:
48 logger.error(stderr.read())
Monty Taylorf45f6ca2012-05-01 17:11:48 -040049
Monty Taylorf45f6ca2012-05-01 17:11:48 -040050
Monty Taylorda3bada2012-11-22 09:38:22 -080051def main():
Monty Taylorf45f6ca2012-05-01 17:11:48 -040052
Monty Taylorda3bada2012-11-22 09:38:22 -080053 parser = argparse.ArgumentParser()
54 parser.add_argument('user', help='The gerrit admin user')
55 parser.add_argument('ssh_key', help='The gerrit admin SSH key file')
56 options = parser.parse_args()
Monty Taylorf45f6ca2012-05-01 17:11:48 -040057
Monty Taylorda3bada2012-11-22 09:38:22 -080058 GERRIT_USER = options.user
59 GERRIT_SSH_KEY = options.ssh_key
Monty Taylorf45f6ca2012-05-01 17:11:48 -040060
Monty Taylorda3bada2012-11-22 09:38:22 -080061 logging.basicConfig(format='%(asctime)-6s: %(name)s - %(levelname)s'
62 ' - %(message)s',
63 filename='/var/log/gerrit/expire_reviews.log')
64
65 logger.info('Starting expire reviews')
66 logger.info('Connecting to Gerrit')
67
68 ssh = paramiko.SSHClient()
69 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
70 ssh.connect('localhost', username=GERRIT_USER,
71 key_filename=GERRIT_SSH_KEY, port=29418)
72
73 # Query all open with no activity for 2 weeks
74 logger.info('Searching no activity for 2 weeks')
75 stdin, stdout, stderr = ssh.exec_command(
76 'gerrit query --current-patch-set --format JSON status:open age:2w')
77
78 for line in stdout:
79 row = json.loads(line)
80 if 'rowCount' not in row:
81 expire_patch_set(ssh,
82 row['currentPatchSet']['revision'],
83 row['subject'],
84 False)
85
86 # Query all reviewed with no activity for 1 week
87 logger.info('Searching no activity on negative review for 1 week')
88 stdin, stdout, stderr = ssh.exec_command(
89 'gerrit query --current-patch-set --all-approvals'
90 ' --format JSON status:reviewed age:1w')
91
92 for line in stdout:
93 row = json.loads(line)
94 if 'rowCount' not in row:
95 # Search for negative approvals
96 for approval in row['currentPatchSet']['approvals']:
97 if approval['value'] == '-1':
98 expire_patch_set(ssh,
99 row['currentPatchSet']['revision'],
100 row['subject'],
101 True)
102 break
103
104 logger.info('End expire review')