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
52 changes: 45 additions & 7 deletions scripts/apply-workflow-pins-remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -301,15 +301,48 @@
done < <(pin_shas "$1" | sort -u)
}

# list_repos β€” print every non-archived repository of the owners in OWNERS that
# this credential can see, one full_name per line, sorted and deduplicated.
#
# Every credential gets each owner's PUBLIC listing. Under a GitHub App
# installation token (prefix ghs_) the installation's own repositories are ADDED
# to it: users/<o>/repos and orgs/<o>/repos return public repositories only to an
# installation, so the private repositories the App can write never reached the
# census. The installation listing never REPLACES the public one, because
# GITHUB_TOKEN is ghs_ too and its installation is this one repository; a
# replacement would shrink the audit-mode census to standards alone.
#
# Returns 1 and prints nothing when any listing fails. A rate-limited owner that
# silently contributed zero repositories would read as an owner with nothing to
# re-point, which is the same fail-open fetch_workflows was cured of.
list_repos() {
local owner
local owner all part tok="${GH_TOKEN:-${GITHUB_TOKEN:-}}"
all=$(mktemp); part=$(mktemp)
for owner in ${OWNERS//,/ }; do
# /users/<o>/repos covers a user; if that 404s the owner is an org.
gh api "users/${owner}/repos" --paginate \
--jq '.[] | select(.archived == false) | .full_name' 2>/dev/null \
|| gh api "orgs/${owner}/repos" --paginate \
--jq '.[] | select(.archived == false) | .full_name' 2>/dev/null
# users/<o>/repos covers a user; if that fails the owner may be an org.
if gh api "users/${owner}/repos" --paginate \
--jq '.[] | select(.archived == false) | .full_name' > "$part" \
|| gh api "orgs/${owner}/repos" --paginate \
--jq '.[] | select(.archived == false) | .full_name' > "$part"; then
cat "$part" >> "$all"
else
log "FATAL: could not list the repositories of ${owner}: users/${owner}/repos and orgs/${owner}/repos both failed."; rm -f "$all" "$part"; return 1
fi
done
case "$tok" in

Check failure on line 332 in scripts/apply-workflow-pins-remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add a default case (*) to handle unexpected values.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExo04a7Ylg7XFUFe&open=AaEeExo04a7Ylg7XFUFe&pullRequest=1211
ghs_*)
gh api --paginate 'installation/repositories?per_page=100' \
--jq '.repositories[] | select(.archived | not) | .full_name' > "$part" \
|| { log "FATAL: an App installation token could not list installation/repositories."; rm -f "$all" "$part"; return 1; }
# One installation belongs to one account; keep only the owners being
# walked, so --owners narrows the census under an App token as well.
for owner in ${OWNERS//,/ }; do
awk -v o="${owner,,}/" 'index(tolower($0), o) == 1' "$part" >> "$all"
done
;;
esac
sort -u "$all"
rm -f "$all" "$part"
}

# fetch_workflows <repo> <destdir> β€” download .github/workflows/*.y*ml.
Expand Down Expand Up @@ -480,7 +513,12 @@

WORKDIR=$(mktemp -d); trap 'rm -rf "${WORKDIR:-}"' EXIT
local repos n=0
if [ -n "$ONLY_REPO" ]; then repos="$ONLY_REPO"; else repos=$(list_repos); fi
if [ -n "$ONLY_REPO" ]; then

Check failure on line 516 in scripts/apply-workflow-pins-remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExo04a7Ylg7XFUFf&open=AaEeExo04a7Ylg7XFUFf&pullRequest=1211
repos="$ONLY_REPO"
elif ! repos=$(list_repos); then
log "FATAL: repository enumeration failed for ${OWNERS}. Refusing to report a partial census."
exit 1
fi
[ -n "$repos" ] || { log "FATAL: enumerated zero repositories for ${OWNERS} (rate limit or auth?). Refusing to report an empty census."; exit 1; }

local repo
Expand Down
282 changes: 282 additions & 0 deletions tests/test_apply_workflow_pins_remote.sh
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,288 @@
*) fail "mutant 'fetch_fail_open' stayed GREEN" ;; esac
fi

