Add script to diff projects in OSA releases

This script takes two OSA commit SHA's and provides a list of commits
from each of the projects that OSA builds. This can be helpful for
deployers who want to know if a particular bug in an OpenStack
project, like keystone, was fixed between OSA SHA bumps.

Example output: http://paste.openstack.org/raw/510670/

Change-Id: I0f17842f5f3040d637fc6f51bde8988e4df83eb6
This commit is contained in:
Major Hayden 2016-06-10 15:09:48 -05:00
parent 7651e4b2a6
commit a5ab919247
No known key found for this signature in database
GPG Key ID: 737051E0C1011FB1
1 changed files with 187 additions and 0 deletions

187
osa-differ.py Executable file
View File

@ -0,0 +1,187 @@
#!/usr/bin/env python
# Copyright 2016, Rackspace US, Inc.
#
# 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.
"""Analyzes the differences between two OpenStack-Ansible commits."""
import argparse
import pygithub3
import requests
import sys
from urlparse import urlparse
import yaml
def get_arguments():
"""Setup argument Parsing."""
parser = argparse.ArgumentParser(
usage='%(prog)s',
description='OpenStack-Ansible Release Diff Generator',
epilog='Licensed "Apache 2.0"')
parser.add_argument(
'old_commit',
action='store',
nargs=1,
help="Git SHA of the older commit",
)
parser.add_argument(
'new_commit',
action='store',
nargs=1,
help="Git SHA of the newer commit",
)
return vars(parser.parse_args())
def short_commit(commit_sha):
"""Return a short commit hash string."""
return commit_sha[0:8]
def get_commit_data(commit_sha):
"""Get information about a commit from Github."""
commit_data = gh.repos.commits.get(user='openstack',
repo='openstack-ansible',
sha=commit_sha)
return commit_data
def get_commit_message(commit_sha):
"""Get the first line of the commit message for a particular commit."""
commit_data = get_commit_data(commit_sha)
commit_message = commit_data.commit.message.splitlines()[0]
return commit_message
def get_project_names(project_dict):
"""Get project names from the list of project variables."""
return [x[:-9] for x in project_dict if x.endswith('git_repo')]
def get_projects(yaml_urls):
"""Get all projects from multiple YAML files."""
yaml_parsed = []
for yaml_url in yaml_urls:
r = requests.get(yaml_url)
yaml_parsed.append(yaml.load(r.text))
merged_dicts = {k: v for d in yaml_parsed for k, v in d.items()}
return merged_dicts
if __name__ == "__main__":
# Set up some initial variables
gh = pygithub3.Github()
args = get_arguments()
report = ''
# Store our arguments into variables to make things easier.
old_commit = args['old_commit'][0]
new_commit = args['new_commit'][0]
# Get the first line of the commit message in the older commit
try:
old_commit_message = get_commit_message(old_commit)
except pygithub3.exceptions.NotFound:
print("The old commit SHA was not found: {0}".format(old_commit))
sys.exit(1)
# Get the first line of the commit message in the newer commit
try:
new_commit_message = get_commit_message(new_commit)
except pygithub3.exceptions.NotFound:
print("The new commit SHA was not found: {0}".format(new_commit))
sys.exit(1)
report_header = """
OpenStack-Ansible Release Diff Generator
-------------------------------------------------------------------------------
Old commit: {0} {1}
New commit: {2} {3}
-------------------------------------------------------------------------------
""".format(
short_commit(old_commit),
old_commit_message,
short_commit(new_commit),
new_commit_message
)
report += report_header
# Set up the URLs for the YAML files which contain the projects used by
# OpenStack-Ansible.
base_url = 'https://raw.githubusercontent.com/openstack/' \
'openstack-ansible/{0}/{1}'
repo_files = [
'playbooks/defaults/repo_packages/openstack_services.yml',
'playbooks/defaults/repo_packages/openstack_other.yml'
]
# Get all of the OpenStack projects that OpenStack-Ansible builds
old_commit_yaml_urls = [base_url.format(old_commit, x) for x in repo_files]
old_commit_projects = get_projects(old_commit_yaml_urls)
new_commit_yaml_urls = [base_url.format(new_commit, x) for x in repo_files]
new_commit_projects = get_projects(new_commit_yaml_urls)
# Get the bare project names from the YAML data we retrieved
old_commit_project_names = get_project_names(old_commit_projects)
new_commit_project_names = get_project_names(new_commit_projects)
# Loop through each project found in the latest commit
for project in sorted(new_commit_project_names):
# Find the git repo URL from the new commit
git_repo = new_commit_projects["{0}_git_repo".format(project)]
_, user, project_repo_name = urlparse(git_repo).path.split('/')
# Determine the latest sha for this project
project_sha = "{0}_git_install_branch".format(project)
latest_sha = new_commit_projects[project_sha]
# If this module didn't exist in the old OpenStack-Ansible commit,
# just skip it for now.
try:
project_sha = "{0}_git_install_branch".format(project)
older_sha = old_commit_projects[project_sha]
except:
continue
# Compare the two commits in the project's repository to see what
# the differences are between them.
comparison = gh.repos.commits.compare(
user=user,
repo=project_repo_name,
base=older_sha,
head=latest_sha
)
project_header = "________ {0} (commits: {1}) ".format(
project,
len(comparison.commits)
)
project_header = project_header.ljust(78, '_')
report += "\n{0}\n".format(project_header)
if len(comparison.commits) == 0:
report += " No changes\n"
continue
for commit in comparison.commits:
commit_line = commit.commit['message'].splitlines()[0]
# Skip the merge messages since they're not terribly helpful
if commit_line.startswith('Merge "'):
continue
report += "{0} {1}\n".format(commit.sha[0:8], commit_line)
print(report)