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
50 changes: 49 additions & 1 deletion scripts/deploy-standard-workflows.sh
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,41 @@ fetch_existing() {
printf '%s\t%s' "$sha" "$decoded"
}

# template_requires_s7635_marker <template> -> 0 if the template carries a REAL
# `secrets: inherit` YAML line (indented key, not a `#`-comment/prose mention). Such
# stubs hand the reusable every org secret and must carry the inline
# `# NOSONAR(githubactions:S7635)` marker, else SonarCloud re-flags any consumer that
# copied the marker-less stub (#875/#876). Anchors `secrets:` to start-of-line-after-
# indent — mirrors the s7635-secrets-inherit.bats template guard.
template_requires_s7635_marker() {
grep -qE '^[[:space:]]*secrets:[[:space:]]+inherit([[:space:]]|$)' "$1"
}

# stub_has_s7635_marker — 0 if the stub content on stdin carries the
# `# NOSONAR(githubactions:S7635)` marker on a real `secrets: inherit` line.
stub_has_s7635_marker() {
grep -qE '^[[:space:]]*secrets:[[:space:]]+inherit[[:space:]].*NOSONAR\(githubactions:S7635\)'
}

# is_already_compliant <existing_content> <template> <repo> -> 0 if the deployed
# stub needs no re-deploy. A stub is compliant only when it is BOTH pin-compliant
# (is_pin_compliant, below) AND — when its template carries a real `secrets: inherit`
# line — still carries the S7635 NOSONAR marker on that line. A pin-correct stub that
# dropped the marker is DRIFT (#877): #875/#876 restored the marker in the templates
# but not the driver, so a re-sweep skipped already-pinned consumers (broodminder-
# export, bmad-bgreat-suite, …) whose stubs merged marker-less during #857. Flagging
# the missing marker as drift re-deploys and restores it. Kept targeted (pin + marker
# presence), NOT a byte-compare, to avoid churn on cosmetic diffs.
is_already_compliant() {
local existing_content="$1" template="$2" repo="$3"
is_pin_compliant "$existing_content" "$template" "$repo" || return 1
if template_requires_s7635_marker "$template" \
&& ! stub_has_s7635_marker <<< "$existing_content"; then
return 1
Comment thread
qodo-code-review[bot] marked this conversation as resolved.
fi
Comment thread
don-petry marked this conversation as resolved.
return 0
}
Comment thread
don-petry marked this conversation as resolved.