# --- 4. list_repos sees every repository the credential can see ---------------
# Under a GitHub App installation token (ghs_), users/<o>/repos and
# orgs/<o>/repos return PUBLIC repositories only, so the private repositories the
# App can write never reached the census (finding 2026-10-08). The cure ADDS
# installation/repositories. It must not REPLACE the public listing: GITHUB_TOKEN
# is ghs_ too, its installation is one repository, and the scheduled audit runs
# on it while no App is configured.
echo "== 4. enumeration under App, GITHUB_TOKEN and PAT credentials =="
command -v jq >/dev/null || { fail "jq is required by section 4"; exit 1; }
T="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
LSTUB="$TMP/lstub"; mkdir -p "$LSTUB"
cat > "$LSTUB/gh" <<'EOF'
#!/usr/bin/env bash
# gh β€” test double serving repository listings and workflow trees from
# $GH_FIX, and modelling which token kinds may call installation/repositories.
echo "$*" >> "$GH_FIX/calls.log"
[ "${1:-} ${2:-}" = "auth status" ] && exit 0
[ "${1:-}" = api ] || exit 64
shift
path="" jqx="" gql=0
while [ $# -gt 0 ]; do
case "$1" in
--jq|-q) jqx="$2"; shift ;;
-F|-f|-H) shift ;;
-*) ;;
graphql) gql=1 ;;
*) [ -n "$path" ] || path="$1" ;;
esac
shift
done
# refuse β€” fail the way gh does on a non-2xx response: message on stderr, rc 1.
refuse() { echo "gh: $2 (HTTP $1)" >&2; exit 1; }
if [ "$gql" = 1 ]; then
# Every repository holds one workflow, pinned FRESH at $TARGET.
jq -n --arg sha "$TARGET" '{data: {repository: {object: {entries: [{name: "ci.yml", type: "blob",
object: {text: ("jobs:\n a:\n uses: hyperpolymath/standards/.github/workflows/x.yml@" + $sha + "\n")}}]}}}}'
exit 0
fi
p="${path%%\?*}"
case "$p" in
users/*/repos|orgs/*/repos)
kind="${p%%/*}"; o="${p#*/}"; o="${o%/repos}"
[ -f "$GH_FIX/${kind}_fail_$o" ] && refuse 403 "API rate limit exceeded"
body="$GH_FIX/${kind}_$o.json" ;;
installation/repositories)
case "${GH_TOKEN:-}" in ghs_*) ;; *) refuse 403 "This endpoint requires an installation access token" ;; esac
[ -f "$GH_FIX/inst_fail" ] && refuse 502 "Bad Gateway"
body="$GH_FIX/inst.json" ;;
*) refuse 404 "Not Found" ;;
esac
[ -f "$body" ] || refuse 404 "Not Found"
if [ -n "$jqx" ]; then jq -r "$jqx" "$body"; else cat "$body"; fi
EOF
chmod +x "$LSTUB/gh"

# Mutants are sourced, and the applier sources lib/ beside itself.
MUT="$TMP/mut"; mkdir -p "$MUT"
ln -s "$(cd "$(dirname "$APPLIER")" && pwd)/lib" "$MUT/lib"

# fixture_repos <file> <owner/name:archived>... β€” write a REST repository list.
fixture_repos() {

Check warning on line 246 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFg&open=AaEeExyr4a7Ylg7XFUFg&pullRequest=1211
local f="$1"; shift
printf '%s\n' "$@" \
| jq -R 'split(":") | {full_name: .[0], archived: (.[1] == "true")}' | jq -s . > "$f"
}

# new_case <label> β€” make a fixture directory holding the two-owner estate every
# case starts from, and print its path. hyperpolymath has a public and an
# archived repository, metadatastician one public one, and the App installation
# on hyperpolymath holds the public one, a PRIVATE one and an archived one.
new_case() {

Check warning on line 256 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFh&open=AaEeExyr4a7Ylg7XFUFh&pullRequest=1211
local d; d=$(mktemp -d "$TMP/list.$1.XXXX")
fixture_repos "$d/users_hyperpolymath.json" hyperpolymath/pub-a:false hyperpolymath/old:true
fixture_repos "$d/users_metadatastician.json" metadatastician/pub-c:false
fixture_repos "$d/inst.repos" hyperpolymath/pub-a:false hyperpolymath/priv-b:false hyperpolymath/arch-p:true
jq '{total_count: length, repositories: .}' "$d/inst.repos" > "$d/inst.json"
echo "$d"
}

