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
343 changes: 343 additions & 0 deletions scripts/apply-branch-gates.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,343 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
#
# apply-branch-gates.sh — fill the `required_status_checks` rule of a
# repository's active branch ruleset with contexts DERIVED from what its
# default-branch runs actually emitted.
#
# WHY THIS EXISTS
# config/rulesets/README.adoc has said so outright since it was written:
# "the propagation mechanism is still missing by design, and this note is the
# reminder that a template fix without an applier is a half fix." Nothing in
# this repository read config/rulesets/gates.json as DATA — every reference
# was prose, or tests/test_governance_reusable_shape.sh asserting the file's
# contents. gates.json specified a derivation that no code performed.
# apply-tag-ruleset-canon.sh is the TAG applier; this is its branch sibling.
#
# CONTEXTS ARE DERIVED, NEVER TYPED
# config/rulesets/gates.json: "Contexts are never typed by hand." A typed
# context that nothing emits is a PHANTOM — it can never turn green, so it
# blocks the branch forever. This script therefore reads the check names the
# latest default-branch run of each gate workflow ACTUALLY produced:
# GET /repos/{o}/{r}/actions/workflows/{file}/runs?branch=<default>&per_page=1
# GET /repos/{o}/{r}/actions/runs/{id}/jobs
# and uses the job `name` verbatim. For a reusable caller GitHub already
# renders that as "<caller job id> / <reusable job name>".
#
# THE TWO REFUSALS THAT MATTER
# if_no_run_yet -> omit that file's contexts and REPORT it.
# Never write a context nothing has emitted.
# if_zero_contexts_overall -> do NOT write the rule at all; report UNGATED.
# A required_status_checks rule with an empty list
# is a VACUOUS GATE: it reports "protected" while
# requiring nothing. That is worse than no rule,
# because it is indistinguishable from a real one
# in every summary view.
#
# EXACTNESS GUARD
# A ruleset PUT REPLACES the whole object. This script therefore refuses to
# write unless the planned body, normalised over the required_status_checks
# rule alone, is byte-identical to the source. Anything else moved => refuse.
# Without this, one jq slip silently strips required_signatures estate-wide.
#
# WHAT IT DELIBERATELY DOES NOT DO
# * It never CREATES a ruleset. A repo with no active branch ruleset is
# reported NORULESET. Creating branch protection where none exists is a
# policy act, not a gate-fill.
# * It never DELETES or rewrites another rule. Repos carrying the retired
# types (update, required_deployments, code_quality, code_coverage) are
# REPORTED, not repaired: the estate census was ruled report-only. Pass
# --strip-retired to opt in, one repo at a time.
# * It never emits a retired rule type itself. The exactness guard makes that
# structurally impossible, not merely intended.
# * Two active branch rulesets => AMBIGUOUS, fail closed. Rulesets are
# ADDITIVE (see apply-tag-ruleset-canon.sh): writing one of a pair leaves
# the other enforcing, and the repo stays blocked by a rule nothing
# announced. Guessing which to fill is how that happens silently.
#
# Inputs (environment):
# GH_TOKEN required for writes; needs administration:write on targets.
# ESTATE_ORGS optional, space-separated. Default "metadatastician".
#
# Flags:
# --apply perform writes. WITHOUT IT THIS SCRIPT ONLY REPORTS.
# --repo OWNER/NAME process exactly one repository (repeatable).
# --limit N process at most N repositories (pilot runs).
# --gates-file F default config/rulesets/gates.json
# --strip-retired also remove the 4 retired rule types. Off by default.
# --require-green N drop any derived context that is not green across the
# last N default-branch runs of its workflow. Off (0) by
# default. Owner ruling on #956: "require the reliably-
# green set" -- a required context that is currently red
# blocks the branch the moment it is required, so gating
# on it converts a visible red into a merge deadlock.
# `skipped` and `neutral` COUNT AS GREEN: GitHub treats
# both as satisfying a required status check.
# --skip-user do not enumerate user/repos; use only ESTATE_ORGS.
#
# Output: TSV on stdout repo <TAB> state <TAB> detail
# per-class summary on stderr.
#
# Exit codes: 0 ok · 1 usage/refusal · 2 at least one repo FAILED
set -uo pipefail

