blob: 9c18f1d4f9189b655144ae851e83ed9519fce2ca [file] [log] [blame]
Monty Taylorf45f6ca2012-05-01 17:11:48 -04001#!/usr/bin/env python
2# Copyright (c) 2011 OpenStack, LLC.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
16# This is designed to be called by a gerrit hook. It searched new
17# patchsets for strings like "blueprint FOO" or "bp FOO" and updates
18# corresponding Launchpad blueprints with links back to the change.
19
20from launchpadlib.launchpad import Launchpad
21from launchpadlib.uris import LPNET_SERVICE_ROOT
22import os
23import argparse
24import re
25import subprocess
26
27import StringIO
28import ConfigParser
29import MySQLdb
30
31BASE_DIR = '/home/gerrit2/review_site'
32GERRIT_CACHE_DIR = os.path.expanduser(os.environ.get('GERRIT_CACHE_DIR',
33 '~/.launchpadlib/cache'))
34GERRIT_CREDENTIALS = os.path.expanduser(os.environ.get('GERRIT_CREDENTIALS',
35 '~/.launchpadlib/creds'))
36GERRIT_CONFIG = os.environ.get('GERRIT_CONFIG',
37 '/home/gerrit2/review_site/etc/gerrit.config')
38GERRIT_SECURE_CONFIG = os.environ.get('GERRIT_SECURE_CONFIG',
39 '/home/gerrit2/review_site/etc/secure.config')
40SPEC_RE = re.compile(r'(blueprint|bp)\s*[#:]?\s*(\S+)', re.I)
41BODY_RE = re.compile(r'^\s+.*$')
42
43def get_broken_config(filename):
44 """ gerrit config ini files are broken and have leading tabs """
45 text = ""
46 with open(filename,"r") as conf:
47 for line in conf.readlines():
48 text = "%s%s" % (text, line.lstrip())
49
50 fp = StringIO.StringIO(text)
51 c=ConfigParser.ConfigParser()
52 c.readfp(fp)
53 return c
54
55GERRIT_CONFIG = get_broken_config(GERRIT_CONFIG)
56SECURE_CONFIG = get_broken_config(GERRIT_SECURE_CONFIG)
57DB_USER = GERRIT_CONFIG.get("database", "username")
58DB_PASS = SECURE_CONFIG.get("database","password")
59DB_DB = GERRIT_CONFIG.get("database","database")
60
61def update_spec(launchpad, project, name, subject, link, topic=None):
62 # For testing, if a project doesn't match openstack/foo, use
63 # the openstack-ci project instead.
64 group, project = project.split('/')
65 if group != 'openstack':
66 project = 'openstack-ci'
67
68 spec = launchpad.projects[project].getSpecification(name=name)
69 if not spec: return
70
71 if spec.whiteboard:
72 wb = spec.whiteboard.strip()
73 else:
74 wb = ''
75 changed = False
76 if topic:
77 topiclink = '%s/#q,topic:%s,n,z' % (link[:link.find('/',8)],
78 topic)
79 if topiclink not in wb:
80 wb += "\n\n\nGerrit topic: %(link)s" % dict(link=topiclink)
81 changed = True
82
83 if link not in wb:
84 wb += "\n\n\nAddressed by: %(link)s\n %(subject)s\n" % dict(subject=subject,
85 link=link)
86 changed = True
87
88 if changed:
89 spec.whiteboard = wb
90 spec.lp_save()
91
92def find_specs(launchpad, dbconn, args):
93 git_log = subprocess.Popen(['git',
94 '--git-dir=' + BASE_DIR + '/git/' + args.project + '.git',
95 'log', '--no-merges',
96 args.commit + '^1..' + args.commit],
97 stdout=subprocess.PIPE).communicate()[0]
98
99 cur = dbconn.cursor()
100 cur.execute("select subject, topic from changes where change_key=%s", args.change)
101 subject, topic = cur.fetchone()
102 specs = set([m.group(2) for m in SPEC_RE.finditer(git_log)])
103
104 if topic:
105 topicspec = topic.split('/')[-1]
106 specs |= set([topicspec])
107
108 for spec in specs:
109 update_spec(launchpad, args.project, spec, subject,
110 args.change_url, topic)
111
112def main():
113 parser = argparse.ArgumentParser()
114 parser.add_argument('hook')
115 #common
116 parser.add_argument('--change', default=None)
117 parser.add_argument('--change-url', default=None)
118 parser.add_argument('--project', default=None)
119 parser.add_argument('--branch', default=None)
120 parser.add_argument('--commit', default=None)
121 #change-merged
122 parser.add_argument('--submitter', default=None)
123 # patchset-created
124 parser.add_argument('--uploader', default=None)
125 parser.add_argument('--patchset', default=None)
126
127 args = parser.parse_args()
128
129 launchpad = Launchpad.login_with('Gerrit User Sync', LPNET_SERVICE_ROOT,
130 GERRIT_CACHE_DIR,
131 credentials_file = GERRIT_CREDENTIALS,
132 version='devel')
133
134 conn = MySQLdb.connect(user = DB_USER, passwd = DB_PASS, db = DB_DB)
135
136 find_specs(launchpad, conn, args)
137
138if __name__ == '__main__':
139 main()