# run_list <dir> <token> <owners> <applier> β€” run list_repos against the listing
# stub; stdout to <dir>/out, stderr to <dir>/err, exit status to <dir>/rc.
run_list() {

Check warning on line 267 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFl&open=AaEeExyr4a7Ylg7XFUFl&pullRequest=1211
local d="$1"
: > "$d/calls.log"
# shellcheck disable=SC2016 # $1 and $2 are expanded by the inner shell
env PATH="$LSTUB:$PATH" GH_FIX="$d" GH_TOKEN="$2" GITHUB_TOKEN= \

Check warning on line 271 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFi&open=AaEeExyr4a7Ylg7XFUFi&pullRequest=1211
bash -c 'source "$1"; OWNERS="$2"; list_repos' _ "$4" "$3" > "$d/out" 2> "$d/err"

Check warning on line 272 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFk&open=AaEeExyr4a7Ylg7XFUFk&pullRequest=1211

Check warning on line 272 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFj&open=AaEeExyr4a7Ylg7XFUFj&pullRequest=1211
echo $? > "$d/rc"
}

# run_main <dir> <token> <applier> β€” run the whole applier in audit mode against
# the stub, with only the network ancestry proof stubbed out.
run_main() {

Check warning on line 278 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFo&open=AaEeExyr4a7Ylg7XFUFo&pullRequest=1211
local d="$1"
: > "$d/calls.log"
# shellcheck disable=SC2016 # $1 and $2 are expanded by the inner shell
env PATH="$LSTUB:$PATH" GH_FIX="$d" GH_TOKEN="$2" GITHUB_TOKEN= TARGET="$T" \

Check warning on line 282 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFm&open=AaEeExyr4a7Ylg7XFUFm&pullRequest=1211
bash -c 'source "$1"; validate_target() { return 0; }; shift; main "$@"' _ "$3" \

Check warning on line 283 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFn&open=AaEeExyr4a7Ylg7XFUFn&pullRequest=1211
--to "$T" --owners hyperpolymath,metadatastician > "$d/out" 2> "$d/err"
echo $? > "$d/rc"
}

# expect_list <label> <dir> <want-rc> <repo>... β€” require exactly these
# repositories, each once and sorted, and exactly this exit status.
expect_list() {

Check warning on line 290 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFr&open=AaEeExyr4a7Ylg7XFUFr&pullRequest=1211
local label="$1" d="$2" want_rc="$3"; shift 3
local want got
want=$(printf '%s\n' "$@" | sed '/^$/d' | sort)
got=$(cat "$d/out")
if [ "$(cat "$d/rc")" = "$want_rc" ] && [ "$got" = "$want" ]; then

Check failure on line 295 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFp&open=AaEeExyr4a7Ylg7XFUFp&pullRequest=1211

Check failure on line 295 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFq&open=AaEeExyr4a7Ylg7XFUFq&pullRequest=1211
pass "list: $label"
else
fail "list: $label β€” rc=$(cat "$d/rc") (want $want_rc); got [${got//$'\n'/ }] want [${want//$'\n'/ }]"
fi
}

# case_app <applier> β€” a dedicated App's token: the public listings plus the
# installation's private repository, archived ones dropped, each listed once.
case_app() {

Check warning on line 304 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFt&open=AaEeExyr4a7Ylg7XFUFt&pullRequest=1211
local d; d=$(new_case app)
run_list "$d" ghs_app hyperpolymath,metadatastician "$1"

Check warning on line 306 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFs&open=AaEeExyr4a7Ylg7XFUFs&pullRequest=1211
expect_list "App token adds the installation's private repository" "$d" 0 \
hyperpolymath/priv-b hyperpolymath/pub-a metadatastician/pub-c
}

# case_github_token <applier> β€” GITHUB_TOKEN is ghs_ too, and its installation
# is this one repository: the public listings must survive alongside it.
case_github_token() {

Check warning on line 313 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFv&open=AaEeExyr4a7Ylg7XFUFv&pullRequest=1211
local d; d=$(new_case gtok)
fixture_repos "$d/users_hyperpolymath.json" hyperpolymath/pub-a:false hyperpolymath/standards:false
fixture_repos "$d/inst.repos" hyperpolymath/standards:false
jq '{total_count: length, repositories: .}' "$d/inst.repos" > "$d/inst.json"
run_list "$d" ghs_gtok hyperpolymath,metadatastician "$1"

Check warning on line 318 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFu&open=AaEeExyr4a7Ylg7XFUFu&pullRequest=1211
expect_list "GITHUB_TOKEN keeps the public census" "$d" 0 \
hyperpolymath/pub-a hyperpolymath/standards metadatastician/pub-c
}

