blob: 3536769db3c279875d61624b99792627be1ddbfa [file] [log] [blame]
Tom Fifieldd3393472013-11-28 12:27:56 +11001#!/usr/bin/env python
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15# This is designed to be called by a gerrit hook. It searched new
16# patchsets for those from a first time commiter, then posts a helpful
17# message welcoming them to the community and explaining the review process
18#
19# For example, this might be called as follows
20# python welcome_message.py -change Ia1fea1eab3976f1a9cb89ceb3ce1c6c6a7e79c42
21# --change-url \ https://review-dev.openstack.org/81 --project gtest-org/test \
22# --branch master --uploader User A. Example (user@example.com) --commit \
23# 05508ae633852469d2fd7786a3d6f1d06f87055b --patchset 1 patchset-merged user \
24# ~/.ssh/id_rsa
25# and if this was the first commit from "user@example.com", a message
26# would be posted on review 81.
27
28
29import argparse
30import logging
31import paramiko
32
33import jeepyb.gerritdb
34
35BASE_DIR = '/home/gerrit2/review_site'
36
37logger = logging.getLogger('welcome_reviews')
Tom Fifieldd3393472013-11-28 12:27:56 +110038
39
40def is_newbie(uploader):
41 """Determine if the owner of the patch is a first-timer."""
42
43 # Retrieve uploader email
44 try:
45 searchkey = uploader[uploader.rindex("(") + 1:-1]
46 except ValueError:
47 logger.info('Couldnt get email for %s', uploader)
48 return False
49
50 # this query looks for all distinct patchsets for the given
51 # user. If there's only 1, they're a first-timer.
52 query = """SELECT COUNT(DISTINCT p.change_id + p.patch_set_id)
53 FROM patch_sets p, account_external_ids a
54 WHERE a.email_address = %s
55 AND a.account_id = p.uploader_account_id;"""
56
57 cursor = jeepyb.gerritdb.connect().cursor()
58 cursor.execute(query, searchkey)
59 data = cursor.fetchone()
60 if data:
Jeremy Stanleyad63ded2014-03-06 23:42:15 +000061 if data[0] == 1:
Tom Fifieldafc6c242013-12-13 08:50:43 +080062 logger.info('We found a newbie: %s', uploader)
Tom Fifieldd3393472013-11-28 12:27:56 +110063 return True
64 else:
65 return False
66
67
68def post_message(change_id, gerrit_user, gerrit_ssh_key):
69 """Post a welcome message on the patch set specified by the change_id."""
70
71 welcome_text = """Thank you for your first contribution to OpenStack.
72
73 Your patch will now be tested automatically by OpenStack testing frameworks
74 and once the automatic tests pass, it will be reviewed by other friendly
75 developers. They will give you feedback and may require you to refine it.
76
77 People seldom get their patch approved on the first try, so don't be
78 concerned if requested to make corrections. Feel free to modify your patch
79 and resubmit a new change-set.
80
81 Patches usually take 3 to 7 days to be reviewed so be patient and be
82 available on IRC to ask and answer questions about your work. The more you
83 participate in the community the more rewarding it is for you. You may also
84 notice that the more you get to know people and get to be known, the faster
85 your patches will be reviewed and eventually approved. Get to know others
86 and become known by doing code reviews: anybody can do it, and it's a
87 great way to learn the code base.
88
89 Thanks again for supporting OpenStack, we look forward to working with you.
90
91 IRC: https://wiki.openstack.org/wiki/IRC
92 Workflow: https://wiki.openstack.org/wiki/Gerrit_Workflow
93 """
94 # get the patch_id
95 query = """SELECT change_id FROM patch_sets WHERE change_id = %s;"""
96
97 cursor = jeepyb.gerritdb.connect().cursor()
98 cursor.execute(query, change_id)
99 data = cursor.fetchone()
100 if data[0]:
101 # post the above message, using ssh.
102 command = ('gerrit review '
103 '--message="{message}" {patch_id}').format(
104 message=welcome_text,
105 patch_id=data)
106 logger.info('Welcoming: %s', data[0])
107 ssh = paramiko.SSHClient()
108 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
109 ssh.connect('localhost', username=gerrit_user,
110 key_filename=gerrit_ssh_key, port=29418)
111 stdin, stdout, stderr = ssh.exec_command(command)
112
113 else:
114 logger.info('Unable to find patch_id for change_id=%s', change_id)
115
116
117def main():
118 parser = argparse.ArgumentParser()
119 parser.add_argument('hook')
120 # common
121 parser.add_argument('--change', default=None)
122 parser.add_argument('--change-url', default=None)
123 parser.add_argument('--project', default=None)
124 parser.add_argument('--branch', default=None)
125 parser.add_argument('--commit', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800126 parser.add_argument('--topic', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100127 # change-merged
128 parser.add_argument('--submitter', default=None)
129 # patchset-created
130 parser.add_argument('--uploader', default=None)
131 parser.add_argument('--patchset', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800132 parser.add_argument('--is-draft', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100133 # for Welcome Message
134 parser.add_argument('user', help='The gerrit admin user')
135 parser.add_argument('ssh_key', help='The gerrit admin SSH key file')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800136 # Don't actually post the message
137 parser.add_argument('--dryrun', dest='dryrun', action='store_true')
138 parser.add_argument('--no-dryrun', dest='dryrun', action='store_false')
Jeremy Stanley6cfc9ea2014-02-25 14:56:09 +0000139 parser.add_argument('-v', '--verbose', dest='verbose', action='store_true',
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800140 help='verbose output')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800141 parser.set_defaults(dryrun=False)
Tom Fifieldd3393472013-11-28 12:27:56 +1100142
143 args = parser.parse_args()
144
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800145 if args.verbose:
146 logging.basicConfig(level=logging.DEBUG)
147 else:
148 logging.basicConfig(level=logging.ERROR)
149
Tom Fifieldd3393472013-11-28 12:27:56 +1100150 # they're a first-timer, post the message on 1st patchset
Tom Fifieldafc6c242013-12-13 08:50:43 +0800151 if is_newbie(args.uploader) and args.patchset == 1 and not args.dryrun:
Tom Fifieldd3393472013-11-28 12:27:56 +1100152 post_message(args.change, args.user, args.ssh_key)
153
154if __name__ == "__main__":
155 main()