Skip to content

feat: add bootstrap-repo skill#266

Merged
jdfalk merged 1 commit intomainfrom
feat/bootstrap-repo-skill
Apr 25, 2026
Merged

feat: add bootstrap-repo skill#266
jdfalk merged 1 commit intomainfrom
feat/bootstrap-repo-skill

Conversation

@jdfalk
Copy link
Copy Markdown
Owner

@jdfalk jdfalk commented Apr 25, 2026

Summary

Adds .claude/skills/bootstrap-repo/ — a thin orchestration skill that creates a new GitHub repo (or adopts an existing one) and applies the full ghcommon house standard in one command: settings, branch protection, labels, dependabot, instruction files, flavor overlay.

Design summary

Decision Value
Owner default hardcoded jdfalk, override via --owner
Status check discovery parse YAML jobs.<id> keys from PR-triggering workflows
web_commit_signoff_required off
required_conversation_resolution on
enforce_admins off
has_issues / has_wiki / has_projects on / off / off
Merge rebase-only, auto-merge on, no delete
Required approvals 0 (with dismiss_stale_reviews: true)
Secrets manual checklist (deferred to issue #264)

Reference docs (references/repo-settings.md, references/branch-protection.md) are the canonical source of truth; scripts mirror them. Drift is caught by verify_bootstrap.sh.

What's in the PR

  • SKILL.md — thin trigger doc + usage + flavor decision tree
  • scripts/bootstrap_repo.sh — orchestrator (create/adopt × action/library/service)
  • scripts/apply_repo_settings.shgh api PATCH /repos/:o/:r
  • scripts/apply_branch_protection.shgh api PUT /repos/:o/:r/branches/main/protection
  • scripts/discover_status_checks.py — YAML parser → required-check contexts
  • scripts/verify_bootstrap.sh — read-back diff, idempotency check
  • references/{repo-settings,branch-protection,flavors}.md — canonical specs

Reuses ghcommon/scripts/sync-repo-setup.py and sync-github-labels.py rather than duplicating them.

Cross-references

  • ghcommon#264 — future: secret provisioning automation (deferred)
  • ghcommon#265 — followup: split ACTION_REPO_STANDARDS.md by flavor + audit labels.json (deferred; was originally planned as parallel subagent work but blocked by harness gating on Bash)

Test plan

  • shellcheck passes on all .sh files (enforced via pre-commit)
  • ruff passes on discover_status_checks.py
  • discover_status_checks.py produces correct job IDs against ghcommon's own workflows (19 jobs surfaced)
  • quick_validate.py reports skill is valid
  • Live dry-run on jdfalk/bootstrap-test-DELETE-ME (private throwaway): adopt mode, verify state, re-run, confirm idempotency, delete. Pending user authorization — creates and destroys a real (private) GitHub repo.
  • Apply to one real existing repo (suggest a low-risk one) and confirm settings stick

Notes for reviewer

  • The skill assumes ghcommon is cloned at ~/repos/github.com/jdfalk/ghcommon (override via --ghcommon or $GHCOMMON_PATH).
  • The skill assumes main is the default branch. Adopting a master-default repo requires a manual rename first.
  • Library and service template repos (jft-library-template, jft-service-template) don't yet exist — the skill falls back to creating an empty repo. Once the skill stabilizes, run it against two empty repos and flip isTemplate: true to bootstrap the templates from the skill.

🤖 Generated with Claude Code

Adds .claude/skills/bootstrap-repo/ — a thin orchestration skill that
applies the full ghcommon house standard (settings, branch protection,
labels, dependabot, instruction files, flavor overlay) to a new or
existing repo in one command.

Wraps existing ghcommon scripts where they exist:
- sync-repo-setup.py for instruction/dependabot/AGENTS file copy
- sync-github-labels.py for labels.json sync

Adds new scripts for the gap (no prior automation):
- apply_repo_settings.sh — repo-level settings via gh api PATCH
- apply_branch_protection.sh — main protection via gh api PUT
- discover_status_checks.py — autodiscovers required checks from PR-triggered workflows
- verify_bootstrap.sh — idempotent read-back diff for adoption auditing
- bootstrap_repo.sh — orchestrator (create or adopt mode, action/library/service flavor)

Reference docs are the source of truth for payloads; scripts mirror them.

Cross-refs:
- ghcommon issue #264 (future: secret provisioning automation)
- ghcommon issue #265 (followup: split ACTION_REPO_STANDARDS by flavor + label audit)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added size/XL type:documentation Improvements or additions to documentation tech:python Python programming language tech:shell Shell scripting (bash, sh) labels Apr 25, 2026
@jdfalk jdfalk merged commit 80f40c1 into main Apr 25, 2026
32 of 38 checks passed
@jdfalk jdfalk deleted the feat/bootstrap-repo-skill branch April 25, 2026 10:18
@jdfalk
Copy link
Copy Markdown
Owner Author

jdfalk commented Apr 25, 2026

Live dry-run results — jdfalk/bootstrap-test-DELETE-ME (private)

Ran the skill end-to-end. Surfaced and fixed three integration bugs (commit ede0515):

Bugs fixed

  1. sync-repo-setup.py only exposes sync_all_repositories() via CLI — auto-discovers all repos. Needed single-target. Added a Python shim (scripts/_sync_one_repo.py) that imports RepoSetupSyncer and calls sync_repository(target_repo) directly. Doesn't modify ghcommon's script.
  2. sync-github-labels.py arg signature mismatch — uses positional (owner, repo) (not flags) and reads PAT_TOKEN/GITHUB_TOKEN (not GH_TOKEN). Bootstrap was passing flags. Fixed.
  3. verify_bootstrap.sh false-positive — when no PR-triggering workflows exist, required_status_checks is null by design, but verify was still asserting .strict == true. Now skips that check when the object is null.

Idempotency confirmed

Real-world ceiling found

GitHub's secondary rate limit kicks in around ~190 of the 242 labels when sync hits in tight succession. The script reports it (Failed to create label '<name>': 403 secondary rate limit) and continues; remaining labels create on the next bootstrap run. Non-blocking; documented in the script's existing error handler. Could be improved with throttling, but that's a sync-github-labels.py change, out of scope for this PR.

Cleanup

🚨 Throwaway repo NOT auto-deleted — my gh token lacks delete_repo scope. Run manually:

gh auth refresh -h github.com -s delete_repo
gh repo delete jdfalk/bootstrap-test-DELETE-ME --yes

Updated test plan checklist:

  • shellcheck passes (pre-commit)
  • ruff passes (pre-commit)
  • discover_status_checks.py outputs correct job IDs against ghcommon's workflows
  • quick_validate.py reports skill is valid
  • Live dry-run on jdfalk/bootstrap-test-DELETE-ME (4 runs, idempotent, fully verified)
  • Apply to one real existing repo (next step after merge)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XL tech:python Python programming language tech:shell Shell scripting (bash, sh) type:documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant