Template
[nobump] Added plugin minor version auto-increment
This commit is contained in:
1 parent
1ef4e61334
commit
5e7f722bd9
1 file changed
+135
Executable
+135
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip())
|
||||
PLUGIN_JSON_PATH = REPO_ROOT / "plugin.json"
|
||||
|
||||
STOP_PATTERNS = [
|
||||
r"\[no[-_ ]?bump\]",
|
||||
r"\[skip[-_ ]?bump\]",
|
||||
r"\[no[-_ ]?version[-_ ]?bump\]",
|
||||
r"\[skip[-_ ]?version\]",
|
||||
r"\bno[-_ ]bump\b",
|
||||
r"\bskip[-_ ]bump\b",
|
||||
r"\bno[-_ ]version[-_ ]bump\b",
|
||||
]
|
||||
|
||||
|
||||
def increment_patch_version(version_str: str) -> str:
|
||||
match = re.fullmatch(r"^(\d+)\.(\d+)\.(\d+)(.*)$", version_str.strip())
|
||||
if not match:
|
||||
raise ValueError(f"Version '{version_str}' does not match x.y.z format")
|
||||
major, minor, patch, suffix = match.groups()
|
||||
new_patch = int(patch) + 1
|
||||
return f"{major}.{minor}.{new_patch}{suffix}"
|
||||
|
||||
|
||||
def get_head_version() -> str | None:
|
||||
res = subprocess.run(
|
||||
["git", "rev-parse", "--verify", "HEAD"],
|
||||
cwd=REPO_ROOT,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
if res.returncode != 0:
|
||||
return None
|
||||
|
||||
show_res = subprocess.run(
|
||||
["git", "show", "HEAD:plugin.json"],
|
||||
cwd=REPO_ROOT,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
text=True,
|
||||
)
|
||||
if show_res.returncode != 0:
|
||||
return None
|
||||
|
||||
try:
|
||||
head_data = json.loads(show_res.stdout)
|
||||
return str(head_data.get("version")) if "version" in head_data else None
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
|
||||
|
||||
def should_skip_from_commit_msg() -> bool:
|
||||
# 1. Check GIT_PARAMS / COMMIT_EDITMSG / MERGE_MSG
|
||||
candidates = [
|
||||
REPO_ROOT / ".git" / "COMMIT_EDITMSG",
|
||||
REPO_ROOT / ".git" / "MERGE_MSG",
|
||||
]
|
||||
for p in candidates:
|
||||
if p.exists():
|
||||
content = p.read_text(encoding="utf-8", errors="replace")
|
||||
lines = [line for line in content.splitlines() if not line.strip().startswith("#")]
|
||||
text = " ".join(lines)
|
||||
for pattern in STOP_PATTERNS:
|
||||
if re.search(pattern, text, re.IGNORECASE):
|
||||
return True
|
||||
|
||||
# 2. Check process command-line arguments (e.g. git commit -m "...")
|
||||
try:
|
||||
# On Linux, inspect parent process /proc cmdline
|
||||
ppid = subprocess.check_output(["ps", "-o", "ppid=", "-p", str(Path("/proc/self").resolve().name)], text=True).strip()
|
||||
cmdline_path = Path(f"/proc/{ppid}/cmdline")
|
||||
if cmdline_path.exists():
|
||||
cmd_args = cmdline_path.read_bytes().decode("utf-8", errors="replace")
|
||||
for pattern in STOP_PATTERNS:
|
||||
if re.search(pattern, cmd_args, re.IGNORECASE):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def main() -> int:
|
||||
# Don't auto-bump during merge/rebase in progress
|
||||
if (REPO_ROOT / ".git" / "MERGE_HEAD").exists() or (REPO_ROOT / ".git" / "rebase-merge").exists():
|
||||
return 0
|
||||
|
||||
if should_skip_from_commit_msg():
|
||||
print("pre-commit: stop word detected in commit message, skipping version bump")
|
||||
return 0
|
||||
|
||||
if not PLUGIN_JSON_PATH.exists():
|
||||
return 0
|
||||
|
||||
try:
|
||||
data = json.loads(PLUGIN_JSON_PATH.read_text(encoding="utf-8"))
|
||||
current_version = str(data.get("version", ""))
|
||||
except Exception as e:
|
||||
print(f"pre-commit: failed to parse {PLUGIN_JSON_PATH}: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
head_version = get_head_version()
|
||||
|
||||
# Skip if version was manually changed (differs from HEAD)
|
||||
if head_version is not None and current_version != head_version:
|
||||
print(
|
||||
f"pre-commit: version already modified ({head_version} -> {current_version}), skipping auto-increment"
|
||||
)
|
||||
return 0
|
||||
|
||||
try:
|
||||
new_version = increment_patch_version(current_version)
|
||||
data["version"] = new_version
|
||||
PLUGIN_JSON_PATH.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
||||
except Exception as e:
|
||||
print(f"pre-commit: failed to bump version in {PLUGIN_JSON_PATH}: {e}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
res = subprocess.run(["git", "add", str(PLUGIN_JSON_PATH)], cwd=REPO_ROOT)
|
||||
if res.returncode != 0:
|
||||
print("pre-commit: failed to stage plugin.json", file=sys.stderr)
|
||||
return res.returncode
|
||||
|
||||
print(f"pre-commit: bumped version {current_version} -> {new_version}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user