Repository navigation
[Phase 2] Bootstrap wrapper: scripts/bootstrap-new-repo.sh applies the full non-file policy surface #967
Copy link
Copy link
Closed
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Description
Story
As a developer who just created a repo from the template,
I want run a single DRY_RUN-aware bootstrap command that applies repo settings, security/GHAS + push protection, both sanctioned rulesets with bypass actors, required checks, labels, and CODEOWNERS by reusing the existing apply-* scripts,
so that the new repo reaches full compliance in one command instead of a multi-step manual runbook, with no policy reimplemented.
Acceptance Criteria
scripts/bootstrap-new-repo.sh owner/new-repo(DRY_RUN-aware) invokes scripts/apply-repo-settings.sh thenscripts/apply-rulesets.sh --repo owner/new-repoin sequence, exits non-zero if either fails, and prints a clear pass/fail summary.- It applies repo settings + security/GHAS + secret-scanning push protection (via apply-repo-settings.sh + scripts/lib/push-protection.sh) and the sanctioned rulesets pr-quality + code-quality — each carrying the mandatory bypass actors dependabot-automerge-petry (App) + OrganizationAdmin, both bypass_mode
always— and creates NO legacy/ad-hocmainrulesets. - It applies the standard label set, verifies the CODEOWNERS team (
@petry-projects/org-leadsas first owner), and wires required status checks to the repo's actual check contexts (CodeQL, SonarCloud,Dev-Lead Agent / dev-lead, the CI pipeline name, coverage,Secret scan (gitleaks),dependency-audit / Detect ecosystems— not the per-ecosystem jobs that skip). - No policy is reimplemented: the script orchestrates existing scripts, and any net-new artifact (e.g. a codified pr-quality.json) is data the existing apply-rulesets.sh consumes.
- A bats test (tests/test_bootstrap_new_repo.bats) covers the DRY_RUN path and the fail-fast + summary behavior, is registered in the lint.yml bats list, and
shellcheck --severity=warning -x scripts/*.shpasses.
Tasks / Subtasks
- Author scripts/bootstrap-new-repo.sh (set -euo pipefail) chaining apply-repo-settings.sh then apply-rulesets.sh --repo, with fail-fast and a pass/fail summary; bridge one DRY_RUN flag onto apply-repo-settings.sh's DEV_LEAD_DRY_RUN and apply-rulesets.sh's DRY_RUN. (AC: test issue from agent #1, Optimize review: small-PR and incremental fast paths #4)
- If no canonical pr-quality.json exists for apply-rulesets.sh to read, codify one matching the discussion's pr-quality spec (1 approval, code-owner review, required thread resolution, dismiss-stale-approvals, squash-only) with the two mandatory bypass actors, mirroring the bypass-actor + required-checks shape in .github/rulesets/code-quality.json. (AC: Go-live improvements for PR review agent #2)
- Add the standard label-set application, CODEOWNERS team verification, and required-status-check wiring to the real check contexts, reusing existing helpers where present. (AC: Add @claude delegation, auto-merge, and rebase handling #3)
- Add tests/test_bootstrap_new_repo.bats (mirroring tests/test_apply_rulesets.bats) and register it in the lint.yml bats job list. (AC: feat: add Copilot engine support via REVIEW_ENGINE toggle #5)
Dev Notes
- apply-rulesets.sh applies EVERY .github/rulesets/*.json to its --repo target; today only code-quality.json + release-channel-tags.json exist — there is NO pr-quality.json locally (verified). To satisfy "apply pr-quality + code-quality without reimplementation," pr-quality must first be codified as a ruleset JSON apply-rulesets can consume. (Where it should canonically live is an open question — see open_questions.)
- .github/rulesets/code-quality.json shows the exact shape to mirror: bypass_actors = [{actor_type: OrganizationAdmin, bypass_mode: always}, {actor_type: Integration, actor_id, bypass_mode: always}] and a required_status_checks rule with strict_required_status_checks_policy: true. The dependabot-automerge App's actor_id must be supplied for pr-quality's second bypass actor.
- apply-repo-settings.sh already handles security_and_analysis, check-suite auto-trigger disabling, and push protection (via scripts/lib/push-protection.sh); it needs a classic PAT in GH_TOKEN (OAuth rejected). It honors DEV_LEAD_DRY_RUN; apply-rulesets.sh honors DRY_RUN — bridge BOTH from one bootstrap flag.
- Required status check contexts must match the consumer's real check names. code-quality.json currently lists SonarCloud / CodeQL /
agent-shield / AgentShield/dependency-audit / Detect ecosystems; reconcile with the fuller list in the discussion when wiring checks. - Testing standard: bats tests live in tests/ and are listed in the lint.yml
batsjob (run via scripts/run-bats.sh); shellcheck runs--severity=warning -xover scripts/*.sh. Mirror tests/test_apply_rulesets.bats for the new test.
Project Structure Notes
Adds scripts/bootstrap-new-repo.sh + a bats test in tests/ + (likely) .github/rulesets/pr-quality.json in this repo. The script is a thin orchestrator over existing apply-* scripts — it must not duplicate their logic.
References
- scripts/apply-repo-settings.sh
- scripts/apply-rulesets.sh
- scripts/lib/push-protection.sh
- .github/rulesets/code-quality.json
- tests/test_apply_rulesets.bats
- .github/workflows/lint.yml
- scripts/run-bats.sh
- discussion Create a GitHub template repository to scaffold new petry-projects repos with org standards #962
Likely target surface
new script scripts/bootstrap-new-repo.shnew ruleset .github/rulesets/pr-quality.jsonnew test tests/test_bootstrap_new_repo.bats.github/workflows/lint.yml
Story prepared by the BMAD Scrum Master (Bob) for epic #964. Status: ready-for-dev.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
dev-leadFor dev-lead agent pickupFor dev-lead agent pickupinitiativeEpic / initiative tracking issueEpic / initiative tracking issue
Activity
don-petry commentedon Jun 27, 2026
Dev-Lead Implementation Plan
Issue: #967 — [Phase 2] Bootstrap wrapper: scripts/bootstrap-new-repo.sh applies the full non-file policy surface
Scope
Add a thin, DRY_RUN-aware
scripts/bootstrap-new-repo.shorchestrator that brings a new repo to compliance by reusing the existingapply-repo-settings.shandapply-rulesets.shscripts (plus a net-new codifiedpr-qualityruleset), with fail-fast sequencing and a pass/fail summary — reimplementing no policy.Implementation Checklist
.github/rulesets/pr-quality.json— codify the sanctioned pr-quality ruleset (1 approval, code-owner review, required thread resolution, dismiss-stale, squash-only) with the two mandatory bypass actors (OrganizationAdmin + Integrationdependabot-automerge-petry, bothbypass_mode: always), mirroringcode-quality.json. This is dataapply-rulesets.shconsumes — no new logic.scripts/bootstrap-new-repo.sh—set -euo pipefailorchestrator: bridges oneDRY_RUNflag ontoapply-repo-settings.sh(DEV_LEAD_DRY_RUN) andapply-rulesets.sh(DRY_RUN); runs apply-repo-settings thenapply-rulesets.sh --repo owner/repoin sequence; applies the standard label set; verifies the CODEOWNERS team (@petry-projects/org-leadsfirst owner); fail-fast (exit non-zero if any step fails) with a clear pass/fail summary. Sub-script paths overridable via env for testability..github/workflows/lint.yml— register the new bats test in thebatsjob list.Tests to Write
tests/test_bootstrap_new_repo.bats(mirrorstest_apply_rulesets.bats): DRY_RUN path makes no write calls + prints intent + exits 0; fail-fast stops after a failing step and exits non-zero; pass/fail summary is printed; pr-quality.json shape (bypass actors, squash-only, code-owner review, default-branch target).Test Command
scripts/run-bats.sh tests/test_bootstrap_new_repo.batsandbash scripts/dev-lead-lint.shdon-petry commentedon Jun 27, 2026
Dev-Lead: Implementation Complete
Plan Execution
.github/rulesets/pr-quality.json(net-new data forapply-rulesets.sh)scripts/bootstrap-new-repo.sh(orchestrator, fail-fast, DRY_RUN-bridged)tests/test_bootstrap_new_repo.batsand registered it inlint.ymlTest Results
Files Changed
scripts/bootstrap-new-repo.sh(new):set -euo pipefailorchestrator. Bridges oneDRY_RUNflag ontoapply-repo-settings.sh(DEV_LEAD_DRY_RUN) andapply-rulesets.sh(DRY_RUN). Runs, in sequence and fail-fast: (1) repo settings + security/GHAS + push protection viaapply-repo-settings.sh; (2)apply-rulesets.sh --repo owner/repo(applies pr-quality + code-quality + the existing release-channel-tags); (3) the standard label set; (4) CODEOWNERS-team verification. Prints a clear PASS/FAIL summary and exits non-zero if step 1 or 2 fails. Sub-script paths are env-overridable (APPLY_REPO_SETTINGS/APPLY_RULESETS) as a test seam..github/rulesets/pr-quality.json(new): codifiedpr-qualityruleset —pull_requestrule (1 approval, code-owner review, required thread resolution, dismiss-stale, squash-only) targeting~DEFAULT_BRANCH, with the two mandatory bypass actors (OrganizationAdmin + Integration app3167543= dependabot-automerge-petry, bothbypass_mode: always), mirroringcode-quality.json. No new logic — dataapply-rulesets.shalready consumes.tests/test_bootstrap_new_repo.bats(new): covers the DRY_RUN no-write path, fail-fast + summary behavior, ordered sequencing, and the pr-quality.json shape. Mirrorstests/test_apply_rulesets.bats..github/workflows/lint.yml: registered the new bats file in thebatsjob list.Notes
apply-*scripts; the only net-new artifact ispr-quality.json, which is data the existingapply-rulesets.shreads. Required status checks remain carried by thecode-quality.jsonruleset data (applied in step 2), not re-wired by the bootstrap.code-quality.json'srequired_status_checksto the fuller discussion list (Dev-Lead Agent / dev-lead, the CI pipeline name,coverage,Secret scan (gitleaks)).code-quality.jsonis live policy applied by default topetry-projects/.github-private, and the exact "CI pipeline name" context isn't resolvable from this repo — changing it here risks blocking merges on a non-existent check. Recommend reconciling the canonical check-context set in a focused follow-up (it edits shared live policy and warrants its own review). The bootstrap already applies whatevercode-quality.jsoncarries.needs-human-review,ack-test-deletion,dependencies,automerge) applied idempotently (gh label create --force); CODEOWNERS verification and label apply are best-effort (warn, don't hard-fail) so a transient/missing read doesn't abort an otherwise-compliant bootstrap.apply-rulesets.shapplies every.github/rulesets/*.json, so a bootstrapped repo also receives the sanctionedrelease-channel-tagsruleset — existing, intended behavior; no legacy/ad-hocmainruleset is created.feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…
feat: implement issue #967 — [Phase 2] Bootstrap wrapper: scripts/boo…