blob: f4dbdf6cd492abb11f31fcb7343d6ae1210b4844 [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
K Jonathan Harker364eb142014-07-09 17:40:41 -070068def post_message(commit, gerrit_user, gerrit_ssh_key, message_file):
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +000069 """Post a welcome message on the patch set specified by the commit."""
Tom Fifieldd3393472013-11-28 12:27:56 +110070
K Jonathan Harker364eb142014-07-09 17:40:41 -070071 default_text = """Thank you for your first contribution to OpenStack.
Tom Fifieldd3393472013-11-28 12:27:56 +110072
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
Jeremy Stanley76a1a282014-12-05 03:30:42 +000092 Workflow: http://docs.openstack.org/infra/manual/developers.html
K Jonathan Harker5935b672014-07-09 16:54:00 -070093 Commit Messages: https://wiki.openstack.org/wiki/GitCommitMessages
Tom Fifieldd3393472013-11-28 12:27:56 +110094 """
K Jonathan Harker364eb142014-07-09 17:40:41 -070095
96 if message_file:
97 try:
98 with open(message_file, 'r') as _file:
99 welcome_text = _file.read()
100 except (OSError, IOError):
101 logger.exception("Could not open message file")
102 welcome_text = default_text
103 else:
104 welcome_text = default_text
105
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +0000106 # post the above message, using ssh.
107 command = ('gerrit review '
108 '--message="{message}" {commit}').format(
109 message=welcome_text,
110 commit=commit)
111 logger.info('Welcoming: %s', commit)
112 ssh = paramiko.SSHClient()
113 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
114 ssh.connect('localhost', username=gerrit_user,
115 key_filename=gerrit_ssh_key, port=29418)
116 stdin, stdout, stderr = ssh.exec_command(command)
117 stdout_text = stdout.read()
118 stderr_text = stderr.read()
119 ssh.close()
120 if stdout_text:
121 logger.debug('stdout: %s' % stdout_text)
122 if stderr_text:
123 logger.error('stderr: %s' % stderr_text)
Tom Fifieldd3393472013-11-28 12:27:56 +1100124
125
126def main():
127 parser = argparse.ArgumentParser()
128 parser.add_argument('hook')
129 # common
130 parser.add_argument('--change', default=None)
131 parser.add_argument('--change-url', default=None)
132 parser.add_argument('--project', default=None)
133 parser.add_argument('--branch', default=None)
134 parser.add_argument('--commit', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800135 parser.add_argument('--topic', default=None)
Khai Dobb2eed52015-04-14 15:17:31 -0700136 parser.add_argument('--change-owner', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100137 # change-merged
138 parser.add_argument('--submitter', default=None)
139 # patchset-created
140 parser.add_argument('--uploader', default=None)
141 parser.add_argument('--patchset', default=None)
Khai Do335ef392014-01-28 20:45:04 -0800142 parser.add_argument('--is-draft', default=None)
Khai Dobb2eed52015-04-14 15:17:31 -0700143 parser.add_argument('--kind', default=None)
Tom Fifieldd3393472013-11-28 12:27:56 +1100144 # for Welcome Message
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +0000145 parser.add_argument('--ssh-user', dest='ssh_user',
146 help='The gerrit welcome message user')
147 parser.add_argument('--ssh-key', dest='ssh_key',
148 help='The gerrit welcome message SSH key file')
K Jonathan Harker364eb142014-07-09 17:40:41 -0700149 parser.add_argument('--message-file', dest='message_file', default=None,
150 help='The gerrit welcome message')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800151 # Don't actually post the message
152 parser.add_argument('--dryrun', dest='dryrun', action='store_true')
153 parser.add_argument('--no-dryrun', dest='dryrun', action='store_false')
Jeremy Stanley6cfc9ea2014-02-25 14:56:09 +0000154 parser.add_argument('-v', '--verbose', dest='verbose', action='store_true',
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800155 help='verbose output')
Tom Fifieldafc6c242013-12-13 08:50:43 +0800156 parser.set_defaults(dryrun=False)
Tom Fifieldd3393472013-11-28 12:27:56 +1100157
158 args = parser.parse_args()
159
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800160 if args.verbose:
K Jonathan Harker40639372014-07-30 16:34:02 -0700161 logging.basicConfig(level=logging.DEBUG,
Jonathan Harker002e1522014-08-03 14:48:59 -0700162 format='%(asctime)-6s: %(name)s - %(levelname)s'
163 ' - %(message)s')
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800164 else:
K Jonathan Harker40639372014-07-30 16:34:02 -0700165 logging.basicConfig(level=logging.ERROR,
Jonathan Harker002e1522014-08-03 14:48:59 -0700166 format='%(asctime)-6s: %(name)s - %(levelname)s'
167 ' - %(message)s')
James E. Blairfdc8b5d2014-02-10 09:56:28 -0800168
Tom Fifieldd3393472013-11-28 12:27:56 +1100169 # they're a first-timer, post the message on 1st patchset
Jeremy Stanleyaaaf1c72014-03-18 02:14:55 +0000170 if is_newbie(args.uploader) and args.patchset == '1' and not args.dryrun:
K Jonathan Harker364eb142014-07-09 17:40:41 -0700171 post_message(args.commit, args.ssh_user, args.ssh_key,
172 args.message_file)
Tom Fifieldd3393472013-11-28 12:27:56 +1100173
174if __name__ == "__main__":
175 main()