# case_pat <applier> β€” a PAT keeps the public listings and never calls the
# installation endpoint, which would refuse it.
case_pat() {

Check warning on line 325 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFx&open=AaEeExyr4a7Ylg7XFUFx&pullRequest=1211
local d; d=$(new_case pat)
run_list "$d" ghp_pat hyperpolymath,metadatastician "$1"

Check warning on line 327 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFw&open=AaEeExyr4a7Ylg7XFUFw&pullRequest=1211
expect_list "PAT lists the public repositories" "$d" 0 hyperpolymath/pub-a metadatastician/pub-c
if grep -q 'installation/repositories' "$d/calls.log"; then
fail "list: PAT called installation/repositories"
else
pass "list: PAT never calls installation/repositories"
fi
}

# case_owner_filter <applier> β€” --owners narrows the census under an App token
# too: the installation's hyperpolymath repositories must not leak in.
case_owner_filter() {

Check warning on line 338 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFz&open=AaEeExyr4a7Ylg7XFUFz&pullRequest=1211
local d; d=$(new_case owners)
run_list "$d" ghs_app metadatastician "$1"

Check warning on line 340 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUFy&open=AaEeExyr4a7Ylg7XFUFy&pullRequest=1211
expect_list "--owners metadatastician admits no installation repo of hyperpolymath" "$d" 0 \
metadatastician/pub-c
}

# case_org_fallback <applier> β€” an owner whose users/ listing 404s is listed
# through orgs/.
case_org_fallback() {

Check warning on line 347 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF1&open=AaEeExyr4a7Ylg7XFUF1&pullRequest=1211
local d; d=$(new_case orgs)
mv "$d/users_metadatastician.json" "$d/orgs_metadatastician.json"
run_list "$d" ghp_pat hyperpolymath,metadatastician "$1"

Check warning on line 350 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF0&open=AaEeExyr4a7Ylg7XFUF0&pullRequest=1211
expect_list "a users/ 404 falls back to orgs/" "$d" 0 hyperpolymath/pub-a metadatastician/pub-c
}

# case_inst_fail <applier> β€” a failed installation listing fails the whole
# enumeration, prints no repositories, and names the endpoint.
case_inst_fail() {

Check warning on line 356 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF3&open=AaEeExyr4a7Ylg7XFUF3&pullRequest=1211
local d; d=$(new_case instfail)
touch "$d/inst_fail"
run_list "$d" ghs_app hyperpolymath,metadatastician "$1"

Check warning on line 359 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF2&open=AaEeExyr4a7Ylg7XFUF2&pullRequest=1211
expect_list "a failed installation listing fails closed" "$d" 1
if grep -q 'installation/repositories' "$d/err"; then
pass "list: the failure names installation/repositories"
else
fail "list: the failure does not name installation/repositories"
fi
}

# case_public_fail <applier> β€” an owner whose public listing fails on both
# endpoints fails the enumeration, even though the installation listing worked.
case_public_fail() {

Check warning on line 370 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF5&open=AaEeExyr4a7Ylg7XFUF5&pullRequest=1211
local d; d=$(new_case pubfail)
touch "$d/users_fail_metadatastician" "$d/orgs_fail_metadatastician"
run_list "$d" ghs_app hyperpolymath,metadatastician "$1"

Check warning on line 373 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF4&open=AaEeExyr4a7Ylg7XFUF4&pullRequest=1211
expect_list "a rate-limited owner fails closed, not empty" "$d" 1
if grep -q 'metadatastician' "$d/err"; then
pass "list: the failure names the owner"
else
fail "list: the failure does not name the owner"
fi
}

# case_main_app <applier> β€” end to end: under an App token the private
# repository is fetched and classified, and appears in the census.
case_main_app() {

Check warning on line 384 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF8&open=AaEeExyr4a7Ylg7XFUF8&pullRequest=1211
local d; d=$(new_case mainapp)
run_main "$d" ghs_app "$1"

Check warning on line 386 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF6&open=AaEeExyr4a7Ylg7XFUF6&pullRequest=1211
if [ "$(cat "$d/rc")" = 0 ] && grep -qF "$(printf 'hyperpolymath/priv-b\tci.yml\tFRESH')" "$d/out"; then

Check failure on line 387 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF7&open=AaEeExyr4a7Ylg7XFUF7&pullRequest=1211
pass "main: the census classifies the private repository"
else
fail "main: private repository missing from the census (rc=$(cat "$d/rc"))"
sed 's/^/ /' "$d/err" | tail -5 >&2
fi
}

