Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/standards-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,16 @@ jobs:
# entirely rather than passed with an empty value — the script
# treats an unresolvable ref as a hard error, which is correct for a
# typo'd ref but wrong for "no narrowing requested".
# "${scope_args[@]-}" expands an EMPTY array to one empty-string
# argument, not to nothing, which run-standards.sh then rejects via
# its catch-all `*)` branch as `unknown argument: `. Plain
# "${scope_args[@]}" expands to nothing when empty and is safe under
# `set -u` on bash 4.4+ (runners are bash 5.x).
scope_args=()
[ -n "${CHANGED_SINCE}" ] && scope_args+=(--changed-since "${CHANGED_SINCE}")
bash standards-src/standards/run-standards.sh \
--repo repo \
--config-dir standards-src/standards \
--skip "${skip_list}" \
--node-floor "${NODE_FLOOR}" \
"${scope_args[@]-}"
"${scope_args[@]}"
39 changes: 39 additions & 0 deletions tests/test-run-standards.sh
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,44 @@ else
_bad "--changed-since bad ref exited ${rc}, expected 2 (see ${tmp}/cs-badref.log)"
fi

# The workflow builds the optional --changed-since flag in an array and
# expands it at the call site. "${arr[@]-}" expands an EMPTY array to one
# empty-string argument rather than to nothing, which lands on the runner's
# catch-all `*)` branch as `unknown argument: ` and exits 2 — so a repo that
# skips no linters and requests no narrowing fails the whole check. Assert the
# expansion form the workflow actually uses passes no stray argument.
# This asserts on argument assembly only, so it does not depend on the linters
# being installed — it counts what the call site would pass, without running a
# real lint. The workflow's own expansion form is reproduced verbatim.
_argc_for() { # $1 = expansion form, literally as written in the workflow
bash -c '
set -euo pipefail
scope_args=()
CHANGED_SINCE=""
[ -n "${CHANGED_SINCE}" ] && scope_args+=(--changed-since "${CHANGED_SINCE}")
set -- --skip "" --node-floor 22 '"$1"'
echo "$#"
'
}
# Built from a literal dollar rather than written inline, so the expansion
# forms under test stay unexpanded here without tripping SC2016.
d='\044'
fixed_form="$(printf '"%b{scope_args[@]}"' "${d}")"
broken_form="$(printf '"%b{scope_args[@]-}"' "${d}")"
fixed_argc="$(_argc_for "${fixed_form}")"
broken_argc="$(_argc_for "${broken_form}")"
if [[ "${fixed_argc}" -eq 4 ]]; then
_ok "empty scope_args expands to nothing (no stray empty argument)"
else
_bad "empty scope_args expanded to ${fixed_argc} args, expected 4"
fi
# Guard the test itself: the form this replaced must still be detectably wrong,
# so a future refactor cannot make this assertion vacuous.
if [[ "${broken_argc}" -eq 5 ]]; then
_ok "known-bad expansion form is still detected as passing a stray argument"
else
_bad "known-bad expansion form no longer reproduces; this test proves nothing"
fi

echo "${pass} passed, ${fail} failed"
[[ "${fail}" -eq 0 ]]
Loading