# True if the existing decoded content already has the canonical uses: reference
# for this workflow (extracted from the template itself, so it tracks version bumps).
#
Expand All @@ -284,7 +319,7 @@ fetch_existing() {
# the shared ring model accepts for THIS repo (its tier channel + the transitional
# legacy grace) — so the sweep never reverts an intentional ring/next pin. Non-ring
# templates (e.g. add-to-project, not in RING_REUSABLES) keep the exact-match rule.
is_already_compliant() {
is_pin_compliant() {
local existing_content="$1" template="$2" repo="$3"
local expected_uses
expected_uses=$(grep -E '^[[:space:]]*uses:' "$template" | head -1 | sed 's/^[[:space:]]*uses:[[:space:]]*//' | sed 's/[[:space:]]*#.*//' | tr -d '\r' || true)
Expand Down Expand Up @@ -460,6 +495,19 @@ deploy_repo() {
fi
fi

# When repin_source is a copy of existing_content (meta-repo consumer or body-
# preserving repin-in-place) and the template requires the S7635 marker but the
# copy lacks it, inject the marker now. Without this, the deployed stub would
# still be marker-less after the PR lands and is_already_compliant would flag it
# as drift again on every subsequent sweep — an infinite redeployment loop (#878).
if [[ "$repin_source" != "$template" ]] && [[ "$DRY_RUN" != "true" ]]; then
if template_requires_s7635_marker "$template" && ! stub_has_s7635_marker < "$repin_source"; then
local patched; patched="$(mktemp)"; _TMPFILES+=("$patched")
sed -E 's/^([[:space:]]*secrets:[[:space:]]+inherit)([[:space:]]*#.*)?$/\1 # NOSONAR(githubactions:S7635) first-party trusted reusable/' "$repin_source" > "$patched"
repin_source="$patched"
fi
fi

if [[ -n "$existing_sha" ]] && [[ "$FORCE" == "false" ]] && is_already_compliant "$existing_content" "$template" "$repo"; then
skip "$repo/$target_path already compliant"
continue
Expand Down
4 changes: 3 additions & 1 deletion test/scripts/deploy-standard-workflows/dry-run.bats
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ STUB
# ring1 repo legitimately pins @auto-rebase/ring1. The sweep must treat that as
# compliant and NOT plan a PR reverting it to stable.
stub_pinning() { # <ref> → base64 of a minimal stub pinning the reusable at <ref>
# Carries the S7635 marker — a converged consumer's shape after #875/#876 — so the
# ring-awareness fixtures below are not tripped by the marker-drift check (#877).
local body="jobs:
auto-rebase:
uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@$1
secrets: inherit"
secrets: inherit # NOSONAR(githubactions:S7635) first-party trusted reusable"
base64 -w 0 <<<"$body" 2>/dev/null || base64 -b 0 <<<"$body"
}

Expand Down
83 changes: 83 additions & 0 deletions test/scripts/deploy-standard-workflows/emit-vform.bats
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ channel_refs() { # <agent> <M> [extra refs...]
}

stub_pinning() { # <ref> → base64 of a minimal auto-rebase stub pinning the reusable at <ref>
# Carries the S7635 marker on `secrets: inherit` — the shape a converged consumer
# holds after #875/#876, so pin-drift fixtures are not falsely tripped by the
# marker-drift check (#877).
local body="jobs:
auto-rebase:
uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@$1
secrets: inherit # NOSONAR(githubactions:S7635) first-party trusted reusable"
base64 -w 0 <<<"$body" 2>/dev/null || base64 -b 0 <<<"$body"
}

stub_pinning_no_marker() { # <ref> → base64 of the SAME stub but marker-less (#857 shape)
local body="jobs:
auto-rebase:
uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@$1
Expand All @@ -90,6 +101,16 @@ devlead_stub_pinning() { # <ref> → base64 of a .github dev-lead CONSUMER stub
base64 -w 0 <<<"$body" 2>/dev/null || base64 -b 0 <<<"$body"
}

devlead_stub_pinning_with_marker() { # <ref> → base64 of the same stub but WITH the S7635 marker (#878 post-fix shape)
local body="jobs:
dev-lead:
uses: petry-projects/.github-private/.github/workflows/dev-lead-reusable.yml@$1
with:
agent_ref: $1
secrets: inherit # NOSONAR(githubactions:S7635) first-party trusted reusable"
base64 -w 0 <<<"$body" 2>/dev/null || base64 -b 0 <<<"$body"
}

selfhost_stub() { # <base> → base64 of a meta-repo SELF-HOST stub using a local ./ ref
local body="jobs:
$1:
Expand Down Expand Up @@ -162,6 +183,35 @@ selfhost_stub() { # <base> → base64 of a meta-repo SELF-HOST stub using a loc
echo "$output" | grep -qE 'Would open PR for TalkTerm .* auto-rebase.yml'
}

# ── #877: a pin-correct stub that DROPPED the S7635 marker is drift ─────────────
# #875/#876 restored the `# NOSONAR(githubactions:S7635)` marker in the templates
# but did NOT touch the driver, so a re-sweep skipped already-pinned consumers
# whose stubs merged marker-less during #857 (broodminder-export, bmad-bgreat-suite,
# …) — the restored marker never reached them. A pin-correct stub MISSING the marker
# is now drift so the sweep re-deploys and restores it.

@test "#877: flags a tier-correct stub that DROPPED the S7635 marker as drift" {
GH_MATCHING_REFS="$(channel_refs auto-rebase 2)"; export GH_MATCHING_REFS
# Pin is tier-correct for TalkTerm (ring1) but the `secrets: inherit` line lost the
# marker → drift → re-deploy to restore it.
GH_CONTENT_B64="$(stub_pinning_no_marker auto-rebase/v2-ring1)"; export GH_CONTENT_B64
install_gh_stub
run env GH_TOKEN=x bash "$SCRIPT" --dry-run --repo TalkTerm --workflow auto-rebase.yml
[ "$status" -eq 0 ]
! echo "$output" | grep -q 'already compliant'
echo "$output" | grep -qE 'Would open PR for TalkTerm .* auto-rebase.yml'
}

@test "#877: keeps a tier-correct stub that CARRIES the S7635 marker compliant (no churn)" {
GH_MATCHING_REFS="$(channel_refs auto-rebase 2)"; export GH_MATCHING_REFS
GH_CONTENT_B64="$(stub_pinning auto-rebase/v2-ring1)"; export GH_CONTENT_B64
install_gh_stub
run env GH_TOKEN=x bash "$SCRIPT" --dry-run --repo TalkTerm --workflow auto-rebase.yml
[ "$status" -eq 0 ]
echo "$output" | grep -q 'already compliant'
! echo "$output" | grep -q 'Would open PR'
}

# ── meta-repo consumer stubs (#704) ────────────────────────────────────────────
# The meta-repos (.github / .github-private) are exempt from blanket stub
# deployment because they self-host most reusables via local `./` refs. But they
Expand Down Expand Up @@ -225,3 +275,36 @@ refs/tags/dev-lead/v1-stable"
echo "$output" | grep -qi 'does not resolve'
! echo "$output" | grep -qi 'Would open PR'
}

# ── #878: marker injection for meta-repo consumer stubs prevents infinite churn ──
# When the driver re-pins a meta-repo consumer stub using repin_source=existing_content
# and that existing content lacks the S7635 marker, the deployed stub would be
# marker-less and is_already_compliant would flag it as drift again on the next sweep
# — an infinite redeployment loop. The fix (non-dry-run path) injects the marker into
# repin_source before computing deploy_template, so the PR's content is immediately
# compliant. The dry-run tests below verify the trigger condition (marker-absent →
# drift) and the post-fix compliant shape (marker-present → no churn).

@test "#878: meta-repo consumer stub at correct v-form but missing S7635 marker is drift" {
GH_MATCHING_REFS="$(channel_refs dev-lead 3)"; export GH_MATCHING_REFS
# .github (ring0) is at the correct @dev-lead/v3-ring0 pin but the S7635 marker
# is absent — the shape a PR opened without the fix would produce. Must be drift.
GH_CONTENT_B64="$(devlead_stub_pinning dev-lead/v3-ring0)"; export GH_CONTENT_B64
install_gh_stub
run env GH_TOKEN=x bash "$SCRIPT" --dry-run --repo .github --workflow dev-lead.yml
[ "$status" -eq 0 ]
! echo "$output" | grep -q 'already compliant'
echo "$output" | grep -qE 'Would open PR for \.github .* dev-lead.yml'
}

@test "#878: meta-repo consumer stub with S7635 marker at correct v-form is compliant (no churn after fix)" {
GH_MATCHING_REFS="$(channel_refs dev-lead 3)"; export GH_MATCHING_REFS
# .github (ring0) stub has the correct @dev-lead/v3-ring0 pin AND the S7635 marker
# — the shape the fix injects on re-deploy. Must be compliant on the next sweep.
GH_CONTENT_B64="$(devlead_stub_pinning_with_marker dev-lead/v3-ring0)"; export GH_CONTENT_B64
install_gh_stub
run env GH_TOKEN=x bash "$SCRIPT" --dry-run --repo .github --workflow dev-lead.yml
[ "$status" -eq 0 ]
echo "$output" | grep -q 'already compliant'
! echo "$output" | grep -q 'Would open PR'
}
Loading