RETIRED_TYPES='update required_deployments code_quality code_coverage'
ACTIONS_INTEGRATION_ID=15368

APPLY=0 LIMIT=0 STRIP_RETIRED=0 SKIP_USER=0 REQUIRE_GREEN=0
GATES_FILE='config/rulesets/gates.json'
REPOS_EXPLICIT=()

die() { printf '%s\n' "$*" >&2; exit 1; }

while [ $# -gt 0 ]; do

Check failure on line 93 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUX&open=AaDK-csPPlHkxrhvECUX&pullRequest=1011
case "$1" in
--apply) APPLY=1 ;;
--repo) shift; [ $# -gt 0 ] || die 'usage: --repo OWNER/NAME'; REPOS_EXPLICIT+=("$1") ;;

Check failure on line 96 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUY&open=AaDK-csPPlHkxrhvECUY&pullRequest=1011
--limit) shift; [ $# -gt 0 ] || die 'usage: --limit N'; LIMIT="$1" ;;

Check failure on line 97 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUZ&open=AaDK-csPPlHkxrhvECUZ&pullRequest=1011
--gates-file) shift; [ $# -gt 0 ] || die 'usage: --gates-file PATH'; GATES_FILE="$1" ;;

Check failure on line 98 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUa&open=AaDK-csPPlHkxrhvECUa&pullRequest=1011
--strip-retired) STRIP_RETIRED=1 ;;
--require-green) shift; [ $# -gt 0 ] || die 'usage: --require-green N'; REQUIRE_GREEN="$1" ;;

Check failure on line 100 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUb&open=AaDK-csPPlHkxrhvECUb&pullRequest=1011
--skip-user) SKIP_USER=1 ;;
-h|--help) sed -n '2,70p' "$0"; exit 0 ;;
*) die "unknown flag: $1" ;;
esac
shift
done

[ -r "$GATES_FILE" ] || die "gates file not readable: $GATES_FILE"

Check failure on line 108 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUc&open=AaDK-csPPlHkxrhvECUc&pullRequest=1011
command -v gh >/dev/null || die 'gh is required'
command -v jq >/dev/null || die 'jq is required'

WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT

jq -e . "$GATES_FILE" >/dev/null 2>&1 || die "gates file is not valid JSON: $GATES_FILE"

jq -r '.never_required_workflows[]?' "$GATES_FILE" | sort -u > "$WORK/never_wf"
jq -r '.never_required_contexts[]?' "$GATES_FILE" | sort -u > "$WORK/never_ctx"

emit() { printf '%s\t%s\t%s\n' "$1" "$2" "$3"; printf '%s\n' "$2" >> "$WORK/states"; }

Check warning on line 119 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUd&open=AaDK-csPPlHkxrhvECUd&pullRequest=1011

# --- normalise away ONLY the required_status_checks rule, so a diff of the
# normalised forms proves nothing outside it moved.
# The required_status_checks rule is the INTENDED change, so it is removed from
# both sides before comparison -- including when it is being ADDED, where the
# two rule arrays legitimately differ in length. Everything else must match
# exactly. The rule's own contents are verified separately, after the write,
# by comparing the planned context set against what the API returns.
norm_rsc() {

Check warning on line 128 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUf&open=AaDK-csPPlHkxrhvECUf&pullRequest=1011
jq -S '.rules = ((.rules // []) | map(select(.type!="required_status_checks")))' "$1"

Check warning on line 129 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUe&open=AaDK-csPPlHkxrhvECUe&pullRequest=1011
}

# --- is $1 listed in never_required_contexts, whole or after the first " / "?
is_never_ctx() {
local c="$1" tail="${1#* / }"
command grep -qxF -- "$c" "$WORK/never_ctx" && return 0
[ "$tail" != "$c" ] && command grep -qxF -- "$tail" "$WORK/never_ctx" && return 0

Check failure on line 136 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUg&open=AaDK-csPPlHkxrhvECUg&pullRequest=1011
return 1
}

# ---------------------------------------------------------------- repo list
if [ "${#REPOS_EXPLICIT[@]}" -gt 0 ]; then

