add release note chnage log generation

Signed-off-by: Harsha Narayana <harsha2k4@gmail.com>
This commit is contained in:
Harsha Narayana 2018-12-09 21:46:36 +05:30
parent 5189d8b14c
commit 9c6b83501f
No known key found for this signature in database
GPG Key ID: 8AF211CB60D4B28C
2 changed files with 114 additions and 26 deletions

View File

@ -1,22 +1,48 @@
#!/usr/bin/env python
from argparse import ArgumentParser, Namespace
from datetime import datetime
from os import path
from collections import OrderedDict
from configparser import RawConfigParser
from datetime import datetime
from json import dumps
from os import path
from subprocess import Popen, PIPE
from jinja2 import Environment, BaseLoader
from requests import patch
GIT_COMMANDS = {
"get_tag": ["git describe --tags --abbrev=0"],
"create_new_branch": ["git checkout -b {new_version} master"],
"commit_version_change": ["git commit -m 'Bumping up version from {current_version} to {new_version}'"],
"push_new_branch": ["git push origin {new_version}"],
"commit_version_change": [
"git add . && git commit -m 'Bumping up version from {current_version} to {new_version}'"],
"create_new_tag": ["git tag -a {new_version} -m 'Bumping up version from {current_version} to {new_version}'"],
"push_tag": ["git push origin {new_version}"],
"get_change_log": ['git log --no-merges --pretty=format:"%h: %cn: %s" {current_version}..']
"get_change_log": ['git log --no-merges --pretty=format:"%h::: %cn::: %s" {current_version}..']
}
RELASE_NOTE_TEMPLATE = """
# {{ release_name }} - {% now 'utc', '%Y-%m-%d' %}
To see the exhaustive list of pull requests included in this release see:
https://github.com/huge-success/sanic/milestone/{{milestone}}?closed=1
# Changelog
{% for row in changelogs %}
* {{ row -}}
{% endfor %}
# Credits
{% for author in authors %}
* {{ author -}}
{% endfor %}
"""
JINJA_RELASE_NOTE_TEMPLATE = Environment(
loader=BaseLoader, extensions=['jinja2_time.TimeExtension']).from_string(RELASE_NOTE_TEMPLATE)
RELEASE_NOTE_UPDATE_URL = \
"https://api.github.com/repos/huge-success/sanic/releases/tags/{new_version}?access_token={token}"
def _run_shell_command(command: list):
try:
@ -24,8 +50,10 @@ def _run_shell_command(command: list):
shell=True)
output, error = process.communicate()
return_code = process.returncode
return output, error, return_code
return output.decode("utf-8"), error, return_code
except:
import traceback
traceback.print_exc()
return None, None, -1
@ -73,35 +101,69 @@ def _get_current_tag(git_command_name="get_tag"):
def _update_release_version_for_sanic(current_version, new_version, config_file):
old_version_line = '__version__ = "{current_version}"'.format(current_version=current_version)
new_version_line = '__version__ = "{new_version}"'.format(new_version=new_version)
with open("sanic/__init__.py") as init_file:
data = init_file.read()
new_data = data.replace(old_version_line, new_version_line)
with open("sanic/__init__.py", "w") as init_file:
init_file.write(new_data)
config_parser = RawConfigParser()
with open(config_file) as cfg:
config_parser.read_file(cfg)
config_parser.set("version", "current_version", new_version)
version_file = config_parser.get("version", "file")
current_version_line = config_parser.get("version", "current_version_pattern").format(
current_version=current_version)
new_version_line = config_parser.get("version", "new_version_pattern").format(new_version=new_version)
with open(version_file) as init_file:
data = init_file.read()
new_data = data.replace(current_version_line, new_version_line)
with open(version_file, "w") as init_file:
init_file.write(new_data)
with open(config_file, "w") as config:
config_parser.write(config)
command = GIT_COMMANDS.get("commit_version_change")
command[0] = command[0].format(new_version=new_version, current_version=current_version)
_, _, ret = _run_shell_command(command)
_, err, ret = _run_shell_command(command)
if int(ret) != 0:
print("Failed to Commit Version upgrade changes to Sanic")
print("Failed to Commit Version upgrade changes to Sanic: {}".format(err.decode("utf-8")))
exit(1)
def _tag_release(new_version, current_version):
def _generate_change_log(current_version: str = None):
global GIT_COMMANDS
for command_name in ["push_new_branch", "create_new_tag", "push_tag"]:
command = GIT_COMMANDS.get("get_change_log")
command[0] = command[0].format(current_version=current_version)
output, error, ret = _run_shell_command(command=command)
if not len(str(output)):
print("Unable to Fetch Change log details to update the Release Note")
exit(1)
commit_details = OrderedDict()
commit_details["authors"] = dict()
commit_details["commits"] = list()
for line in str(output).split("\n"):
commit, author, description = line.split(":::")
if 'GitHub' not in author:
commit_details["authors"][author] = 1
commit_details["commits"].append(" - ".join([commit, description]))
return commit_details
def _generate_markdown_document(milestone, release_name, current_version, release_version):
global JINJA_RELASE_NOTE_TEMPLATE
release_name = release_name or release_version
change_log = _generate_change_log(current_version=current_version)
return JINJA_RELASE_NOTE_TEMPLATE.render(
release_name=release_name, milestone=milestone, changelogs=change_log["commits"],
authors=change_log["authors"].keys())
def _tag_release(new_version, current_version, milestone, release_name, token):
global GIT_COMMANDS
global RELEASE_NOTE_UPDATE_URL
for command_name in ["create_new_tag", "push_tag"]:
command = GIT_COMMANDS.get(command_name)
command[0] = command[0].format(new_version=new_version, current_version=current_version)
out, error, ret = _run_shell_command(command=command)
@ -109,16 +171,33 @@ def _tag_release(new_version, current_version):
print("Failed to execute the command: {}".format(command[0]))
exit(1)
change_log = _generate_markdown_document(milestone, release_name, current_version, new_version)
body = {
"name": release_name or new_version,
"body": change_log
}
headers = {
"content-type": "application/json"
}
response = patch(RELEASE_NOTE_UPDATE_URL.format(new_version=new_version, token=token),
data=dumps(body), headers=headers)
response.raise_for_status()
def release(args: Namespace):
current_tag = _get_current_tag()
current_version = _fetch_current_version(args.config)
if current_tag and current_version not in current_tag:
print("Tag mismatch between what's in git and what was provided by --current-version")
print("Tag mismatch between what's in git and what was provided by --current-version. "
"Existing: {}, Give: {}".format(current_tag, current_version))
exit(1)
new_version = _get_new_version(args.config, current_version, args.micro_release)
new_version = args.release_version or _get_new_version(args.config, current_version, args.micro_release)
_update_release_version_for_sanic(current_version=current_version, new_version=new_version, config_file=args.config)
_tag_release(current_version=current_version, new_version=new_version)
_tag_release(current_version=current_version, new_version=new_version,
milestone=args.milestone, release_name=args.release_name, token=args.token)
if __name__ == '__main__':
@ -129,7 +208,13 @@ if __name__ == '__main__':
cli.add_argument("--current-version", "-cv", help="Current Version to default in case if you don't want to "
"use the version configuration files",
default=None, required=False)
cli.add_argument("--config", "-c", help="Configuration file used for release", default="./setup.cfg", required=False)
cli.add_argument("--config", "-c", help="Configuration file used for release", default="./setup.cfg",
required=False)
cli.add_argument("--token", "-t", help="Git access token with necessary access to Huge Sanic Org",
required=True)
cli.add_argument("--milestone", "-ms", help="Git Release milestone information to include in relase note",
required=True)
cli.add_argument("--release-name", "-n", help="Release Name to use if any", required=False)
cli.add_argument("--micro-release", "-m", help="Micro Release with patches only",
default=False, action='store_true', required=False)
args = cli.parse_args()

View File

@ -14,4 +14,7 @@ multi_line_output = 3
not_skip = __init__.py
[version]
current_version = 0.8.3
current_version = 18.12.0
file = sanic/__init__.py
current_version_pattern = __version__ = "{current_version}"
new_version_pattern = __version__ = "{new_version}"