From 14f48f43f5921bd4a8338503c8fa7673f27c1c9c Mon Sep 17 00:00:00 2001 From: donpetry-bot <281750570+donpetry-bot@users.noreply.github.com> Date: Mon, 13 Jul 2026 02:05:53 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20implement=20issue=20#606=20=E2=80=94=20?= =?UTF-8?q?Story=20(B):=20channel-ify=20feature-ideation=20+=20pr-auto-rev?= =?UTF-8?q?iew=20[#604]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/compliance-audit.sh | 10 +++--- scripts/deploy-standard-workflows.sh | 2 +- scripts/lib/ring-pins.sh | 2 ++ standards/workflows/pr-auto-review.yml | 22 ++++++------- .../centralized-stub-pins.bats | 33 ++++++++++++++++++- test/scripts/lib/ring-pins.bats | 11 ++++++- 6 files changed, 62 insertions(+), 18 deletions(-) diff --git a/scripts/compliance-audit.sh b/scripts/compliance-audit.sh index 431a69b8d..d562357f9 100755 --- a/scripts/compliance-audit.sh +++ b/scripts/compliance-audit.sh @@ -1241,11 +1241,12 @@ check_centralized_workflow_stubs() { # model": the expected channel is the repo's RING TIER # (next/ring0/ring1/stable — see ring_tier_for_repo), # e.g. `agent-shield/ring1` on a ring1 repo. Any other - # value is a fixed pin (e.g. feature-ideation → v1). + # value would be a fixed pin (e.g. `foo → v1`); every + # reusable below is now on the ring model (#606). # legacy-accepted-csv — additional refs still accepted *during* migration so # the audit neither flags nor reverts a stub mid-move. - # For RING reusables the per-repo legacy set (the - # `/stable` channel + v1,v2) is computed below. + # For RING reusables the per-repo legacy set (the other + # ring channels — higher tiers) is computed below. # NOTE: dev-lead.yml is intentionally NOT listed here — its reusable lives in # the private petry-projects/.github-private repo and is pinned to the # dev-lead/stable channel, validated by check_dev_lead_stub() below. @@ -1255,8 +1256,9 @@ check_centralized_workflow_stubs() { "dependabot-automerge.yml:dependabot-automerge-reusable:RING" "dependabot-rebase.yml:dependabot-rebase-reusable:RING" "agent-shield.yml:agent-shield-reusable:RING" - "feature-ideation.yml:feature-ideation-reusable:v1:" + "feature-ideation.yml:feature-ideation-reusable:RING" "pr-review-mention.yml:pr-review-mention-reusable:RING" + "pr-auto-review.yml:pr-auto-review-reusable:RING" ) # List the repo's workflow directory once instead of probing each file. diff --git a/scripts/deploy-standard-workflows.sh b/scripts/deploy-standard-workflows.sh index 130287845..865ac8bf5 100755 --- a/scripts/deploy-standard-workflows.sh +++ b/scripts/deploy-standard-workflows.sh @@ -160,7 +160,7 @@ fetch_existing() { # `/ring1`). For those reusables the stub is compliant when it pins ANY ref # 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, feature-ideation@v1) keep the exact-match rule. +# templates (e.g. add-to-project, not in RING_REUSABLES) keep the exact-match rule. is_already_compliant() { local existing_content="$1" template="$2" repo="$3" local expected_uses diff --git a/scripts/lib/ring-pins.sh b/scripts/lib/ring-pins.sh index c0bf0e8e5..31cea2899 100644 --- a/scripts/lib/ring-pins.sh +++ b/scripts/lib/ring-pins.sh @@ -29,6 +29,8 @@ readonly RING_REUSABLES=( agent-shield pr-review-mention dev-lead + feature-ideation + pr-auto-review ) # ring_tier_for_repo -> next|ring0|ring1|stable diff --git a/standards/workflows/pr-auto-review.yml b/standards/workflows/pr-auto-review.yml index be91ffa77..c7901d8ad 100644 --- a/standards/workflows/pr-auto-review.yml +++ b/standards/workflows/pr-auto-review.yml @@ -6,17 +6,17 @@ # AGENTS — READ BEFORE EDITING: # • This file is a THIN CALLER STUB. All readiness-gate logic lives in the # reusable workflow above. -# • You MAY change: the tag in the `uses:` line when upgrading the reusable -# workflow version (e.g. bump `@v2` → `@v3` when petry-projects/.github cuts -# a new release), and the workflow name(s) in `workflow_run.workflows` to -# match your repository's CI workflow name(s). -# • You MUST NOT change: trigger event types or the job-level `permissions:` -# block — reusable workflows can be granted no more permissions than the -# calling job, so removing the stanza breaks the reusable's gh API calls. +# • You MAY change: the workflow name(s) in `workflow_run.workflows` to match +# your repository's CI workflow name(s). +# • You MUST NOT change: the `@pr-auto-review/stable` channel in the `uses:` +# line — this reusable is on the org-wide moving-channel model (rollout and +# rollback are a single central tag move; a frozen `@vN`/`@` pin is +# rejected by the compliance audit). Nor the trigger event types or the +# job-level `permissions:` block — reusable workflows can be granted no more +# permissions than the calling job, so removing the stanza breaks the +# reusable's gh API calls. # • If you need different behaviour, open a PR against the reusable in the -# central repo. -# • When publishing a new version of this reusable, also update this template -# and open a fanout PR across all caller repos. +# central repo. The change will propagate everywhere on next run. # ───────────────────────────────────────────────────────────────────────────── # # PR Auto-Review — thin caller for the org-level reusable. @@ -50,6 +50,6 @@ jobs: pull-requests: read checks: read actions: read - uses: petry-projects/.github/.github/workflows/pr-auto-review-reusable.yml@v2 # NOSONAR(githubactions:S7637) first-party channel ref + uses: petry-projects/.github/.github/workflows/pr-auto-review-reusable.yml@pr-auto-review/stable # NOSONAR(githubactions:S7637) first-party channel ref secrets: GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} diff --git a/test/scripts/compliance-audit/centralized-stub-pins.bats b/test/scripts/compliance-audit/centralized-stub-pins.bats index 0a4414c5d..528b12da1 100644 --- a/test/scripts/compliance-audit/centralized-stub-pins.bats +++ b/test/scripts/compliance-audit/centralized-stub-pins.bats @@ -63,13 +63,44 @@ R="petry-projects/.github/.github/workflows/agent-shield-reusable.yml" } @test "with no legacy grace, only the canonical ref is accepted" { - # mirrors the feature-ideation entry (canonical @v1, empty legacy) + # A fixed-pin entry with an empty legacy CSV: only the exact canonical ref + # passes. (feature-ideation used this shape before #606 channel-ified it.) accept " uses: $R@v1" "v1" "" [ "$status" -eq 0 ] accept " uses: $R@v2" "v1" "" [ "$status" -ne 0 ] } +# --------------------------------------------------------------------------- +# #606 — feature-ideation and pr-auto-review are now RING reusables. Their +# stubs resolve the canonical pin through the same ring model as the others, +# so a `/stable` channel pin on a stable-tier repo is accepted and the +# pre-ring @v1/@v2 pin is rejected (grace dropped, #870). +# --------------------------------------------------------------------------- +accept_reusable() { + local reusable="$1" line="$2" canonical="$3" legacy="$4" + run bash -c 'source "$1" >/dev/null 2>&1; stub_pin_acceptable "$2" "$3" "$4" "$5"' \ + _ "$SCRIPT" "$line" "$reusable" "$canonical" "$legacy" +} + +@test "feature-ideation stub: @feature-ideation/stable accepted, @v1 rejected (#606)" { + local reusable="feature-ideation-reusable" + local ref="petry-projects/.github/.github/workflows/${reusable}.yml" + accept_reusable "$reusable" " uses: $ref@feature-ideation/stable" "feature-ideation/stable" "" + [ "$status" -eq 0 ] + accept_reusable "$reusable" " uses: $ref@v1" "feature-ideation/stable" "" + [ "$status" -ne 0 ] +} + +@test "pr-auto-review stub: @pr-auto-review/stable accepted, @v2 rejected (#606)" { + local reusable="pr-auto-review-reusable" + local ref="petry-projects/.github/.github/workflows/${reusable}.yml" + accept_reusable "$reusable" " uses: $ref@pr-auto-review/stable" "pr-auto-review/stable" "" + [ "$status" -eq 0 ] + accept_reusable "$reusable" " uses: $ref@v2" "pr-auto-review/stable" "" + [ "$status" -ne 0 ] +} + # --------------------------------------------------------------------------- # ring_tier_for_repo() — maps a repo to its canary-ring tier (epic #495). # --------------------------------------------------------------------------- diff --git a/test/scripts/lib/ring-pins.bats b/test/scripts/lib/ring-pins.bats index e695b4cb2..36314c477 100644 --- a/test/scripts/lib/ring-pins.bats +++ b/test/scripts/lib/ring-pins.bats @@ -23,10 +23,19 @@ setup() { ring_is_ring_reusable auto-rebase ring_is_ring_reusable pr-review-mention ring_is_ring_reusable dev-lead - ! ring_is_ring_reusable feature-ideation + # channel-ified in #606 (Story B of the shim-identity epic #604) + ring_is_ring_reusable feature-ideation + ring_is_ring_reusable pr-auto-review ! ring_is_ring_reusable add-to-project } +@test "ring_canonical_ref: feature-ideation and pr-auto-review resolve to tier channels (#606)" { + [ "$(ring_canonical_ref feature-ideation markets)" = "feature-ideation/stable" ] + [ "$(ring_canonical_ref feature-ideation TalkTerm)" = "feature-ideation/ring1" ] + [ "$(ring_canonical_ref pr-auto-review markets)" = "pr-auto-review/stable" ] + [ "$(ring_canonical_ref pr-auto-review TalkTerm)" = "pr-auto-review/ring1" ] +} + @test "ring_canonical_ref is the repo's tier channel" { [ "$(ring_canonical_ref agent-shield TalkTerm)" = "agent-shield/ring1" ] [ "$(ring_canonical_ref agent-shield markets)" = "agent-shield/stable" ]