Check failure on line 141 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUh&open=AaDK-csPPlHkxrhvECUh&pullRequest=1011
printf '%s\n' "${REPOS_EXPLICIT[@]}" > "$WORK/repos"
else
: > "$WORK/repos"
[ "$SKIP_USER" = 1 ] || gh repo list --limit 1000 --json nameWithOwner,isArchived \

Check failure on line 145 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUi&open=AaDK-csPPlHkxrhvECUi&pullRequest=1011
--jq '.[]|select(.isArchived|not)|.nameWithOwner' >> "$WORK/repos" 2>/dev/null
printf '%s\n' ${ESTATE_ORGS:-metadatastician} | while IFS= read -r ORG; do
[ -n "$ORG" ] || continue

Check failure on line 148 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUj&open=AaDK-csPPlHkxrhvECUj&pullRequest=1011
gh repo list "$ORG" --limit 1000 --json nameWithOwner,isArchived \
--jq '.[]|select(.isArchived|not)|.nameWithOwner' >> "$WORK/repos" 2>/dev/null
done
sort -u "$WORK/repos" -o "$WORK/repos"
fi

[ -s "$WORK/repos" ] || die 'refusing to report a clean sweep over nothing: target list is empty'

Check failure on line 155 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUk&open=AaDK-csPPlHkxrhvECUk&pullRequest=1011
[ "$LIMIT" -gt 0 ] 2>/dev/null && head -n "$LIMIT" "$WORK/repos" > "$WORK/r2" && mv "$WORK/r2" "$WORK/repos"

Check failure on line 156 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUl&open=AaDK-csPPlHkxrhvECUl&pullRequest=1011

printf '# mode=%s repos=%d gates=%s\n' \
"$( [ "$APPLY" = 1 ] && echo APPLY || echo REPORT-ONLY )" "$(wc -l < "$WORK/repos")" "$GATES_FILE" >&2

Check failure on line 159 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUm&open=AaDK-csPPlHkxrhvECUm&pullRequest=1011
printf 'repo\tstate\tdetail\n'
: > "$WORK/states"

# ---------------------------------------------------------------- main loop
while IFS= read -r R; do
[ -n "$R" ] || continue

Check failure on line 165 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUn&open=AaDK-csPPlHkxrhvECUn&pullRequest=1011

gh api "repos/$R" > "$WORK/repo.json" 2>"$WORK/e" \
|| { emit "$R" "UNKNOWN" "repo GET failed: $(head -c 100 "$WORK/e" | tr -d '\n')"; continue; }
DEF=$(jq -r '.default_branch // empty' "$WORK/repo.json")
[ -n "$DEF" ] || { emit "$R" "UNKNOWN" 'no default branch (empty repo?)'; continue; }

Check failure on line 170 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUo&open=AaDK-csPPlHkxrhvECUo&pullRequest=1011

# ---- 1. which gate workflow FILES apply (profiles) --------------------
gh api "repos/$R/contents/.github/workflows" --jq '.[]?|.name' 2>/dev/null | sort -u > "$WORK/wf" || : > "$WORK/wf"
gh api "repos/$R/contents" --jq '.[]?|.name' 2>/dev/null | sort -u > "$WORK/root" || : > "$WORK/root"

: > "$WORK/gatewf"
jq -r '.profiles | to_entries[] | @base64' "$GATES_FILE" > "$WORK/profiles"
while IFS= read -r P64; do
P=$(printf '%s' "$P64" | base64 -d)
KEY=$(printf '%s' "$P" | jq -r '.key')
ACTIVE=0
if [ "$KEY" = base ]; then

Check failure on line 182 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUp&open=AaDK-csPPlHkxrhvECUp&pullRequest=1011
ACTIVE=1
else
# detect: root-level files/globs
while IFS= read -r PAT; do
[ -n "$PAT" ] || continue

Check failure on line 187 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUq&open=AaDK-csPPlHkxrhvECUq&pullRequest=1011
while IFS= read -r F; do
case "$F" in $PAT) ACTIVE=1 ;; esac

Check failure on line 189 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUr&open=AaDK-csPPlHkxrhvECUr&pullRequest=1011
done < "$WORK/root"
done < <(printf '%s' "$P" | jq -r '.value.detect[]?')
# detect_workflows: presence of a workflow file
while IFS= read -r WFN; do
[ -n "$WFN" ] || continue

