Gerrit Project Builder Tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
6.4 KiB

#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is designed to be called by a gerrit hook. It searched new
# patchsets for those from a first time commiter, then posts a helpful
# message welcoming them to the community and explaining the review process
# For example, this might be called as follows
# python --change Ia1fea1eab3976f1a9cb89ceb3ce1c6c6a7e79c42
# --change-url \ --project gtest-org/test \
# --branch master --uploader User A. Example ( --commit \
# 05508ae633852469d2fd7786a3d6f1d06f87055b --patchset 1 patchset-merged \
# --ssh-user=user --ssh-key=/home/user/.ssh/id_rsa
# and if this was the first commit from "", a message
# would be posted on review 81.
import argparse
import logging
import paramiko
import jeepyb.gerritdb
import jeepyb.log
logger = logging.getLogger('welcome_reviews')
def is_newbie(uploader):
"""Determine if the owner of the patch is a first-timer."""
# Retrieve uploader email
searchkey = uploader[uploader.rindex("(") + 1:-1]
except ValueError:'Couldnt get email for %s', uploader)
return False
# this query looks for all distinct patchsets for the given
# user. If there's only 1, they're a first-timer.
query = """SELECT COUNT(DISTINCT p.change_id + p.patch_set_id)
FROM patch_sets p, account_external_ids a
WHERE a.email_address = %s
AND a.account_id = p.uploader_account_id;"""
cursor = jeepyb.gerritdb.connect().cursor()
cursor.execute(query, searchkey)
data = cursor.fetchone()
if data:
if data[0] == 1:'We found a newbie: %s', uploader)
return True
return False
def post_message(commit, gerrit_user, gerrit_ssh_key, message_file):
"""Post a welcome message on the patch set specified by the commit."""
default_text = """\
Congratulations, you've proposed your first change in OpenDev.
Your submission will now be tested automatically by Zuul, our gatekeeper,
and reviewed by other friendly developers. They will give you feedback and
may require you to refine it.
People seldom get their patch approved on the first try, so don't be
concerned if requested to make corrections. Feel free to modify your patch
and resubmit a new change-set.
Patches often take days (and sometimes weeks) to get reviewed, so be
patient. Don't hesitate to ask for help, and answer questions about your
work promptly if you can. The more you get to know reviewers and get to be
known by them, the smoother the review and approval process will become. The
fastest way to accomplish this is by reviewing other proposed changes
yourself: anybody can do it, and it's a great way to learn the code base.
Thanks again for participating in OpenDev, we look forward to seeing you
Workflow Guide:
if message_file:
with open(message_file, 'r') as _file:
welcome_text =
except (OSError, IOError):
logger.exception("Could not open message file")
welcome_text = default_text
welcome_text = default_text
# post the above message, using ssh.
command = ('gerrit review '
'--message="{message}" {commit}').format(
commit=commit)'Welcoming: %s', commit)
ssh = paramiko.SSHClient()
ssh.connect('localhost', username=gerrit_user,
key_filename=gerrit_ssh_key, port=29418)
stdin, stdout, stderr = ssh.exec_command(command)
stdout_text =
stderr_text =
if stdout_text:
logger.debug('stdout: %s' % stdout_text)
if stderr_text:
logger.error('stderr: %s' % stderr_text)
def main():
parser = argparse.ArgumentParser()
# common
parser.add_argument('--change', default=None)
parser.add_argument('--change-url', default=None)
parser.add_argument('--project', default=None)
parser.add_argument('--branch', default=None)
parser.add_argument('--commit', default=None)
parser.add_argument('--topic', default=None)
parser.add_argument('--change-owner', default=None)
# patchset-abandoned
parser.add_argument('--abandoner', default=None)
parser.add_argument('--reason', default=None)
# change-merged
parser.add_argument('--submitter', default=None)
parser.add_argument('--newrev', default=None)
# patchset-created
parser.add_argument('--uploader', default=None)
parser.add_argument('--patchset', default=None)
parser.add_argument('--is-draft', default=None)
parser.add_argument('--kind', default=None)
# for Welcome Message
parser.add_argument('--ssh-user', dest='ssh_user',
help='The gerrit welcome message user')
parser.add_argument('--ssh-key', dest='ssh_key',
help='The gerrit welcome message SSH key file')
parser.add_argument('--message-file', dest='message_file', default=None,
help='The gerrit welcome message')
# Don't actually post the message
parser.add_argument('--dryrun', dest='dryrun', action='store_true')
parser.add_argument('--no-dryrun', dest='dryrun', action='store_false')
args = parser.parse_args()
# they're a first-timer, post the message on 1st patchset
if is_newbie(args.uploader) and args.patchset == '1' and not args.dryrun:
post_message(args.commit, args.ssh_user, args.ssh_key,
if __name__ == "__main__":