Skip to content

Commit 2dbae29

Browse files
author
MarkusB
committed
Add git-tag script for creating and pushing annotated release tags
1 parent 7922030 commit 2dbae29

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

scripts/git-tag

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python3
2+
"""Create an annotated release tag and push to origin (see --help)."""
3+
4+
from __future__ import annotations
5+
6+
import argparse
7+
import subprocess
8+
import sys
9+
10+
11+
def _run_git(args: list[str], **kwargs) -> subprocess.CompletedProcess[str]:
12+
return subprocess.run(
13+
["git", *args],
14+
check=True,
15+
capture_output=True,
16+
text=True,
17+
**kwargs,
18+
)
19+
20+
21+
def _git_ok(args: list[str]) -> bool:
22+
r = subprocess.run(["git", *args], capture_output=True)
23+
return r.returncode == 0
24+
25+
26+
def main() -> int:
27+
p = argparse.ArgumentParser(
28+
description=(
29+
"Create an annotated tag at HEAD with message 'Release TAG', "
30+
"then push to origin. Refuses if the working tree is dirty or the tag exists."
31+
)
32+
)
33+
p.add_argument("tag", help='e.g. v1.2.0')
34+
p.add_argument(
35+
"--no-push",
36+
action="store_true",
37+
help="only create the tag locally",
38+
)
39+
args = p.parse_args()
40+
tag = args.tag
41+
42+
if not _git_ok(["rev-parse", "--is-inside-work-tree"]):
43+
print("Error: not inside a Git repository", file=sys.stderr)
44+
return 1
45+
46+
if _git_ok(["show-ref", "--verify", "--quiet", f"refs/tags/{tag}"]):
47+
print(f"Error: tag {tag!r} already exists", file=sys.stderr)
48+
return 1
49+
50+
st = subprocess.run(
51+
["git", "status", "--porcelain"],
52+
check=True,
53+
capture_output=True,
54+
text=True,
55+
)
56+
if st.stdout.strip():
57+
print(
58+
"Error: working tree is not clean; commit or stash before tagging",
59+
file=sys.stderr,
60+
)
61+
return 1
62+
63+
_run_git(["tag", "-a", tag, "-m", f"Release {tag}"])
64+
short = _run_git(["rev-parse", "--short", "HEAD"]).stdout.strip()
65+
print(f"Created annotated tag {tag} at {short}")
66+
67+
if not args.no_push:
68+
_run_git(["push", "origin", tag])
69+
print(f"Pushed {tag} to origin")
70+
71+
return 0
72+
73+
74+
if __name__ == "__main__":
75+
sys.exit(main())

scripts/git-tag.cmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
@echo off
2+
setlocal
3+
python "%~dp0git-tag" %*
4+
endlocal

0 commit comments

Comments
 (0)