Skip to content

Instantly share code, notes, and snippets.

@jecolasurdo
Created September 19, 2021 03:06
Show Gist options
  • Save jecolasurdo/b64a6b528693f3d565e25bd6020fd2ae to your computer and use it in GitHub Desktop.
Save jecolasurdo/b64a6b528693f3d565e25bd6020fd2ae to your computer and use it in GitHub Desktop.
git command for incrementing semver tags
#!/usr/local/bin/python3
import operator
import re
import subprocess
import sys
# Slightly modified from the semver.org spec (see note below).
# https://regex101.com/r/Ly7O1x/3/
#
# I've required the use of a leading "v", since I'm primarily using this for
# go, which requires a leading v in their semantic version values.
semver_re = '^v(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
tags = subprocess.run(["sh", "-c", "git tag"], check=True, capture_output=True, text=True).stdout.splitlines()
versions= []
for tag in tags:
match = re.match(semver_re, tag)
if match:
version_tuple = (int(match.group('major')), int(match.group('minor')), int(match.group('patch')))
versions.append(version_tuple)
if not versions:
version = None
print("No existing valid semantic version.")
while not version:
version = input("Please enter an initial version: ")
if not re.match(semver_re, version):
print("The specified value is not a valid semantic version number.")
version = None
subprocess.run(["sh", "-c", "git tag {}".format(version)], check=True)
else:
versions.sort(key = operator.itemgetter(0,1,2))
last_version = versions[-1]
last_version_string = "v{}.{}.{}".format(last_version[0], last_version[1], last_version[2])
print("Latest version: {}".format(last_version_string))
part = None
while not part:
part = input("Which part to bump? m[a]jor, m[i]nor, [p]atch, e[x]it: ").lower()
if part not in ["a", "i", "p", "x"]:
print("invalid input")
part = None
next_version = [0,0,0]
if part == "a":
next_version[0] = last_version[0] + 1
elif part == "i":
next_version[0] = last_version[0]
next_version[1] = last_version[1] + 1
elif part == "p":
next_version[0] = last_version[0]
next_version[1] = last_version[1]
next_version[2] = last_version[2] + 1
else:
sys.exit(0)
next_version_string = "v{}.{}.{}".format(next_version[0], next_version[1], next_version[2])
print("{} -> {}".format(last_version_string, next_version_string))
accept = None
while not accept:
accept = input("Accept? [y/n]: ").lower()
if accept not in ["y", "n"]:
print("invalid input")
accept= None
if not accept:
print("Done (version not updated)")
sys.exit(0)
subprocess.run(["sh", "-c", "git tag {}".format(next_version_string)], check=True)
push = None
while not push:
push = input("Push tags? [y/n]: ").lower()
if push not in ["y", "n"]:
print("invalid input")
push = None
if push == "y":
subprocess.run(["sh", "-c", "git push --tags"], check=False)
print("Done")
help: ## this help message
$(info Available targets)
@awk '/^[a-zA-Z\-\_0-9]+:/ { \
nb = sub( /^## /, "", helpMsg ); \
if(nb == 0) { \
helpMsg = $$0; \
nb = sub( /^[^:]*:.* ## /, "", helpMsg ); \
} \
if (nb) \
print $$1 "\t" helpMsg; \
} \
{ helpMsg = $$0 }' \
$(MAKEFILE_LIST) | column -ts $$'\t' | \
grep --color '^[^ ]*'
.PHONY: help
install: ## install git-bump for use with git
chmod +x git-bump
cp git-bump /usr/local/bin/git-bump
.PHONY: install
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment