diff --git a/manifests/site.pp b/manifests/site.pp index 5d99d12a17..bc0cb6a788 100644 --- a/manifests/site.pp +++ b/manifests/site.pp @@ -43,8 +43,20 @@ class openstack_jenkins_slave { # # Long lived servers: # -node "gerrit.openstack.org", "gerrit-dev.openstack.org" { +node "gerrit.openstack.org" { include openstack_server + class { 'gerrit': + canonicalweburl => "https://review.openstack.org/", + email => "review@openstack.org", + } +} + +node "gerrit-dev.openstack.org" { + include openstack_server + class { 'gerrit': + canonicalweburl => "https://review-dev.openstack.org/", + email => "review-dev@openstack.org", + } } node "docs.openstack.org" { diff --git a/modules/gerrit/files/change-merged b/modules/gerrit/files/change-merged new file mode 100755 index 0000000000..9c8c6c4438 --- /dev/null +++ b/modules/gerrit/files/change-merged @@ -0,0 +1,174 @@ +#!/usr/bin/env python +# +# Gerrit-Launchpad Hook, inspired by https://github.com/hobbs/jirret +# +# Copyright (C) 2011 Catalyst IT (http://www.catalyst.net.nz) +# Copyright (C) 2011 Rackspace US, Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Changed by James E. Blair to add +# config file parsing, and signed email with commands. + +# Some parts: +# Copyright 2009-2011 Canonical Ltd. This software is licensed under the +# GNU Affero General Public License version 3 (see the file LICENSE). + +from email.mime.text import MIMEText +from getopt import getopt +import re +import smtplib +import subprocess +import sys, os +import pyme, pyme.core +import StringIO +import ConfigParser + +TO_ADDRESS_SUFFIX = '@bugs.launchpad.net' +BASE_DIR = '/home/gerrit2/review_site' +GERRIT_CONFIG = os.environ.get('GERRIT_CONFIG','/home/gerrit2/review_site/etc/gerrit.config') + +def get_broken_config(filename): + """ gerrit config ini files are broken and have leading tabs """ + text = "" + with open(filename,"r") as conf: + for line in conf.readlines(): + text = "%s%s" % (text, line.lstrip()) + + fp = StringIO.StringIO(text) + c=ConfigParser.ConfigParser() + c.readfp(fp) + return c + +gerrit_config = get_broken_config(GERRIT_CONFIG) +FROM_ADDRESS = gerrit_config.get('user', 'email') + + +# From Launchpad: lib/lp/services/mail/incoming.py +# Match '\n' and '\r' line endings. That is, all '\r' that are not +# followed by a '\n', and all '\n' that are not preceded by a '\r'. +non_canonicalised_line_endings = re.compile('((?>> canonicalise_line_endings('\n\nfoo\nbar\rbaz\r\n') + '\r\n\r\nfoo\r\nbar\r\nbaz\r\n' + + >>> canonicalise_line_endings('\r\rfoo\r\nbar\rbaz\n') + '\r\n\r\nfoo\r\nbar\r\nbaz\r\n' + + >>> canonicalise_line_endings('\r\nfoo\r\nbar\nbaz\r') + '\r\nfoo\r\nbar\r\nbaz\r\n' + """ + if non_canonicalised_line_endings.search(text): + text = non_canonicalised_line_endings.sub('\r\n', text) + if trailing_whitespace.search(text): + text = trailing_whitespace.sub('', text) + return text +# End code from Launchpad: lib/lp/services/mail/incoming.py + +def email_tracker(change_url, project, branch, submitter, commit): + # Extract git log of all merged commits + git_log = subprocess.Popen(['git', '--git-dir=' + BASE_DIR + '/git/' + project + '.git', 'log', '--no-merges', commit + '^1..' + commit], stdout=subprocess.PIPE).communicate()[0] + + # Find bug numbers referenced in the git log + bug_regexp = r'([Bb]ug|[Ll][Pp])\s*[#:]?\s*(\d+)' + tokens = re.split(bug_regexp, git_log) + + # Extract unique bug numbers + bugs = [] + for token in tokens: + if re.match('^\d+$', token) and (token not in bugs): + bugs.append(token) + send_bug_mail(token, change_url, project, commit, submitter, branch, git_log) + +def send_bug_mail(bug_number, change_url, project, commit, submitter, branch, git_log): + + to_address = bug_number + TO_ADDRESS_SUFFIX + + gitorious_url = 'http://github.com/%s/commit/%s' % (project, commit) + body = '''Reviewed: %s +Committed: %s +Submitter: %s +Branch: %s + + status fixcommitted + done\n''' % (change_url, gitorious_url, submitter, branch) + + body = body + '\n' + git_log + + bodypart = MIMEText(body) + bodystring = bodypart.as_string() + bodystring = canonicalise_line_endings(bodystring) + + plain = pyme.core.Data(bodystring) + cipher = pyme.core.Data() + gpg = pyme.core.Context() + gpg.set_armor(1) + + gpg.op_keylist_start(FROM_ADDRESS, 0) + gpg.op_sign(plain, cipher, pyme.pygpgme.GPGME_SIG_MODE_DETACH) + cipher.seek(0,0) + signature = cipher.read() + + from email.mime.multipart import MIMEMultipart + from email.mime.base import MIMEBase + msg = MIMEMultipart(_subtype='signed',protocol='application/pgp-signature') + msg['Subject'] = 'A change has been merged to %s' % project + msg['From'] = FROM_ADDRESS + msg['To'] = to_address + + msg.attach(bodypart) + signpart = MIMEBase('application','pgp-signature') + signpart.set_payload(signature) + msg.attach(signpart) + + #print msg.as_string() + s = smtplib.SMTP() + s.connect() + s.sendmail(FROM_ADDRESS, [to_address], msg.as_string()) + s.quit() + +def main(): + # https://gerrit.googlecode.com/svn/documentation/2.1.6/config-hooks.html#change-merged + gerrit_args = ['change=', 'change-url=', 'project=', 'branch=', 'submitter=', 'commit='] + args, unused = getopt(sys.argv[1:], '', gerrit_args) + + change_url = project = branch = submitter = commit = None + for argname, argv in args: + if argname == '--change-url': + change_url = argv + elif argname == '--project': + project = argv + elif argname == '--branch': + branch = argv + elif argname == '--submitter': + submitter = argv + elif argname == '--commit': + commit = argv + + if change_url and project and branch and submitter and commit: + email_tracker(change_url, project, branch, submitter, commit) + else: + print 'Missing arguments' + return 1 + + return 0; + +if __name__ == '__main__': + sys.exit(main()) diff --git a/modules/gerrit/files/replication.config b/modules/gerrit/files/replication.config new file mode 100644 index 0000000000..ebb5978f2f --- /dev/null +++ b/modules/gerrit/files/replication.config @@ -0,0 +1,5 @@ +# This file is managed by puppet. +# https://github.com/openstack/openstack-ci-puppet + +[remote "github"] +url = git@github.com:${name}.git diff --git a/modules/gerrit/lib/facter/gerrit_installed.rb b/modules/gerrit/lib/facter/gerrit_installed.rb new file mode 100644 index 0000000000..b3ec1019bc --- /dev/null +++ b/modules/gerrit/lib/facter/gerrit_installed.rb @@ -0,0 +1,5 @@ +Facter.add("gerrit_installed") do + setcode do + FileTest.directory?("/home/gerrit2/review_site/") + end +end diff --git a/modules/gerrit/manifests/init.pp b/modules/gerrit/manifests/init.pp new file mode 100644 index 0000000000..90b32694d3 --- /dev/null +++ b/modules/gerrit/manifests/init.pp @@ -0,0 +1,43 @@ +class gerrit($canonicalweburl='', + $openidssourl="https://login.launchpad.net/+openid", + $email='', + $commentlinks = [ { name => 'launchpad', + match => '([Bb]ug|[Ll][Pp])\\s*[#:]?\\s*(\\d+)', + link => 'https://code.launchpad.net/bugs/$2' } ] + ) { + + if $gerrit_installed { + #notice('Gerrit is installed') + + file { '/home/gerrit2/review_site/etc/replication.config': + owner => 'root', + group => 'root', + mode => 444, + ensure => 'present', + source => 'puppet:///modules/gerrit/replication.config', + replace => 'true', + } + + file { '/home/gerrit2/review_site/etc/gerrit.config': + owner => 'root', + group => 'root', + mode => 444, + ensure => 'present', + content => template('gerrit/gerrit.config.erb'), + replace => 'true', + } + + file { '/home/gerrit2/review_site/hooks/change-merged': + owner => 'root', + group => 'root', + mode => 555, + ensure => 'present', + source => 'puppet:///modules/gerrit/change-merged', + replace => 'true', + } + + } else { + notice('Gerrit is not installed') + } + +} diff --git a/modules/gerrit/templates/gerrit.config.erb b/modules/gerrit/templates/gerrit.config.erb new file mode 100644 index 0000000000..afcca23c21 --- /dev/null +++ b/modules/gerrit/templates/gerrit.config.erb @@ -0,0 +1,32 @@ +# This file is managed by puppet. +# https://github.com/openstack/openstack-ci-puppet + +[gerrit] + basePath = git + canonicalWebUrl = <%= canonicalweburl %> +[database] + type = MYSQL + hostname = localhost + database = reviewdb + username = gerrit2 +[auth] + type = OPENID_SSO + openIdSsoUrl = <%= openidssourl %> +[sendemail] + smtpServer = localhost +[container] + user = gerrit2 + javaHome = /usr/lib/jvm/java-6-openjdk/jre +[sshd] + listenAddress = *:29418 +[httpd] + listenUrl = proxy-https://*:8081/ +[cache] + directory = cache +[user] + email = <%= email %> +<% commentlinks.each do |commentlink| -%> +[commentlink "<%= commentlink['name'] %>"] + match = "<%= commentlink['match'] %>" + link = "<%= commentlink['link'] %>" +<% end -%> \ No newline at end of file