Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 1 | #!/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 Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 20 | # python welcome_message.py --change Ia1fea1eab3976f1a9cb89ceb3ce1c6c6a7e79c42 |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 21 | # --change-url \ https://review-dev.openstack.org/81 --project gtest-org/test \ |
| 22 | # --branch master --uploader User A. Example (user@example.com) --commit \ |
Jeremy Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 23 | # 05508ae633852469d2fd7786a3d6f1d06f87055b --patchset 1 patchset-merged \ |
| 24 | # --ssh-user=user --ssh-key=/home/user/.ssh/id_rsa |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 25 | # and if this was the first commit from "user@example.com", a message |
| 26 | # would be posted on review 81. |
| 27 | |
| 28 | |
| 29 | import argparse |
| 30 | import logging |
| 31 | import paramiko |
| 32 | |
| 33 | import jeepyb.gerritdb |
| 34 | |
| 35 | BASE_DIR = '/home/gerrit2/review_site' |
| 36 | |
| 37 | logger = logging.getLogger('welcome_reviews') |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 38 | |
| 39 | |
| 40 | def 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 Stanley | ad63ded | 2014-03-06 23:42:15 +0000 | [diff] [blame] | 61 | if data[0] == 1: |
Tom Fifield | afc6c24 | 2013-12-13 08:50:43 +0800 | [diff] [blame] | 62 | logger.info('We found a newbie: %s', uploader) |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 63 | return True |
| 64 | else: |
| 65 | return False |
| 66 | |
| 67 | |
Jeremy Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 68 | def post_message(commit, gerrit_user, gerrit_ssh_key): |
| 69 | """Post a welcome message on the patch set specified by the commit.""" |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 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 | """ |
Jeremy Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 94 | # 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 Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 112 | |
| 113 | |
| 114 | def 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 Do | 335ef39 | 2014-01-28 20:45:04 -0800 | [diff] [blame] | 123 | parser.add_argument('--topic', default=None) |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 124 | # 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 Do | 335ef39 | 2014-01-28 20:45:04 -0800 | [diff] [blame] | 129 | parser.add_argument('--is-draft', default=None) |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 130 | # for Welcome Message |
Jeremy Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 131 | 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 Fifield | afc6c24 | 2013-12-13 08:50:43 +0800 | [diff] [blame] | 135 | # 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 Stanley | 6cfc9ea | 2014-02-25 14:56:09 +0000 | [diff] [blame] | 138 | parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', |
James E. Blair | fdc8b5d | 2014-02-10 09:56:28 -0800 | [diff] [blame] | 139 | help='verbose output') |
Tom Fifield | afc6c24 | 2013-12-13 08:50:43 +0800 | [diff] [blame] | 140 | parser.set_defaults(dryrun=False) |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 141 | |
| 142 | args = parser.parse_args() |
| 143 | |
James E. Blair | fdc8b5d | 2014-02-10 09:56:28 -0800 | [diff] [blame] | 144 | if args.verbose: |
| 145 | logging.basicConfig(level=logging.DEBUG) |
| 146 | else: |
| 147 | logging.basicConfig(level=logging.ERROR) |
| 148 | |
Tom Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 149 | # they're a first-timer, post the message on 1st patchset |
Jeremy Stanley | aaaf1c7 | 2014-03-18 02:14:55 +0000 | [diff] [blame^] | 150 | 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 Fifield | d339347 | 2013-11-28 12:27:56 +1100 | [diff] [blame] | 152 | |
| 153 | if __name__ == "__main__": |
| 154 | main() |