blob: ebc026e518ad466196872e480e7d0df4a948c5db [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
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +000020# python welcome_message.py --change Ia1fea1eab3976f1a9cb89ceb3ce1c6c6a7e79c42
Tom Fifieldd3393472013-11-28 12:27:56 +110021# --change-url \ https://review-dev.openstack.org/81 --project gtest-org/test \
22# --branch master --uploader User A. Example (user@example.com) --commit \
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +000023# 05508ae633852469d2fd7786a3d6f1d06f87055b --patchset 1 patchset-merged \
24# --ssh-user=user --ssh-key=/home/user/.ssh/id_rsa
Tom Fifieldd3393472013-11-28 12:27:56 +110025# 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
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +000068def post_message(commit, gerrit_user, gerrit_ssh_key):
69 """Post a welcome message on the patch set specified by the commit."""
Tom Fifieldd3393472013-11-28 12:27:56 +110070
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 """
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +000094 # post the above message, using ssh.
95 command = ('gerrit review '
96 '--message="{message}" {commit}').format(
97 message=welcome_text,
98 commit=commit)
99 logger.info('Welcoming: %s', commit)
100 ssh = paramiko.SSHClient()
101 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
102 ssh.connect('localhost', username=gerrit_user,
103 key_filename=gerrit_ssh_key, port=29418)
104 stdin, stdout, stderr = ssh.exec_command(command)
105 stdout_text = stdout.read()
106 stderr_text = stderr.read()
107 ssh.close()
108 if stdout_text:
109 logger.debug('stdout: %s' % stdout_text)
110 if stderr_text:
111 logger.error('stderr: %s' % stderr_text)
Tom Fifieldd3393472013-11-28 12:27:56 +1100112
113
114def main():
115 parser = argparse.ArgumentParser()
116 parser.add_argument('hook')
117 # common
118 parser.add_argument('--change', default=None)
119 parser.add_argument('--change-url', default=None)
120 parser.add_argument('--project', default=None)
121 parser.add_argument('--branch', default=None)
122 parser.add_argument('--commit', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800123 parser.add_argument('--topic', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100124 # change-merged
125 parser.add_argument('--submitter', default=None)
126 # patchset-created
127 parser.add_argument('--uploader', default=None)
128 parser.add_argument('--patchset', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800129 parser.add_argument('--is-draft', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100130 # for Welcome Message
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +0000131 parser.add_argument('--ssh-user', dest='ssh_user',
132 help='The gerrit welcome message user')
133 parser.add_argument('--ssh-key', dest='ssh_key',
134 help='The gerrit welcome message SSH key file')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800135 # Don't actually post the message
136 parser.add_argument('--dryrun', dest='dryrun', action='store_true')
137 parser.add_argument('--no-dryrun', dest='dryrun', action='store_false')
Jeremy Stanley6cfc9ea2014-02-25 14:56:09 +0000138 parser.add_argument('-v', '--verbose', dest='verbose', action='store_true',
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800139 help='verbose output')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800140 parser.set_defaults(dryrun=False)
Tom Fifieldd3393472013-11-28 12:27:56 +1100141
142 args = parser.parse_args()
143
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800144 if args.verbose:
145 logging.basicConfig(level=logging.DEBUG)
146 else:
147 logging.basicConfig(level=logging.ERROR)
148
Tom Fifieldd3393472013-11-28 12:27:56 +1100149 # they're a first-timer, post the message on 1st patchset
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +0000150 if is_newbie(args.uploader) and args.patchset == '1' and not args.dryrun:
151 post_message(args.commit, args.ssh_user, args.ssh_key)
Tom Fifieldd3393472013-11-28 12:27:56 +1100152
153if __name__ == "__main__":
154 main()