Check failure on line 194 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUs&open=AaDK-csPPlHkxrhvECUs&pullRequest=1011
command grep -qxF -- "$WFN" "$WORK/wf" && ACTIVE=1
done < <(printf '%s' "$P" | jq -r '.value.detect_workflows[]?')
fi
[ "$ACTIVE" = 1 ] || continue

Check failure on line 198 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUt&open=AaDK-csPPlHkxrhvECUt&pullRequest=1011
printf '%s' "$P" | jq -r '.value.gate_workflows[]?' >> "$WORK/gatewf"
done < "$WORK/profiles"

sort -u "$WORK/gatewf" -o "$WORK/gatewf"
# a gate workflow must exist in the repo AND not be never-required
: > "$WORK/gatewf2"
while IFS= read -r WFN; do
[ -n "$WFN" ] || continue

Check failure on line 206 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUu&open=AaDK-csPPlHkxrhvECUu&pullRequest=1011
command grep -qxF -- "$WFN" "$WORK/never_wf" && continue
command grep -qxF -- "$WFN" "$WORK/wf" || continue
printf '%s\n' "$WFN" >> "$WORK/gatewf2"
done < "$WORK/gatewf"

# ---- 2. DERIVE contexts from real runs --------------------------------
: > "$WORK/ctx"; NORUN=''
while IFS= read -r WFN; do
[ -n "$WFN" ] || continue

Check failure on line 215 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUv&open=AaDK-csPPlHkxrhvECUv&pullRequest=1011
RID=$(gh api "repos/$R/actions/workflows/$WFN/runs?branch=$DEF&per_page=1" \
--jq '.workflow_runs[0].id // empty' 2>/dev/null)
if [ -z "$RID" ]; then NORUN="${NORUN:+$NORUN,}$WFN"; continue; fi

Check failure on line 218 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUw&open=AaDK-csPPlHkxrhvECUw&pullRequest=1011
gh api "repos/$R/actions/runs/$RID/jobs?per_page=100" --paginate \
--jq '.jobs[]?|.name' 2>/dev/null >> "$WORK/ctx"
done < "$WORK/gatewf2"

sort -u "$WORK/ctx" -o "$WORK/ctx"
: > "$WORK/ctx2"; EXCLUDED=''
while IFS= read -r C; do
[ -n "$C" ] || continue

Check failure on line 226 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUx&open=AaDK-csPPlHkxrhvECUx&pullRequest=1011
if is_never_ctx "$C"; then EXCLUDED="${EXCLUDED:+$EXCLUDED,}$C"; continue; fi
printf '%s\n' "$C" >> "$WORK/ctx2"
done < "$WORK/ctx"

# ---- optional: keep only contexts that are RELIABLY green ------------
NOTGREEN=''
if [ "$REQUIRE_GREEN" -gt 0 ] 2>/dev/null; then

Check failure on line 233 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUy&open=AaDK-csPPlHkxrhvECUy&pullRequest=1011
: > "$WORK/bad"
while IFS= read -r WFN; do
[ -n "$WFN" ] || continue

Check failure on line 236 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECUz&open=AaDK-csPPlHkxrhvECUz&pullRequest=1011
gh api "repos/$R/actions/workflows/$WFN/runs?branch=$DEF&per_page=$REQUIRE_GREEN" \
--jq '.workflow_runs[]?.id' 2>/dev/null > "$WORK/rids"
while IFS= read -r RID2; do
[ -n "$RID2" ] || continue

Check failure on line 240 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU0&open=AaDK-csPPlHkxrhvECU0&pullRequest=1011
# a job is acceptable when success/skipped/neutral, or still running
gh api "repos/$R/actions/runs/$RID2/jobs?per_page=100" --paginate \
--jq '.jobs[]? | select((.conclusion // "pending") as $c
| ["success","skipped","neutral","pending"] | index($c) | not) | .name' \
2>/dev/null >> "$WORK/bad"
done < "$WORK/rids"
done < "$WORK/gatewf2"
sort -u "$WORK/bad" -o "$WORK/bad"
: > "$WORK/ctx3"
while IFS= read -r C; do
[ -n "$C" ] || continue

