From bfdaa6393dcd99ee172ca894f7fbcebd187eaef9 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Wed, 17 Jun 2026 20:39:19 -0500 Subject: [PATCH 1/2] chore(deploy): enable add-to-project.yml stub deployment (#415) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `add-to-project.yml` to DEPLOYABLE_WORKFLOWS so the org-standard Initiatives caller stub deploys to consumer repos via the canonical mechanism (deploy-standard-workflows.sh), rather than hand-written stubs. The reusable now publishes the `add-to-project/stable` channel (add-to-project/v1.0.0 cut at the #466 merge), so the stub's pinned ref resolves at workflow startup. `.github` stays fully exempt — it hosts its own local-ref self-host caller (uses: ./.github/...), which a channel-pinned stub must not overwrite. `.github-private` self-manages its fleet but participates in the org board, so a narrow per-workflow SKIP_OVERRIDES lets it receive add-to-project.yml only, keeping it exempt from every other stub. No compliance impact: check_centralized_workflow_stubs keys off its own hardcoded list (not DEPLOYABLE_WORKFLOWS) and only validates stubs that already exist; add-to-project is not a required workflow. Refs #415, #414, #466. Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/deploy-standard-workflows.sh | 37 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/scripts/deploy-standard-workflows.sh b/scripts/deploy-standard-workflows.sh index ff5832062..a52c06732 100755 --- a/scripts/deploy-standard-workflows.sh +++ b/scripts/deploy-standard-workflows.sh @@ -29,9 +29,23 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" STANDARDS_DIR="$REPO_ROOT/standards/workflows" -# Repos to never touch. +# Repos exempt from blanket standard-workflow deployment. +# .github — self-host source of truth; its own callers use local refs +# (e.g. add-to-project.yml pins ./.github/...), which a +# channel-pinned stub must never overwrite. +# .github-private — self-manages its workflow fleet (dev-lead runs inline, etc). +# A repo here may still opt into a *specific* workflow via SKIP_OVERRIDES below. SKIP_REPOS=(".github" ".github-private") +# Per-workflow opt-ins for otherwise-skipped repos. Keyed by workflow filename; +# value is a space-separated list of SKIP_REPOS that should still receive it. +# .github-private participates in the org Initiatives board, so it receives the +# add-to-project.yml caller (the org board is a single shared target — the stub +# is identical for every repo) while staying exempt from all other stubs. +declare -A SKIP_OVERRIDES=( + ["add-to-project.yml"]=".github-private" +) + # Workflows deployable from standards/workflows/ verbatim. # Excludes ci.yml, sonarcloud.yml (tech-stack-specific) and # feature-ideation.yml (requires repo-specific project_context input). @@ -43,6 +57,7 @@ DEPLOYABLE_WORKFLOWS=( dependabot-automerge.yml dependabot-rebase.yml dependency-audit.yml + add-to-project.yml ) # --------------------------------------------------------------------------- @@ -84,6 +99,17 @@ is_skipped_repo() { return 1 } +# True if a normally-skipped repo has opted into this specific workflow via +# SKIP_OVERRIDES — lets a self-managed repo receive one stub while staying +# exempt from the rest. +repo_opts_into() { + local repo="$1" workflow="$2" r + for r in ${SKIP_OVERRIDES[$workflow]:-}; do + [[ "$repo" == "$r" ]] && return 0 + done + return 1 +} + # Fetch a file from the repo API in one call; outputs "shadecoded-content". # Returns empty string on 404. fetch_existing() { @@ -194,12 +220,11 @@ fi log "Deploying ${#WORKFLOWS[@]} workflow(s) to ${#REPOS[@]} repo(s)" for repo in "${REPOS[@]}"; do - if is_skipped_repo "$repo"; then - skip "$repo (exempt)" - continue - fi - for workflow in "${WORKFLOWS[@]}"; do + if is_skipped_repo "$repo" && ! repo_opts_into "$repo" "$workflow"; then + skip "$repo/$workflow (exempt)" + continue + fi deploy_workflow_to_repo "$repo" "$workflow" done done From b3bf213d1fcf2306e31278d17fe3a9f4ca6c0350 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Wed, 17 Jun 2026 20:43:20 -0500 Subject: [PATCH 2/2] =?UTF-8?q?chore(deploy):=20address=20review=20?= =?UTF-8?q?=E2=80=94=20robust=20opt-in=20split=20+=20tidy=20skip=20logs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - repo_opts_into: split the SKIP_OVERRIDES value via `read -r -a` instead of an unquoted expansion, so values are never subject to pathname expansion. - Deploy loop: a fully-exempt repo (no per-workflow opt-in among the targeted workflows) logs a single `SKIP (exempt)` line again, rather than one line per workflow; repos with an opt-in still skip per-workflow. Both per gemini-code-assist review on #477. (Top-level loop keeps plain vars — `local` is only valid inside a function.) Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/deploy-standard-workflows.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/scripts/deploy-standard-workflows.sh b/scripts/deploy-standard-workflows.sh index a52c06732..998034567 100755 --- a/scripts/deploy-standard-workflows.sh +++ b/scripts/deploy-standard-workflows.sh @@ -103,8 +103,16 @@ is_skipped_repo() { # SKIP_OVERRIDES — lets a self-managed repo receive one stub while staying # exempt from the rest. repo_opts_into() { - local repo="$1" workflow="$2" r - for r in ${SKIP_OVERRIDES[$workflow]:-}; do + local repo="$1" workflow="$2" + local opt_in="${SKIP_OVERRIDES[$workflow]:-}" + [[ -z "$opt_in" ]] && return 1 + + # Split the space-separated opt-in list into an array (read -r -a avoids the + # pathname expansion an unquoted expansion would be subject to). + local -a allowed_repos + read -r -a allowed_repos <<< "$opt_in" + local r + for r in "${allowed_repos[@]}"; do [[ "$repo" == "$r" ]] && return 0 done return 1 @@ -220,6 +228,22 @@ fi log "Deploying ${#WORKFLOWS[@]} workflow(s) to ${#REPOS[@]} repo(s)" for repo in "${REPOS[@]}"; do + # Fully-exempt repos (no per-workflow opt-in) skip with a single log line + # instead of one per workflow. + if is_skipped_repo "$repo"; then + opts_in_any=false + for w in "${WORKFLOWS[@]}"; do + if repo_opts_into "$repo" "$w"; then + opts_in_any=true + break + fi + done + if [[ "$opts_in_any" == "false" ]]; then + skip "$repo (exempt)" + continue + fi + fi + for workflow in "${WORKFLOWS[@]}"; do if is_skipped_repo "$repo" && ! repo_opts_into "$repo" "$workflow"; then skip "$repo/$workflow (exempt)"