@@ -15,7 +15,20 @@ OLD="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
1515TARGET=" bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
1616
1717PASS=0; TOTAL=0
18- ok () { TOTAL=$(( TOTAL + 1 )) ; if eval " $2 " ; then echo " PASS: $1 " ; PASS=$(( PASS + 1 )) ; else echo " FAIL: $1 " ; fi ; }
18+
19+ # try DESC CMD [ARGS...] — runs CMD as a real command (no eval); PASS on exit 0.
20+ try () {
21+ local desc=" $1 " ; shift
22+ TOTAL=$(( TOTAL + 1 ))
23+ if " $@ " ; then echo " PASS: $desc " ; PASS=$(( PASS + 1 )) ; else echo " FAIL: $desc " ; fi
24+ }
25+
26+ # Small eval-free predicates usable as `try` commands.
27+ contains () { case " $2 " in * " $1 " * ) return 0 ;; * ) return 1 ;; esac ; }
28+ not_contains () { case " $2 " in * " $1 " * ) return 1 ;; * ) return 0 ;; esac ; }
29+ fresh_only () { contains FRESH " $1 " && not_contains BEHIND " $1 " ; }
30+ file_has () { grep -q " $2 " " $1 " ; }
31+ staged_has () { git -C " $1 " diff --cached --name-only | grep -q " $2 " ; }
1932
2033mk_consumer () { # dir
2134 mkdir -p " $1 /.github/workflows"
4154# ── 1. AUDIT mode reports BEHIND and does not modify files ──────────────────
4255R=" $TEST_DIR /audit" ; mk_consumer " $R "
4356OUT=$( bash " $PROP " --to " $TARGET " " $R " )
44- ok " audit reports BEHIND" ' [[ "$OUT" == *BEHIND* ]] '
45- ok " audit leaves file unchanged" ' grep -q "governance-reusable.yml@${OLD}" "$ R/.github/workflows/governance.yml"'
57+ try " audit reports BEHIND" contains BEHIND " $OUT "
58+ try " audit leaves file unchanged" file_has " $ R /.github/workflows/governance.yml" " governance-reusable.yml@ ${OLD} "
4659
4760# ── 2. FIX rewrites the standards pins to the target ────────────────────────
4861R=" $TEST_DIR /fix" ; mk_consumer " $R "
4962bash " $PROP " --fix --to " $TARGET " " $R " > /dev/null
50- ok " fix bumps governance pin" ' grep -q "governance-reusable.yml@${TARGET}" "$ R/.github/workflows/governance.yml"'
51- ok " fix bumps scorecard pin" ' grep -q "scorecard-reusable.yml@${TARGET}" "$ R/.github/workflows/scorecard.yml"'
63+ try " fix bumps governance pin" file_has " $ R /.github/workflows/governance.yml" " governance-reusable.yml@ ${TARGET} "
64+ try " fix bumps scorecard pin" file_has " $ R /.github/workflows/scorecard.yml" " scorecard-reusable.yml@ ${TARGET} "
5265
5366# ── 3. Non-standards action pins are NOT touched ────────────────────────────
54- ok " actions/checkout pin untouched" ' grep -q "actions/checkout@${OLD}" "$ R/.github/workflows/scorecard.yml"'
67+ try " actions/checkout pin untouched" file_has " $ R /.github/workflows/scorecard.yml" " actions/checkout@ ${OLD} "
5568
5669# ── 4. After fix, audit reports FRESH (idempotent) ──────────────────────────
5770OUT=$( bash " $PROP " --to " $TARGET " " $R " )
58- ok " post-fix audit reports FRESH" ' [[ "$OUT" == *FRESH* && "$OUT" != *BEHIND* ]] '
71+ try " post-fix audit reports FRESH" fresh_only " $OUT "
5972
6073# ── 5. Re-running fix is a no-op (idempotent) ───────────────────────────────
6174BEFORE=$( cat " $R /.github/workflows/governance.yml" )
6275bash " $PROP " --fix --to " $TARGET " " $R " > /dev/null
63- ok " fix is idempotent" ' [[ "$(cat "$R/.github/workflows/governance.yml")" == "$BEFORE" ]] '
76+ try " fix is idempotent" test " $( cat " $R /.github/workflows/governance.yml" ) " = " $BEFORE "
6477
6578# ── 6. --fix in a git repo stages a bump branch (no commit/push) ────────────
6679R=" $TEST_DIR /gitrepo" ; mk_consumer " $R "
6780git -C " $R " init -q
6881git -C " $R " config user.email t@t; git -C " $R " config user.name t
6982git -C " $R " add -A; git -C " $R " commit -q -m init
7083bash " $PROP " --fix --to " $TARGET " " $R " > /dev/null 2>&1
71- ok " fix creates bump branch" ' [[ "$(git -C "$R" branch --show-current)" == "chore/bump-standards-pins" ]] '
72- ok " fix stages the change (no commit)" ' git -C "$R" diff --cached --name-only | grep -q governance.yml'
84+ try " fix creates bump branch" test " $( git -C " $R " branch --show-current) " = " chore/bump-standards-pins"
85+ try " fix stages the change (no commit)" staged_has " $R " governance.yml
7386
7487# ── 7. Parent-dir mode processes multiple repos ─────────────────────────────
7588ROOT=" $TEST_DIR /many" ; mk_consumer " $ROOT /repoA" ; mk_consumer " $ROOT /repoB"
7689OUT=$( bash " $PROP " --to " $TARGET " " $ROOT " )
77- ok " parent-dir mode sees repoA" ' [[ "$OUT" == *repoA* ]] '
78- ok " parent-dir mode sees repoB" ' [[ "$OUT" == *repoB* ]] '
90+ try " parent-dir mode sees repoA" contains repoA " $OUT "
91+ try " parent-dir mode sees repoB" contains repoB " $OUT "
7992
8093echo " ----------------------------------------"
8194echo " $PASS /$TOTAL test cases passed."
0 commit comments