Check failure on line 251 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU1&open=AaDK-csPPlHkxrhvECU1&pullRequest=1011
if command grep -qxF -- "$C" "$WORK/bad"; then NOTGREEN="${NOTGREEN:+$NOTGREEN,}$C"; continue; fi
printf '%s\n' "$C" >> "$WORK/ctx3"
done < "$WORK/ctx2"
mv "$WORK/ctx3" "$WORK/ctx2"
fi

NCTX=$(wc -l < "$WORK/ctx2")
DETAIL="branch=$DEF gate_files=$(wc -l < "$WORK/gatewf2") contexts=$NCTX"
[ -n "$NOTGREEN" ] && DETAIL="$DETAIL not_green=[$NOTGREEN]"

Check failure on line 260 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU2&open=AaDK-csPPlHkxrhvECU2&pullRequest=1011
[ -n "$NORUN" ] && DETAIL="$DETAIL no_run=[$NORUN]"

Check failure on line 261 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU3&open=AaDK-csPPlHkxrhvECU3&pullRequest=1011
[ -n "$EXCLUDED" ] && DETAIL="$DETAIL excluded=[$EXCLUDED]"

Check failure on line 262 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU4&open=AaDK-csPPlHkxrhvECU4&pullRequest=1011

# ---- THE REFUSAL: a rule with an empty list is a vacuous gate ---------
if [ "$NCTX" -eq 0 ]; then

Check failure on line 265 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU5&open=AaDK-csPPlHkxrhvECU5&pullRequest=1011
emit "$R" "UNGATED" "$DETAIL — refusing to write an empty required_status_checks rule"
continue
fi

# ---- 3. locate the one active branch ruleset --------------------------
gh api "repos/$R/rulesets" > "$WORK/rs.json" 2>"$WORK/e" \
|| { emit "$R" "UNKNOWN" "rulesets GET failed"; continue; }
jq -r '.[]|select(.target=="branch" and .enforcement=="active")|.id' "$WORK/rs.json" > "$WORK/ids"
NIDS=$(wc -l < "$WORK/ids")
[ "$NIDS" -eq 0 ] && { emit "$R" "NORULESET" "$DETAIL — no active branch ruleset; this script never creates one"; continue; }

Check failure on line 275 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU6&open=AaDK-csPPlHkxrhvECU6&pullRequest=1011
[ "$NIDS" -gt 1 ] && { emit "$R" "AMBIGUOUS" "$DETAIL — $NIDS active branch rulesets ($(tr '\n' ',' < "$WORK/ids")); rulesets are additive, refusing to guess"; continue; }

Check failure on line 276 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU7&open=AaDK-csPPlHkxrhvECU7&pullRequest=1011
ID=$(cat "$WORK/ids")

gh api "repos/$R/rulesets/$ID" > "$WORK/live.json" 2>/dev/null \
|| { emit "$R" "UNKNOWN" "ruleset $ID GET failed"; continue; }

Check warning on line 280 in scripts/apply-branch-gates.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of using the literal 'UNKNOWN' 4 times.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_standards&issues=AaDK-csPPlHkxrhvECVE&open=AaDK-csPPlHkxrhvECVE&pullRequest=1011

FOUND_RETIRED=$(jq -r --arg rt "$RETIRED_TYPES" \
'[.rules[]?.type] as $t | ($rt|split(" ")) - (($rt|split(" ")) - $t) | join(",")' "$WORK/live.json")
[ -n "$FOUND_RETIRED" ] && DETAIL="$DETAIL retired_present=[$FOUND_RETIRED]"

Check failure on line 284 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU8&open=AaDK-csPPlHkxrhvECU8&pullRequest=1011

# ---- 4. build the PUT body -------------------------------------------
jq -R -s --argjson iid "$ACTIONS_INTEGRATION_ID" \
'split("\n")|map(select(length>0))|map({context:., integration_id:$iid})' "$WORK/ctx2" > "$WORK/checks.json"

