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"