Skip to content

[Phase 2] Bootstrap wrapper: scripts/bootstrap-new-repo.sh applies the full non-file policy surface #967

Closed

Description

@github-actions

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

  1. scripts/bootstrap-new-repo.sh owner/new-repo (DRY_RUN-aware) invokes scripts/apply-repo-settings.sh then scripts/apply-rulesets.sh --repo owner/new-repo in sequence, exits non-zero if either fails, and prints a clear pass/fail summary.
  2. 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-hoc main rulesets.
  3. It applies the standard label set, verifies the CODEOWNERS team (@petry-projects/org-leads as 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).
  4. 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.
  5. 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/*.sh passes.

Tasks / Subtasks

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 bats job (run via scripts/run-bats.sh); shellcheck runs --severity=warning -x over 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

Likely target surface

  • new script scripts/bootstrap-new-repo.sh
  • new ruleset .github/rulesets/pr-quality.json
  • new 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.

Activity

  1. don-petry commented on Jun 27, 2026

    @don-petry
    Collaborator

    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.sh orchestrator that brings a new repo to compliance by reusing the existing apply-repo-settings.sh and apply-rulesets.sh scripts (plus a net-new codified pr-quality ruleset), 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 + Integration dependabot-automerge-petry, both bypass_mode: always), mirroring code-quality.json. This is data apply-rulesets.sh consumes — no new logic.
    • scripts/bootstrap-new-repo.sh — set -euo pipefail orchestrator: bridges one DRY_RUN flag onto apply-repo-settings.sh (DEV_LEAD_DRY_RUN) and apply-rulesets.sh (DRY_RUN); runs apply-repo-settings then apply-rulesets.sh --repo owner/repo in sequence; applies the standard label set; verifies the CODEOWNERS team (@petry-projects/org-leads first 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 the bats job list.

    Tests to Write

    • tests/test_bootstrap_new_repo.bats (mirrors test_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.bats and bash scripts/dev-lead-lint.sh

  2. don-petry commented on Jun 27, 2026

    @don-petry
    Collaborator

    Dev-Lead: Implementation Complete

    Plan Execution

    • Codified .github/rulesets/pr-quality.json (net-new data for apply-rulesets.sh)
    • Authored scripts/bootstrap-new-repo.sh (orchestrator, fail-fast, DRY_RUN-bridged)
    • Added tests/test_bootstrap_new_repo.bats and registered it in lint.yml
    • shellcheck + full bats suite green

    Test Results

    # tests/test_bootstrap_new_repo.bats
    1..13
    ok 1 pr-quality.json: valid, branch target, active enforcement
    ok 2 pr-quality.json: bypass = OrganizationAdmin + Integration, both bypass_mode always
    ok 3 pr-quality.json: Integration bypass uses the dependabot-automerge app id (3167543)
    ok 4 pr-quality.json: pull_request rule — 1 approval, code-owner review, thread resolution, dismiss-stale, squash-only
    ok 5 pr-quality.json: targets the default branch — no legacy/ad-hoc 'main' literal
    ok 6 DRY_RUN: exits 0 and makes no write API calls
    ok 7 DRY_RUN: prints intent and a PASS summary
    ok 8 DRY_RUN: bridges the flag onto both sub-scripts (DEV_LEAD_DRY_RUN + DRY_RUN)
    ok 9 sequence: invokes apply-repo-settings then apply-rulesets --repo on success
    ok 10 fail-fast: apply-repo-settings failure stops before apply-rulesets and exits non-zero
    ok 11 fail-fast: apply-rulesets failure exits non-zero with a FAIL summary
    ok 12 summary: success prints a PASS summary naming the repo
    ok 13 errors when no repo argument is given
    
    # Full lint.yml bats suite: 847 ok, 0 not ok (exit 0)
    # scripts/dev-lead-lint.sh: shellcheck on 82 files + agent/CODEOWNERS validation — all checks passed
    

    Files Changed

    • scripts/bootstrap-new-repo.sh (new): set -euo pipefail orchestrator. Bridges one DRY_RUN flag onto apply-repo-settings.sh (DEV_LEAD_DRY_RUN) and apply-rulesets.sh (DRY_RUN). Runs, in sequence and fail-fast: (1) repo settings + security/GHAS + push protection via apply-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): codified pr-quality ruleset — pull_request rule (1 approval, code-owner review, required thread resolution, dismiss-stale, squash-only) targeting ~DEFAULT_BRANCH, with the two mandatory bypass actors (OrganizationAdmin + Integration app 3167543 = dependabot-automerge-petry, both bypass_mode: always), mirroring code-quality.json. No new logic — data apply-rulesets.sh already 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. Mirrors tests/test_apply_rulesets.bats.
    • .github/workflows/lint.yml: registered the new bats file in the bats job list.

    Notes

    • No policy reimplemented (AC4): the script is a thin orchestrator over the existing apply-* scripts; the only net-new artifact is pr-quality.json, which is data the existing apply-rulesets.sh reads. Required status checks remain carried by the code-quality.json ruleset data (applied in step 2), not re-wired by the bootstrap.
    • Required-status-check context list (AC3): I deliberately did not expand code-quality.json's required_status_checks to the fuller discussion list (Dev-Lead Agent / dev-lead, the CI pipeline name, coverage, Secret scan (gitleaks)). code-quality.json is live policy applied by default to petry-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 whatever code-quality.json carries.
    • Label set: a small, defensible baseline of org-automation labels (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.sh applies every .github/rulesets/*.json, so a bootstrapped repo also receives the sanctioned release-channel-tags ruleset — existing, intended behavior; no legacy/ad-hoc main ruleset is created.
  3. added a commit that references this issue on Jun 27, 2026
  4. added 18 commits that reference this issue on Aug 2, 2026
  5. added a commit that references this issue on Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickupinitiativeEpic / initiative tracking issue

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions