Created
December 6, 2018 16:36
-
-
Save gaponcec/99f19e2bc972761e11ccba2260622d10 to your computer and use it in GitHub Desktop.
Script to create Release Notes/Change Log from two ISO manifests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Script to create release notes from project manifests | |
""" | |
#!/usr/bin/env python3 | |
from json import dumps, loads | |
from os.path import basename | |
from sys import exit | |
from xml.etree.ElementTree import fromstringlist | |
from argparse import ArgumentParser | |
from git import Repo, repo, Git | |
from git.exc import GitError | |
from prettytable import PrettyTable, NONE | |
from xmljson import gdata | |
import dictdiffer | |
def load_manifest_to_dict(manifest): | |
""" | |
Loads manifest file into a dictionary and returns it | |
manifest -- manifest file path/name | |
""" | |
with open(manifest, "r") as file_desc: | |
data = file_desc.readlines() | |
return loads(dumps(gdata.data(fromstringlist(data)))) | |
def check_dict_diff(o_re, n_re): | |
""" | |
Checks differences between dictionaries and returns a list of them | |
o_re -- old dictionary | |
n_re -- new dictionary | |
""" | |
return list(dictdiffer.diff(o_re, n_re)) | |
def get_remotes_dict(remotes): | |
""" | |
Creates a dictionary with the remotes names and URLS and returns it | |
remotes -- remotes dictionary created from manifest xml | |
""" | |
rem_dict = {} | |
for i in remotes: | |
rem_dict[i['name']] = i['fetch'] | |
return rem_dict | |
def clone_repo(repo_url, directory): | |
""" | |
Clones a git repo and returns an object to manipulate it | |
repo_url -- URL to git repository | |
directory -- directory to clone the repo | |
""" | |
try: | |
Repo.clone_from(repo_url, directory) | |
except GitError: | |
return Repo(directory) | |
return Repo(directory) | |
def create_argument_parser(): | |
""" | |
Creates an argument parser | |
""" | |
parser = ArgumentParser('Compares changes between ISOs using manifest') | |
parser.add_argument('-o', '--old', type=str, nargs=1, required=True, | |
metavar='manifest.xml', help='Old manifest path') | |
parser.add_argument('-n', '--new', type=str, nargs=1, required=True, | |
metavar='manifest.xml', help='Old manifest path') | |
return parser | |
ARG_PARSE = create_argument_parser().parse_args() | |
OLD_MANIFEST_NAME = ARG_PARSE.old[0] | |
NEW_MANIFEST_NAME = ARG_PARSE.new[0] | |
OLD_MAN = load_manifest_to_dict(OLD_MANIFEST_NAME) | |
NEW_MAN = load_manifest_to_dict(NEW_MANIFEST_NAME) | |
DIFF = check_dict_diff(OLD_MAN['manifest']['remote'], | |
NEW_MAN['manifest']['remote']) | |
if DIFF != []: | |
print("something changed on the remotes") | |
exit(1) | |
REMOTES_DICT = get_remotes_dict(OLD_MAN['manifest']['remote']) | |
DIFF = check_dict_diff(OLD_MAN['manifest']['project'], | |
NEW_MAN['manifest']['project']) | |
RELEASE_NOTES = "RELEASE NOTES FROM " + basename(OLD_MANIFEST_NAME) | |
RELEASE_NOTES += " TO " + basename(NEW_MANIFEST_NAME) + "\n" | |
if DIFF != []: | |
FOR_RELEASE = [] | |
DIFF2 = dict() | |
for _, k, l in DIFF: | |
if k[0] in DIFF2.keys(): | |
if DIFF2[k[0]] == 'upstream': | |
DIFF2[k[0]] = {k[1]: l} | |
else: | |
DIFF2[k[0]] = {k[1]: l} | |
for m in DIFF2: | |
b = DIFF2[m].popitem()[1] | |
if 'remote' not in NEW_MAN['manifest']['project'][m].keys(): | |
NEW_MAN['manifest']['project'][m]['remote'] = \ | |
NEW_MAN['manifest']['default']['remote'] | |
FOR_RELEASE.append({ | |
'name': NEW_MAN['manifest']['project'][m]['name'], | |
'remote': REMOTES_DICT[NEW_MAN['manifest']['project'][m]['remote']], | |
'old_rev': b[0], | |
'new_rev': b[1] | |
}) | |
for r in FOR_RELEASE: | |
TEMP = '' | |
try: | |
TEMP += "\n\nFrom repo: " + r['name'] + "\n" | |
repo = clone_repo("{}/{}".format(r['remote'], r['name']), r['name']) | |
git = Git(r['name']) | |
repo.head.reference = repo.commit(r['old_rev']) | |
old_logs = git.log('--pretty=%ai$%h$%s$%aE').split('\n') | |
repo.head.reference = repo.commit(r['new_rev']) | |
new_logs = git.log('--pretty=%ai$%h$%s$%aE').split('\n') | |
diff_logs = set(new_logs) - set(old_logs) | |
if list(diff_logs) == []: | |
raise ValueError('No changes were found.') | |
p_table = PrettyTable(header_style="upper", vrules=NONE) | |
p_table.field_names = ['Date', 'Commit', 'Message', 'Author'] | |
for d in diff_logs: | |
p_table.add_row(d.split('$')) | |
p_table.sortby = "Date" | |
p_table.align = "l" | |
TEMP += p_table.get_string() | |
except: | |
TEMP = '' | |
RELEASE_NOTES += TEMP | |
else: | |
RELEASE_NOTES += "NO CHANGES" | |
print(RELEASE_NOTES) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment