From 0fd740c8245de3175a46307f002c481863ba77e8 Mon Sep 17 00:00:00 2001 From: Kailash Nadh Date: Wed, 23 Jun 2021 10:51:55 +0530 Subject: [PATCH] Add --changelog for generating Markdown commit changelogs --- README.md | 11 +++++++++- gtbump/__init__.py | 50 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 50896c5..1d97327 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # gtbump -git tag bump: A simple utility to bump semver git tags. +git tag bump: A simple utility to bump and manage semver git tags and generate Markdown changelogs. ## Install ```shell @@ -34,6 +34,15 @@ deleted v1.2.0 # push the last tag upstream(or --push-last=your_remote_name) $ gtbump --push-last pushing v0.3.0 to origin + +# generate changelog for the latest tag. This can be copy-pasted into GitHub's release description. +$ gtbump --changelog +changelog for v1.0.0 -> v1.1.0 +- b361292 Display app version the settings UI +- a3b285f Fix Buefy number input width +- 63520d2 Merge pull request #388 from dunklesToast/chore/update-german-translations +- 3abac31 chore(translations): improve german translations +- 3ecac76 Fix Vue linting issue ``` Check `gtbump --help` for more options. diff --git a/gtbump/__init__.py b/gtbump/__init__.py index e16b513..fbb56d5 100644 --- a/gtbump/__init__.py +++ b/gtbump/__init__.py @@ -5,7 +5,7 @@ import subprocess import sys -__version__ = "1.0" +__version__ = "1.1.0" MAJOR = "major" MINOR = "minor" @@ -14,7 +14,8 @@ def run(cmd): """Executes a git shell command.""" - out = subprocess.Popen(cmd.split(" "), + out = subprocess.Popen(cmd, + shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout, stderr = out.communicate() @@ -49,6 +50,27 @@ def get_last_tag(): SUFFIX: g[3] if g[3] else ""} +def get_all_tags(): + """Get all annotated (closest) tags by lexicographic order.""" + tags = run("git tag --sort=-refname").split("\n") + + # Parse semver tag: v0.0.0-xxxx (optional suffix). + out = [] + for t in tags: + match = re.search(r"^v(\d+)\.(\d+)\.(\d+)((\-|\+).+?)?$", t) + if not match or len(match.groups()) != 5: + raise Exception("invalid tag in non-semver format: {}".format(t)) + + g = match.groups() + out.append({"tag": t, + MAJOR: int(g[0]), + MINOR: int(g[1]), + PATCH: int(g[2]), + SUFFIX: g[3] if g[3] else ""}) + + return out + + def bump(current, part, suffix="", strip_suffix=False): """ Given the current tag, part (major, minor ...) to bump and optional @@ -94,6 +116,8 @@ def main(): dest="init", help="add tag v0.1.0 (when there are no tags)") g.add_argument("-show", "--show", action="store_true", dest="show", help="show last tag") + g.add_argument("-changelog", "--changelog", action="store_true", + dest="changelog", help="generate a Markdown changelog of commits between the last and the current version") g.add_argument("-push-last", "--push-last", action="store", type=str, nargs="?", const="origin", metavar="", dest="push_last", help="push the last tag upstream (default: origin). IMPORTANT: This skips pre-push hooks with --no-verify. eg: --push-last, --push-last=remote_name") g.add_argument("-delete-last", "--delete-last", action="store_true", @@ -115,6 +139,7 @@ def main(): if args.show: print(get_last_tag()["tag"]) sys.exit(0) + elif args.init: # Check if a tag already exists. try: @@ -128,6 +153,27 @@ def main(): SUFFIX: ""}, MINOR, "", False) sys.exit(0) + elif args.changelog: + tags = get_all_tags() + + cmd = "git log --pretty=\"- %h %s\" {}" + if len(tags) == 1: + print("changelog for {}".format(tags[0]["tag"])) + cmd = cmd.format(tags[0]["tag"]) + else: + print("changelog for {} -> {}".format(tags[1]["tag"], tags[0]["tag"])) + # git log --pretty="- %h %s" v1.0.0..v1.1.0 + cmd = cmd.format("{}..{}".format(tags[1]["tag"], tags[0]["tag"])) + + out = run(cmd) + if not out: + print("no commits") + else: + print(out) + + sys.exit(0) + + elif args.push_last: tag = get_last_tag()["tag"] print("pushing {} to {}".format(tag, args.push_last))