misc/git_hook: propagate shared HOOK_VERSION (#19476)

Move HOOK_VERSION into the githook package and export it as
githook.HookVersion, so tailscale/corp can reference it via
the shared-code bump instead of having to bump HOOK_VERSION
by hand.

New launcher.sh composes the wanted version from 2 sources:
the shared HOOK_VERSION and an optional repo local version,
misc/git_hook/HOOK_VERSION, for repo-specific config bumps.

Updates tailscale/corp#40381

Change-Id: I7cf16889ba53cb564cc2df7dfd7588748f542c55

Signed-off-by: Fernando Serboncini <fserb@tailscale.com>
This commit is contained in:
Fernando Serboncini
2026-05-04 12:38:28 -04:00
committed by GitHub
parent 290a6cc03c
commit 29122506be
5 changed files with 29 additions and 22 deletions
+1
View File
@@ -0,0 +1 @@
3
+6
View File
@@ -22,6 +22,12 @@ import (
//go:embed launcher.sh
var Launcher []byte
// HookVersion is the shared version of this package and launcher.sh.
// Bump HOOK_VERSION on any change under this package.
//
//go:embed HOOK_VERSION
var HookVersion string
// RunLocalHook runs an optional user-supplied hook at
// .git/hooks/<name>.local, if present.
func RunLocalHook(hookName string, args []string) error {
+13 -9
View File
@@ -4,13 +4,12 @@
# Written by misc/install-git-hooks.go from the canonical copy embedded
# in tailscale.com/misc/git_hook/githook. On every invocation it:
#
# 1. Compares misc/git_hook/HOOK_VERSION against the binary's version.
# 2. If stale or missing: rebuilds .git/hooks/ts-git-hook-bin and runs
# `ts-git-hook-bin install` to refresh the launcher and per-hook
# wrappers.
# 1. Compares the binary's reported version against the shared
# githook HOOK_VERSION (resolved via `go list -m tailscale.com`)
# plus the repo-local HOOK_VERSION.
# 2. If stale or missing: rebuilds ts-git-hook-bin and runs
# `ts-git-hook-bin install`.
# 3. Execs the binary with the hook's args.
#
# Any change to this file or the binary must bump HOOK_VERSION.
set -euo pipefail
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)" || {
@@ -29,12 +28,17 @@ EXE=""
case "$(uname -s)" in MINGW* | MSYS* | CYGWIN*) EXE=".exe" ;; esac
BINARY="$HOOK_DIR/ts-git-hook-bin$EXE"
WANT="$(cat "$REPO_ROOT/misc/git_hook/HOOK_VERSION" 2>/dev/null || echo 0)"
GO="$REPO_ROOT/tool/go$EXE"
if [ ! -x "$GO" ]; then GO=go; fi
OSS_DIR="$(cd "$REPO_ROOT" && GOWORK=off "$GO" list -m -f '{{.Dir}}' tailscale.com 2>/dev/null || true)"
SHARED_VER="$(cat "$OSS_DIR/misc/git_hook/githook/HOOK_VERSION" 2>/dev/null || echo 0)"
LOCAL_VER="$(cat "$REPO_ROOT/misc/git_hook/HOOK_VERSION" 2>/dev/null || echo 0)"
WANT="$SHARED_VER:$LOCAL_VER"
HAVE="$("$BINARY" version 2>/dev/null || echo none)"
if [ "$WANT" != "$HAVE" ]; then
GO="$REPO_ROOT/tool/go$EXE"
if [ ! -x "$GO" ]; then GO=go; fi
echo "git-hook: rebuilding ts-git-hook-bin..." >&2
(cd "$REPO_ROOT" && GOWORK=off "$GO" build -o "$BINARY" ./misc/git_hook) || {
echo "git-hook: rebuild failed, run: ./tool/go run ./misc/install-git-hooks.go" >&2