generated from exteraGramPlugins/pluginBase
[no bump] Enable git hooks automatically on first bundle run
Publish plugin / publish (push) Successful in 27s
Publish plugin / publish (push) Successful in 27s
tools/bundle.py now sets `core.hooksPath scripts` the first time it runs in a clone (skipped in CI, outside a git work tree, or when core.hooksPath is already set), so the version auto-bump hooks work in fresh clones and repos created from the template without a manual setup step. README documents the hooks, the self-enabling behaviour and the bump stop words. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fc76a20420
commit
b2105ca753
4 files changed
+99
-7
No files matched your search
Executable → Regular
+46
@@ -2,6 +2,9 @@
|
||||
"""Bundle a multi-file exteraGram plugin (plugin.json + src/) into a single .plugin file.
|
||||
|
||||
Usage: python3 tools/bundle.py [--dev|--release] [--out DIR] [--check]
|
||||
|
||||
Also enables the repo's git hooks (scripts/pre-commit, scripts/post-commit) on
|
||||
first run; see ensure_git_hooks().
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -9,13 +12,18 @@ import argparse
|
||||
import ast
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import zlib
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||
SRC_DIR = REPO_ROOT / "src"
|
||||
HOOKS_DIR = "scripts"
|
||||
HOOK_NAMES = ("pre-commit", "post-commit")
|
||||
PLUGIN_JSON = REPO_ROOT / "plugin.json"
|
||||
|
||||
RECOGNIZED_KEYS = {
|
||||
@@ -300,6 +308,43 @@ def assemble_bundle(data: dict, modules: dict, release: bool) -> str:
|
||||
return text
|
||||
|
||||
|
||||
def ensure_git_hooks() -> None:
|
||||
"""Point git at scripts/ for hooks, once per clone.
|
||||
|
||||
Git never enables hooks from repository content, so a fresh clone (or a
|
||||
repo created from the template) starts without them. Every workflow runs
|
||||
this bundler first, directly or via scripts/deploy.sh and scripts/watch.sh,
|
||||
which makes it the one place that can switch them on without an extra
|
||||
setup step. Skipped in CI, outside a git work tree, and when
|
||||
core.hooksPath is already set (including to something else on purpose).
|
||||
Never fails the build.
|
||||
"""
|
||||
if os.environ.get("CI"):
|
||||
return
|
||||
hooks = [REPO_ROOT / HOOKS_DIR / name for name in HOOK_NAMES]
|
||||
if not any(h.is_file() for h in hooks):
|
||||
return
|
||||
|
||||
def git(*args):
|
||||
return subprocess.run(["git", *args], cwd=REPO_ROOT, capture_output=True, text=True)
|
||||
|
||||
try:
|
||||
top = git("rev-parse", "--show-toplevel")
|
||||
if top.returncode != 0 or Path(top.stdout.strip()).resolve() != REPO_ROOT:
|
||||
return
|
||||
if git("config", "--get", "core.hooksPath").stdout.strip():
|
||||
return
|
||||
# Git silently skips hooks that are not executable.
|
||||
for hook in hooks:
|
||||
if hook.is_file():
|
||||
mode = hook.stat().st_mode
|
||||
hook.chmod(mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
|
||||
if git("config", "core.hooksPath", HOOKS_DIR).returncode == 0:
|
||||
print(f"enabled git hooks from {HOOKS_DIR}/ (git config core.hooksPath {HOOKS_DIR})", file=sys.stderr)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
pass
|
||||
|
||||
|
||||
def parse_args(argv):
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Bundle a multi-file exteraGram plugin into a single .plugin file."
|
||||
@@ -318,6 +363,7 @@ def parse_args(argv):
|
||||
|
||||
def main(argv=None) -> int:
|
||||
args = parse_args(sys.argv[1:] if argv is None else argv)
|
||||
ensure_git_hooks()
|
||||
release = bool(args.release)
|
||||
try:
|
||||
data = load_metadata()
|
||||
|
||||
Reference in new issue
Block a user