Improve git2lp and is_direct_release behaviour

* git2lp and is_direct_release are now functions extracted to the projects.py;
* git2lp and is_direct_release mappings are now loaded from projects.yaml;
* temporarily old mappings are used if no info found in projects.yaml.

Fixes: bug #1202820
Fixes: bug #1202800
Fixes: bug #1082792

Change-Id: I487761d110cf781acea26b997486ea24a7deb25e
This commit is contained in:
Sergey Lukjanov 2013-09-10 00:41:20 +04:00
parent 268f92f0c6
commit 32a6775fd5
4 changed files with 256 additions and 119 deletions

View File

@ -28,6 +28,9 @@ from launchpadlib import launchpad
from launchpadlib import uris
import MySQLdb
from jeepyb import projects as p
BASE_DIR = '/home/gerrit2/review_site'
GERRIT_CACHE_DIR = os.path.expanduser(
os.environ.get('GERRIT_CACHE_DIR',
@ -63,22 +66,11 @@ DB_PASS = SECURE_CONFIG.get("database", "password")
DB_DB = GERRIT_CONFIG.get("database", "database")
def short_project(full_project_name):
"""Return the project part of the git repository name."""
return full_project_name.split('/')[-1]
def git2lp(full_project_name):
"""Convert Git repo name to Launchpad project."""
project_map = {
'stackforge/puppet-openstack_dev_env': 'puppet-openstack',
'stackforge/puppet-quantum': 'puppet-neutron',
}
return project_map.get(full_project_name, short_project(full_project_name))
def update_spec(launchpad, project, name, subject, link, topic=None):
project = git2lp(project)
if p.is_no_launchpad_blueprints(project):
return
project = p.git2lp(project)
spec = launchpad.projects[project].getSpecification(name=name)
if not spec:
return

View File

@ -26,6 +26,9 @@ from launchpadlib import launchpad
from launchpadlib import uris
import jeepyb.gerritdb
from jeepyb import projects as p
from jeepyb import utils as u
BASE_DIR = '/home/gerrit2/review_site'
GERRIT_CACHE_DIR = os.path.expanduser(
@ -46,7 +49,8 @@ def fix_or_related_fix(related):
def add_change_proposed_message(bugtask, change_url, project, branch,
related=False):
fix = fix_or_related_fix(related)
subject = '%s proposed to %s (%s)' % (fix, short_project(project), branch)
subject = ('%s proposed to %s (%s)'
% (fix, u.short_project_name(project), branch))
body = '%s proposed to branch: %s\nReview: %s' % (fix, branch, change_url)
bugtask.bug.newMessage(subject=subject, content=body)
@ -54,7 +58,7 @@ def add_change_proposed_message(bugtask, change_url, project, branch,
def add_change_merged_message(bugtask, change_url, project, commit,
submitter, branch, git_log, related=False):
subject = '%s merged to %s (%s)' % (fix_or_related_fix(related),
short_project(project), branch)
u.short_project_name(project), branch)
git_url = 'http://github.com/%s/commit/%s' % (project, commit)
body = '''Reviewed: %s
Committed: %s
@ -140,106 +144,6 @@ def tag_in_branchname(bugtask, branch):
lp_bug.lp_save()
def short_project(full_project_name):
"""Return the project part of the git repository name."""
return full_project_name.split('/')[-1]
def git2lp(full_project_name):
"""Convert Git repo name to Launchpad project."""
project_map = {
'openstack/api-site': 'openstack-api-site',
'openstack/identity-api': 'openstack-api-site',
'openstack/object-api': 'openstack-api-site',
'openstack/volume-api': 'openstack-api-site',
'openstack/netconn-api': 'openstack-api-site',
'openstack/compute-api': 'openstack-api-site',
'openstack/image-api': 'openstack-api-site',
'openstack/database-api': 'openstack-api-site',
'openstack/quantum': 'neutron',
'openstack/python-quantumclient': 'python-neutronclient',
'openstack/oslo-incubator': 'oslo',
'openstack/tripleo-incubator': 'tripleo',
'openstack-infra/askbot-theme': 'openstack-ci',
'openstack-infra/config': 'openstack-ci',
'openstack-infra/devstack-gate': 'openstack-ci',
'openstack-infra/gear': 'openstack-ci',
'openstack-infra/gerrit': 'openstack-ci',
'openstack-infra/gerritbot': 'openstack-ci',
'openstack-infra/gerritlib': 'openstack-ci',
'openstack-infra/gitdm': 'openstack-ci',
'openstack-infra/jeepyb': 'openstack-ci',
'openstack-infra/jenkins-job-builder': 'openstack-ci',
'openstack-infra/lodgeit': 'openstack-ci',
'openstack-infra/meetbot': 'openstack-ci',
'openstack-infra/nose-html-output': 'openstack-ci',
'openstack-infra/publications': 'openstack-ci',
'openstack-infra/puppet-apparmor': 'openstack-ci',
'openstack-infra/puppet-dashboard': 'openstack-ci',
'openstack-infra/puppet-vcsrepo': 'openstack-ci',
'openstack-infra/reviewday': 'openstack-ci',
'openstack-infra/statusbot': 'openstack-ci',
'openstack-infra/zmq-event-publisher': 'openstack-ci',
'stackforge/cookbook-openstack-block-storage': 'openstack-chef',
'stackforge/cookbook-openstack-common': 'openstack-chef',
'stackforge/cookbook-openstack-compute': 'openstack-chef',
'stackforge/cookbook-openstack-dashboard': 'openstack-chef',
'stackforge/cookbook-openstack-identity': 'openstack-chef',
'stackforge/cookbook-openstack-image': 'openstack-chef',
'stackforge/cookbook-openstack-metering': 'openstack-chef',
'stackforge/cookbook-openstack-network': 'openstack-chef',
'stackforge/cookbook-openstack-object-storage': 'openstack-chef',
'stackforge/cookbook-openstack-ops-database': 'openstack-chef',
'stackforge/cookbook-openstack-ops-messaging': 'openstack-chef',
'stackforge/cookbook-openstack-orchestration': 'openstack-chef',
'stackforge/openstack-chef-repo': 'openstack-chef',
'stackforge/puppet-openstack_dev_env': 'puppet-openstack',
'stackforge/puppet-quantum': 'puppet-neutron',
'stackforge/tripleo-heat-templates': 'tripleo',
'stackforge/tripleo-image-elements': 'tripleo',
}
return project_map.get(full_project_name, short_project(full_project_name))
def is_direct_release(full_project_name):
"""Test against a list of projects who directly release changes."""
return full_project_name in [
'openstack/openstack-manuals',
'openstack/api-site',
'openstack/tripleo-incubator',
'openstack/tempest',
'openstack-dev/devstack',
'openstack-infra/askbot-theme',
'openstack-infra/config',
'openstack-infra/devstack-gate',
'openstack-infra/gerrit',
'openstack-infra/gerritbot',
'openstack-infra/gerritlib',
'openstack-infra/gitdm',
'openstack-infra/lodgeit',
'openstack-infra/meetbot',
'openstack-infra/nose-html-output',
'openstack-infra/publications',
'openstack-infra/reviewday',
'openstack-infra/statusbot',
'stackforge/cookbook-openstack-block-storage',
'stackforge/cookbook-openstack-common',
'stackforge/cookbook-openstack-compute',
'stackforge/cookbook-openstack-dashboard',
'stackforge/cookbook-openstack-identity',
'stackforge/cookbook-openstack-image',
'stackforge/cookbook-openstack-metering',
'stackforge/cookbook-openstack-network',
'stackforge/cookbook-openstack-object-storage',
'stackforge/cookbook-openstack-ops-database',
'stackforge/cookbook-openstack-ops-messaging',
'stackforge/cookbook-openstack-orchestration',
'stackforge/openstack-chef-repo',
'stackforge/tripleo-heat-templates',
'stackforge/tripleo-image-elements',
]
class Task:
def __init__(self, lp_task, prefix):
'''Prefixes associated with bug references will allow for certain
@ -291,7 +195,7 @@ def process_bugtask(launchpad, task, git_log, args):
if args.hook == "change-merged":
if args.branch == 'master':
if (is_direct_release(args.project) and
if (p.is_direct_release(args.project) and
task.needs_change('set_fix_released')):
set_fix_released(bugtask)
else:
@ -362,6 +266,13 @@ def find_bugs(launchpad, git_log, args):
:returns: an iterable containing Task objects.
'''
project = args.project
if p.is_no_launchpad_bugs(project):
return []
project = p.git2lp(project)
part1 = r'^[\t ]*(?P<prefix>[-\w]+)?[\s:]*'
part2 = r'(?:\b(?:bug|lp)\b[\s#:]*)+'
part3 = r'(?P<bug_number>\d+)\s*?$'
@ -377,7 +288,7 @@ def find_bugs(launchpad, git_log, args):
try:
lp_bug = launchpad.bugs[bug_num]
for lp_task in lp_bug.bug_tasks:
if lp_task.bug_target_name == git2lp(args.project):
if lp_task.bug_target_name == project:
bugtasks[bug_num] = Task(lp_task, prefix)
break
except KeyError:
@ -424,5 +335,6 @@ def main():
for task in find_bugs(lpconn, git_log, args):
process_bugtask(lpconn, task, git_log, args)
if __name__ == "__main__":
main()

186
jeepyb/projects.py Normal file
View File

@ -0,0 +1,186 @@
# Copyright (c) 2013 Mirantis.
#
# 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
"""
Expected review.projects.yaml format:
- project: some/project
launchpad: awesomeproject
description: Best project ever.
options:
- direct-release
- no-launchpad-bugs
- no-launchpad-blueprints
"""
import jeepyb.utils as u
registry = u.ProjectsYamlRegistry('/home/gerrit2/projects.yaml',
'PROJECTS_YAML')
def git2lp(project_full_name):
try:
return registry[project_full_name]['launchpad']
except KeyError:
return _hardcoded_git2lp(project_full_name)
# return u.short_project_name(project_full_name)
def _is_no_launchpad(project_full_name, obj_type):
try:
return ('no-launchpad-' + obj_type
in registry[project_full_name]['options'])
except KeyError:
return False
def is_no_launchpad_bugs(project_full_name):
return _is_no_launchpad(project_full_name, 'bugs')
def is_no_launchpad_blueprints(project_full_name):
return _is_no_launchpad(project_full_name, 'blueprints')
def is_direct_release(project_full_name):
try:
direct = 'direct-release' in registry[project_full_name]['options']
# return ...
except KeyError:
direct = False
# return False
return direct or _hardcoded_is_direct_release(project_full_name)
# The following functions should be deleted when projects.yaml will be updated
def _hardcoded_is_direct_release(project_full_name):
"""Test against a list of projects who directly release changes.
This function should be removed when projects.yaml will be updated.
To specify direct_release you just need add option 'direct_relese' to your
project declaration in projects.yaml
Example:
- project: some/project
options:
- direct-release
description: Best project ever.
"""
return project_full_name in [
'openstack/openstack-manuals',
'openstack/api-site',
'openstack/tripleo-incubator',
'openstack/tempest',
'openstack-dev/devstack',
'openstack-infra/askbot-theme',
'openstack-infra/config',
'openstack-infra/devstack-gate',
'openstack-infra/gerrit',
'openstack-infra/gerritbot',
'openstack-infra/gerritlib',
'openstack-infra/gitdm',
'openstack-infra/lodgeit',
'openstack-infra/meetbot',
'openstack-infra/nose-html-output',
'openstack-infra/publications',
'openstack-infra/reviewday',
'openstack-infra/statusbot',
'stackforge/cookbook-openstack-block-storage',
'stackforge/cookbook-openstack-common',
'stackforge/cookbook-openstack-compute',
'stackforge/cookbook-openstack-dashboard',
'stackforge/cookbook-openstack-identity',
'stackforge/cookbook-openstack-image',
'stackforge/cookbook-openstack-metering',
'stackforge/cookbook-openstack-network',
'stackforge/cookbook-openstack-object-storage',
'stackforge/cookbook-openstack-ops-database',
'stackforge/cookbook-openstack-ops-messaging',
'stackforge/cookbook-openstack-orchestration',
'stackforge/openstack-chef-repo',
'stackforge/tripleo-heat-templates',
'stackforge/tripleo-image-elements',
]
def _hardcoded_git2lp(project_full_name):
"""Convert Git repo name to Launchpad project.
This function should be removed when projects.yaml will be updated.
To specify launchpad project name you just need add parameter 'lp' to your
project declaration in projects.yaml
Example:
- project: some/project
launchpad: awesomeproject
description: Best project ever.
"""
project_map = {
'openstack/api-site': 'openstack-api-site',
'openstack/identity-api': 'openstack-api-site',
'openstack/object-api': 'openstack-api-site',
'openstack/volume-api': 'openstack-api-site',
'openstack/netconn-api': 'openstack-api-site',
'openstack/compute-api': 'openstack-api-site',
'openstack/image-api': 'openstack-api-site',
'openstack/database-api': 'openstack-api-site',
'openstack/quantum': 'neutron',
'openstack/python-quantumclient': 'python-neutronclient',
'openstack/oslo-incubator': 'oslo',
'openstack/tripleo-incubator': 'tripleo',
'openstack-infra/askbot-theme': 'openstack-ci',
'openstack-infra/config': 'openstack-ci',
'openstack-infra/devstack-gate': 'openstack-ci',
'openstack-infra/gear': 'openstack-ci',
'openstack-infra/gerrit': 'openstack-ci',
'openstack-infra/gerritbot': 'openstack-ci',
'openstack-infra/gerritlib': 'openstack-ci',
'openstack-infra/gitdm': 'openstack-ci',
'openstack-infra/jeepyb': 'openstack-ci',
'openstack-infra/jenkins-job-builder': 'openstack-ci',
'openstack-infra/lodgeit': 'openstack-ci',
'openstack-infra/meetbot': 'openstack-ci',
'openstack-infra/nose-html-output': 'openstack-ci',
'openstack-infra/publications': 'openstack-ci',
'openstack-infra/puppet-apparmor': 'openstack-ci',
'openstack-infra/puppet-dashboard': 'openstack-ci',
'openstack-infra/puppet-vcsrepo': 'openstack-ci',
'openstack-infra/reviewday': 'openstack-ci',
'openstack-infra/statusbot': 'openstack-ci',
'openstack-infra/zmq-event-publisher': 'openstack-ci',
'stackforge/cookbook-openstack-block-storage': 'openstack-chef',
'stackforge/cookbook-openstack-common': 'openstack-chef',
'stackforge/cookbook-openstack-compute': 'openstack-chef',
'stackforge/cookbook-openstack-dashboard': 'openstack-chef',
'stackforge/cookbook-openstack-identity': 'openstack-chef',
'stackforge/cookbook-openstack-image': 'openstack-chef',
'stackforge/cookbook-openstack-metering': 'openstack-chef',
'stackforge/cookbook-openstack-network': 'openstack-chef',
'stackforge/cookbook-openstack-object-storage': 'openstack-chef',
'stackforge/cookbook-openstack-ops-database': 'openstack-chef',
'stackforge/cookbook-openstack-ops-messaging': 'openstack-chef',
'stackforge/cookbook-openstack-orchestration': 'openstack-chef',
'stackforge/openstack-chef-repo': 'openstack-chef',
'stackforge/puppet-openstack_dev_env': 'puppet-openstack',
'stackforge/puppet-quantum': 'puppet-neutron',
'stackforge/tripleo-heat-templates': 'tripleo',
'stackforge/tripleo-image-elements': 'tripleo',
}
return project_map.get(project_full_name,
u.short_project_name(project_full_name))

47
jeepyb/utils.py Normal file
View File

@ -0,0 +1,47 @@
# Copyright (c) 2013 Mirantis.
#
# 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# 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.
import os
import yaml
def short_project_name(full_project_name):
"""Return the project part of the git repository name."""
return full_project_name.split('/')[-1]
class ProjectsYamlRegistry(object):
"""review.projects.yaml style config file parser.
It could be used as dict 'project name' -> 'project properties'.
"""
def __init__(self, file_path, env_name=None):
self.file_path = file_path
self.env_name = env_name
self._parse_file()
def _parse_file(self):
file_path = os.environ.get(self.env_name, self.file_path)
configs_list = [config for config in yaml.load_all(open(file_path))][1]
configs = {}
for section in configs_list:
configs[section['project']] = section
self.configs = configs
def __getitem__(self, item):
return self.configs[item]