From 9c7d53ef4d281cb30e1df9fbd13b74f7646ddedd Mon Sep 17 00:00:00 2001 From: Rian Stockbower Date: Wed, 3 Jun 2026 19:53:22 -0400 Subject: [PATCH] fix: make auto-release path gate CWD-independent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _split_csv split the release/tool path CSVs with an unquoted `for x in $1`, so each field underwent pathname expansion. Run from a repo root — as the reusable auto-release workflow does — a tool-path glob like `tools/cfl/**` expanded into the real directory entries under tools/cfl/ instead of staying a literal pattern, so no changed file matched the tool path and EVERY change to a monorepo tool was skipped (not just version bumps; .go and go.mod too). Single-tool repos were unaffected — their tool glob has nothing to expand against. Disable globbing while splitting and restore the caller's prior setting. Add regression tests that run match-paths from a tree where tools/cfl/ exists; they fail against the old code and pass now. bash 3.2-safe. Closes #25 --- actions/auto-release/gate.sh | 15 +++++++++++++-- actions/auto-release/test_gate.sh | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/actions/auto-release/gate.sh b/actions/auto-release/gate.sh index 1bb293b..6409618 100755 --- a/actions/auto-release/gate.sh +++ b/actions/auto-release/gate.sh @@ -8,8 +8,19 @@ # exit 0 if any changed file is release-worthy, 1 otherwise set -euo pipefail -# Split a comma-separated list into lines, dropping empties. -_split_csv() { local IFS=','; for x in $1; do [ -n "$x" ] && printf '%s\n' "$x"; done; } +# Split a comma-separated list into lines, dropping empties. Globbing MUST be +# off while splitting: the values are path *globs* (e.g. tools/cfl/**), and an +# unquoted `for x in $1` would pathname-expand them against the gate's CWD — so +# run from a repo root, tools/cfl/** would match real directory entries and +# silently corrupt the gate (.github#25). Disable globbing for the split and +# restore the caller's prior setting. +_split_csv() { + local IFS=',' x restore=0 + case $- in *f*) ;; *) set -f; restore=1 ;; esac + for x in $1; do [ -n "$x" ] && printf '%s\n' "$x"; done + [ "$restore" -eq 1 ] && set +f + return 0 +} # Translate a path glob into a bash `case` pattern: ** -> * (case patterns # already match across '/', so a single * suffices for "any depth"). diff --git a/actions/auto-release/test_gate.sh b/actions/auto-release/test_gate.sh index 969c56a..59fa2a8 100755 --- a/actions/auto-release/test_gate.sh +++ b/actions/auto-release/test_gate.sh @@ -36,6 +36,28 @@ mp_pass "shared go" "$REL" "$TOOL" version.txt "shared/util.go" mp_fail "other tool" "$REL" "$TOOL" version.txt "tools/jtk/main.go" mp_fail "root doc in mono" "$REL" "$TOOL" version.txt "README.md" +# --- regression (.github#25): the gate must not depend on its CWD. In CI the +# gate runs from the repo *root*, where tool-paths like `tools/cfl/**` name real +# directories. An unquoted glob in _split_csv pathname-expanded them into +# directory entries, so EVERY change to a monorepo tool was skipped. Re-run the +# monorepo cases from inside such a tree to lock the behavior. --- +GATE="$(pwd)/gate.sh" +fixture="$(mktemp -d)" +mkdir -p "$fixture/tools/cfl/internal" "$fixture/tools/cfl/cmd/cfl" "$fixture/shared" +: > "$fixture/tools/cfl/version.txt"; : > "$fixture/tools/cfl/go.mod" +mp_pass_at() { # label cwd release tool vfile files + if ( cd "$2" && printf '%s\n' "$6" | bash "$GATE" match-paths "$3" "$4" "$5" ); then ok "$1"; else bad "$1"; fi +} +mp_fail_at() { + if ( cd "$2" && printf '%s\n' "$6" | bash "$GATE" match-paths "$3" "$4" "$5" ); then bad "$1"; else ok "$1"; fi +} +mp_pass_at "from root: cfl version bump" "$fixture" "$REL" "$TOOL" version.txt "tools/cfl/version.txt" +mp_pass_at "from root: cfl go file" "$fixture" "$REL" "$TOOL" version.txt "tools/cfl/internal/foo.go" +mp_pass_at "from root: cfl go.mod" "$fixture" "$REL" "$TOOL" version.txt "tools/cfl/go.mod" +mp_fail_at "from root: other tool" "$fixture" "$REL" "$TOOL" version.txt "tools/jtk/main.go" +mp_fail_at "from root: tool doc only" "$fixture" "$REL" "$TOOL" version.txt "tools/cfl/README.md" +rm -rf "$fixture" + # --- version validation --- bash gate.sh validate-version "3.1" >/dev/null 2>&1 && ok "ver 3.1" || bad "ver 3.1" bash gate.sh validate-version "v3.1" >/dev/null 2>&1 && bad "reject v3.1" || ok "reject v3.1"