jq --slurpfile ck "$WORK/checks.json" '
{name,target,enforcement,conditions,bypass_actors,rules}
| .rules = ((.rules // []) | map(select(.type!="required_status_checks")))
| .rules += [{ type:"required_status_checks",
parameters:{ strict_required_status_checks_policy:false,
do_not_enforce_on_create:false,
required_status_checks:$ck[0] } }]
' "$WORK/live.json" > "$WORK/put.json"

if [ "$STRIP_RETIRED" = 1 ]; then

Check failure on line 299 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU9&open=AaDK-csPPlHkxrhvECU9&pullRequest=1011
jq --arg rt "$RETIRED_TYPES" '($rt|split(" ")) as $r | .rules |= map(select(.type as $t | ($r|index($t))|not))' \
"$WORK/put.json" > "$WORK/p2" && mv "$WORK/p2" "$WORK/put.json"
fi

# structural assertion: we never emit a retired type that was not already there
EMITTED_RETIRED=$(jq -r --arg rt "$RETIRED_TYPES" \
'[.rules[]?.type] as $t | ($rt|split(" ")) - (($rt|split(" ")) - $t) | join(",")' "$WORK/put.json")
if [ "$STRIP_RETIRED" = 1 ] && [ -n "$EMITTED_RETIRED" ]; then

Check failure on line 307 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU-&open=AaDK-csPPlHkxrhvECU-&pullRequest=1011

Check failure on line 307 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECU_&open=AaDK-csPPlHkxrhvECU_&pullRequest=1011
emit "$R" "REFUSED" "$DETAIL — --strip-retired left [$EMITTED_RETIRED] in the body"; continue
fi

# ---- EXACTNESS GUARD (skipped when --strip-retired deliberately differs)
if [ "$STRIP_RETIRED" = 0 ]; then

Check failure on line 312 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECVA&open=AaDK-csPPlHkxrhvECVA&pullRequest=1011
jq '{name,target,enforcement,conditions,bypass_actors,rules}' "$WORK/live.json" > "$WORK/src.json"
if ! diff -q <(norm_rsc "$WORK/src.json") <(norm_rsc "$WORK/put.json") >/dev/null; then
emit "$R" "REFUSED" "$DETAIL — exactness guard: change outside the required_status_checks rule"
continue
fi
fi

if [ "$APPLY" = 0 ]; then

Check failure on line 320 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECVB&open=AaDK-csPPlHkxrhvECVB&pullRequest=1011
emit "$R" "WOULD-GATE" "$DETAIL ruleset=$ID :: $(tr '\n' '|' < "$WORK/ctx2")"
continue
fi

if ! gh api -X PUT "repos/$R/rulesets/$ID" --input "$WORK/put.json" >/dev/null 2>"$WORK/e"; then
emit "$R" "FAILED" "$DETAIL — PUT: $(head -c 160 "$WORK/e" | tr -d '\n')"; continue
fi

# ---- 5. post-write verification --------------------------------------
gh api "repos/$R/rulesets/$ID" > "$WORK/after.json" 2>/dev/null \
|| { emit "$R" "WROTE-UNVERIFIED" "$DETAIL — re-GET failed"; continue; }
PRE_BY=$(jq -cS '.bypass_actors//[]' "$WORK/live.json"); POST_BY=$(jq -cS '.bypass_actors//[]' "$WORK/after.json")
WANT=$(jq -cS '[.rules[]?|select(.type=="required_status_checks")|.parameters.required_status_checks[].context]|sort' "$WORK/put.json")
GOT=$(jq -cS '[.rules[]?|select(.type=="required_status_checks")|.parameters.required_status_checks[].context]|sort' "$WORK/after.json")
if [ "$PRE_BY" != "$POST_BY" ]; then emit "$R" "DRIFT" "$DETAIL — bypass_actors changed across the write"; continue; fi

Check failure on line 335 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECVC&open=AaDK-csPPlHkxrhvECVC&pullRequest=1011
if [ "$WANT" != "$GOT" ]; then emit "$R" "DRIFT" "$DETAIL — contexts after write != planned"; continue; fi

Check failure on line 336 in scripts/apply-branch-gates.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=AaDK-csPPlHkxrhvECVD&open=AaDK-csPPlHkxrhvECVD&pullRequest=1011
emit "$R" "GATED" "$DETAIL ruleset=$ID :: $(tr '\n' '|' < "$WORK/ctx2")"
done < "$WORK/repos"

echo '# summary' >&2
sort "$WORK/states" | uniq -c | sort -rn >&2
command grep -qx 'FAILED' "$WORK/states" && exit 2
exit 0
Loading
Loading