diff --git a/openstack_releases/cmds/list_changes.py b/openstack_releases/cmds/list_changes.py new file mode 100644 index 0000000000..140bcbc0e0 --- /dev/null +++ b/openstack_releases/cmds/list_changes.py @@ -0,0 +1,132 @@ +# All Rights Reserved. +# +# 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. + +"""Show the changes that will be included in the release. +""" + +from __future__ import print_function + +import argparse +import atexit +import os +import os.path +import shutil +import subprocess +import tempfile + +import yaml + +from openstack_releases import defaults +from openstack_releases import gitutils + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--no-cleanup', + dest='cleanup', + default=True, + action='store_false', + help='do not remove temporary files', + ) + parser.add_argument( + 'input', + nargs='*', + help=('YAML files to validate, defaults to ' + 'files changed in the latest commit'), + ) + args = parser.parse_args() + + filenames = args.input or gitutils.find_modified_deliverable_files() + if not filenames: + print('no modified deliverable files, skipping report') + return 0 + + workdir = tempfile.mkdtemp(prefix='releases-') + print('creating temporary files in %s' % workdir) + + def cleanup_workdir(): + if args.cleanup: + try: + shutil.rmtree(workdir) + except: + pass + else: + print('not cleaning up %s' % workdir) + atexit.register(cleanup_workdir) + + # Remove any inherited PAGER environment variable to avoid + # blocking the output waiting for input. + os.environ['PAGER'] = '' + + for filename in filenames: + print('\nChecking %s' % filename) + with open(filename, 'r') as f: + deliverable_info = yaml.load(f.read()) + + series = os.path.basename( + os.path.dirname( + os.path.abspath(filename) + ) + ) + if series == defaults.RELEASE: + branch = 'master' + else: + branch = 'stable/' + series + + # assume the releases are in order and take the last two + new_release = deliverable_info['releases'][-1] + if len(deliverable_info['releases']) >= 2: + previous_release = deliverable_info['releases'][-2] + else: + previous_release = None + for project in new_release['projects']: + if gitutils.commit_exists(project['repo'], + new_release['version']): + print('%s %s exists already' % + (project['repo'], new_release['version'])) + continue + + if previous_release: + git_range = '%s..%s' % (previous_release['version'], + project['hash']) + else: + git_range = project['hash'] + + # Check out the code. + subprocess.check_call( + ['zuul-cloner', + '--branch', branch, + '--workspace', workdir, + 'git://git.openstack.org', + project['repo'], + ] + ) + header = '%s %s' % (project['repo'], git_range) + print('\n%s' % header) + print('-' * len(header)) + + # Show the log output. + log_cmd = [ + 'git', 'log', '--no-color', + '--format=%h %ci %s', '--no-merges', + git_range, + ] + subprocess.check_call( + log_cmd, + cwd=os.path.join(workdir, project['repo']), + ) + print() + + return 0 diff --git a/openstack_releases/cmds/validate.py b/openstack_releases/cmds/validate.py index f232bfd168..11e5fe0bab 100755 --- a/openstack_releases/cmds/validate.py +++ b/openstack_releases/cmds/validate.py @@ -29,12 +29,10 @@ import yaml from requests.packages import urllib3 urllib3.disable_warnings() +from openstack_releases import defaults from openstack_releases import gitutils -DEFAULT_RELEASE = 'liberty' - - def is_a_hash(val): "Return bool indicating if val looks like a valid hash." return re.search('^[a-f0-9]{40}$', val, re.I) is not None @@ -53,8 +51,8 @@ def main(): filenames = args.input or gitutils.find_modified_deliverable_files() if not filenames: print('no modified deliverable files, validating all releases from %s' - % DEFAULT_RELEASE) - filenames = glob.glob('deliverables/' + DEFAULT_RELEASE + '/*.yaml') + % defaults.RELEASE) + filenames = glob.glob('deliverables/' + defaults.RELEASE + '/*.yaml') errors = [] @@ -92,7 +90,7 @@ def main(): '%(hash)r, which is not a hash') % project ) else: - exists = gitutils.commit_has_merged( + exists = gitutils.commit_exists( project['repo'], project['hash'], ) if not exists: diff --git a/openstack_releases/defaults.py b/openstack_releases/defaults.py new file mode 100644 index 0000000000..f1e9af06e9 --- /dev/null +++ b/openstack_releases/defaults.py @@ -0,0 +1,15 @@ +# All Rights Reserved. +# +# 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. + +RELEASE = 'liberty' diff --git a/openstack_releases/gitutils.py b/openstack_releases/gitutils.py index dba66c9c51..2861545d92 100644 --- a/openstack_releases/gitutils.py +++ b/openstack_releases/gitutils.py @@ -36,7 +36,7 @@ def find_modified_deliverable_files(): return filenames -def commit_has_merged(repo, hash): +def commit_exists(repo, hash): """Return boolean specifying whether the hash exists in the repository. Uses a cgit query instead of looking locally to avoid cloning a diff --git a/requirements.txt b/requirements.txt index f7f69d5b4c..acdfe13fa4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ argparse launchpadlib requests>=1.1 PyYAML>=3.1.0 +zuul diff --git a/setup.cfg b/setup.cfg index 4ad190eb93..248bd36c73 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,3 +23,4 @@ packages = openstack_releases [entry_points] console_scripts = validate-request = openstack_releases.cmds.validate:main + list-changes = openstack_releases.cmds.list_changes:main diff --git a/tox.ini b/tox.ini index 98ac5b6544..a414eaac5b 100644 --- a/tox.ini +++ b/tox.ini @@ -15,6 +15,9 @@ deps = -r{toxinidir}/requirements.txt [testenv:validate] commands = validate-request {posargs} +[testenv:list-changes] +commands = list-changes {posargs} + [testenv:pep8] deps = flake8 commands = flake8