# case_main_fail <applier> β€” end to end: a failed enumeration stops the run,
# writes no census, and says the enumeration failed.
case_main_fail() {

Check warning on line 397 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add an explicit return statement at the end of the function.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF_&open=AaEeExyr4a7Ylg7XFUF_&pullRequest=1211
local d; d=$(new_case mainfail)
touch "$d/inst_fail"
run_main "$d" ghs_app "$1"

Check warning on line 400 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Assign this positional parameter to a local variable.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF9&open=AaEeExyr4a7Ylg7XFUF9&pullRequest=1211
if [ "$(cat "$d/rc")" = 1 ] && ! grep -q '^REPO' "$d/out" \

Check failure on line 401 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUF-&open=AaEeExyr4a7Ylg7XFUF-&pullRequest=1211
&& grep -q 'repository enumeration failed' "$d/err"; then
pass "main: a failed enumeration stops the run before any census"
else
fail "main: failed enumeration not reported as such (rc=$(cat "$d/rc"))"
fi
}

# Planted positives: the stub must be able to say no, or every fail-closed case
# above could pass because nothing ever failed.
d=$(new_case planted)
if env GH_FIX="$d" GH_TOKEN=ghp_pat "$LSTUB/gh" api installation/repositories >/dev/null 2>&1; then
fail "planted: stub let a PAT list installation/repositories"
else
pass "planted: stub refuses installation/repositories to a PAT"
fi
touch "$d/users_fail_metadatastician"
if env GH_FIX="$d" GH_TOKEN=ghs_app "$LSTUB/gh" api users/metadatastician/repos >/dev/null 2>&1; then
fail "planted: stub ignored a users_fail flag"
else
pass "planted: stub fails a flagged users/ listing"
fi

case_app "$APPLIER"
case_github_token "$APPLIER"
case_pat "$APPLIER"
case_owner_filter "$APPLIER"
case_org_fallback "$APPLIER"
case_inst_fail "$APPLIER"
case_public_fail "$APPLIER"
case_main_app "$APPLIER"
case_main_fail "$APPLIER"

# list_mutant <name> <sed-expr> <case-fn> β€” apply <sed-expr> to a copy of the
# applier, prove the edit landed and still parses, then require <case-fn> to
# report FAIL against it.
list_mutant() {
local name="$1" expr="$2" fn="$3"
local m="$MUT/mutant_${name}.sh" out
cp "$APPLIER" "$m"
sed -E -i "$expr" "$m"
if cmp -s "$APPLIER" "$m"; then
fail "mutant '$name' changed NOTHING β€” the sed did not match"; return
fi
if ! bash -n "$m" 2>"$MUT/${name}.parse"; then
fail "mutant '$name' is SYNTACTICALLY INVALID β€” its redness would be meaningless"
sed 's/^/ /' "$MUT/${name}.parse" >&2; return

Check warning on line 447 in tests/test_apply_workflow_pins_remote.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of using the literal 's/^/ /' 5 times.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaEeExyr4a7Ylg7XFUGA&open=AaEeExyr4a7Ylg7XFUGA&pullRequest=1211
fi
out=$("$fn" "$m" 2>&1)
case "$out" in
*FAIL*) pass "mutant '$name' killed by $fn" ;;
*) fail "mutant '$name' stayed GREEN under $fn" ;;
esac
}

# shellcheck disable=SC2016 # the ${…} and $(…) below are sed text to match
{
list_mutant app_token_blind 's@^ ghs_\*\)$@ NOT_A_TOKEN_PREFIX*)@' case_app
list_mutant replace_not_union \
'0,\@^ for owner in \$\{OWNERS//,/ \}; do$@s@@&\n case "$tok" in ghs_*) continue ;; esac@' \
case_github_token
list_mutant no_dedupe 's@^ sort -u "\$all"$@ cat "$all"@' case_app
list_mutant owner_filter_dropped "s@'index\\(tolower\\(\\\$0\\), o\\) == 1'@'1'@" case_owner_filter
list_mutant inst_failure_swallowed 's@\|\| \{ log "FATAL: an App installation token[^}]*\}@|| true@' case_inst_fail
list_mutant public_failure_swallowed 's@^ log "FATAL: could not list the repositories of.*$@ :@' case_public_fail
}

echo
if [ "$rc" -ne 0 ]; then echo "RESULT: FAILED" >&2; else echo "RESULT: all checks passed"; fi
exit $rc
Loading