feat: implement issue #798 — Story: SEED + DISTRIBUTE — baseline into repo-template, bootstrap, and deploy sync - #805
Conversation
… repo-template, bootstrap, and deploy sync
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Review limit reached
Next review available in: 10 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughAdds a reusable marker-delimited ChangesGitignore baseline distribution
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related issues
Possibly related PRs
Sequence Diagram(s)sequenceDiagram
participant SyncGitignoreBaseline
participant GitHubContentsAPI
participant GitignoreBaseline
participant SDDeployViaPR
SyncGitignoreBaseline->>GitHubContentsAPI: fetch repository .gitignore
GitHubContentsAPI-->>SyncGitignoreBaseline: return encoded content or missing file
SyncGitignoreBaseline->>GitignoreBaseline: insert or refresh L1 baseline
SyncGitignoreBaseline->>SDDeployViaPR: create PR when content changes
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request introduces a shared mechanism to seed and sync an organization-wide secrets baseline (L1 block) in .gitignore files across repositories, including bootstrapping updates, a fleet-wide sync script, and comprehensive BATS tests. The review feedback highlights several opportunities to improve script robustness, such as stripping carriage returns (\r) to prevent Windows CRLF line endings from breaking awk matches, utilizing global arrays and EXIT traps for reliable temporary file cleanup, refining jq filters to handle non-JSON API responses gracefully, and ensuring BATS tests use $BATS_TEST_TMPDIR for temporary directories.
There was a problem hiding this comment.
Pull request overview
Implements org-wide seeding and distribution mechanics for the marker-wrapped .gitignore secrets baseline (L1), primarily by introducing a shared upsert_gitignore_baseline() library, wiring it into bootstrap-new-repo.sh, and adding a PR-based fleet sync script plus bats coverage.
Changes:
- Add
scripts/lib/gitignore-baseline.shwithgib_extract_baseline_block()andupsert_gitignore_baseline()to insert/refresh L1 while preserving per-repo L2. - Add
scripts/sync-gitignore-baseline.shto sweep repos and open PRs that insert/refresh the baseline. - Extend
scripts/bootstrap-new-repo.shwith a new.gitignoreseeding step and add/extend bats tests around the new behavior.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_seed_repo_template_gitignore.bats | New bats assertions intended to validate template .gitignore emission includes the marker-wrapped baseline and preserves L2 rules. |
| tests/test_bootstrap_new_repo.bats | Extends bootstrap DRY_RUN coverage to include .gitignore baseline seeding. |
| test/scripts/sync-gitignore-baseline/dry-run.bats | Adds dry-run coverage for the new fleet sync script behavior. |
| test/scripts/lib/gitignore-baseline.bats | Adds unit tests for baseline extraction/upsert behaviors and negation discipline. |
| scripts/sync-gitignore-baseline.sh | New PR-based fleet sweep to insert/refresh .gitignore baseline across repos. |
| scripts/lib/gitignore-baseline.sh | New shared pure-text lib implementing marker block extraction and idempotent upsert. |
| scripts/bootstrap-new-repo.sh | Adds .gitignore baseline seeding/refresh step (PR-based) to new repo bootstrap flow. |
|
CI checks on this PR are still running. Once they complete, re-mention Posted by the donpetry-bot PR-review cascade. |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/test_bootstrap_new_repo.bats (1)
40-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing coverage for the non-dry-run
.gitignorewrite path.Only
DRY_RUN=trueand the missing-canonical-file failure are tested forstep_gitignore; the actual write branch (existing-content fetch +upsert_gitignore_baseline+_cross_repo_file_pr) has no test. Additionally,_stub_gh's default case returns a bare{"full_name":"stub/repo"}for any GET, so agh api repos/.../contents/.gitignore --jq '.content'call would not yield a realistic base64contentpayload — the stub would need acontents/.gitignore-aware branch (similar to the existingcontents/personasspecial-case) before this path is testable.Also applies to: 286-317
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_bootstrap_new_repo.bats` around lines 40 - 63, Extend tests for step_gitignore to cover the non-dry-run existing-content path, including fetching .gitignore content, calling upsert_gitignore_baseline, and invoking _cross_repo_file_pr. Update _stub_gh with a contents/.gitignore-specific response containing realistic base64 content, then assert the write path and resulting behavior; retain the existing dry-run and missing-canonical-file coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/lib/gitignore-baseline.sh`:
- Around line 83-86: Normalize CRLF input before marker detection in
scripts/lib/gitignore-baseline.sh: in lines 83-86 sanitize existing with tr -d
'\r'; in lines 43-44 strip trailing carriage returns in the awk extraction; in
lines 52-53 sanitize content from standard input; and in lines 76-77 sanitize
the loaded block. Apply these changes to the existing read paths so all upsert
comparisons operate on LF-only text.
In `@scripts/sync-gitignore-baseline.sh`:
- Line 65: Update the help-output extraction command in the script’s --help
handling to include the complete header comment through line 26, so the GH_TOKEN
requirement text is displayed without truncation.
- Line 131: Update the printf format string assigned to body in the sync script
to remove the backslashes surrounding `.gitignore`, while preserving the literal
backticks and all other message text and substitutions.
- Around line 177-179: Update the repository loop invoking sync_repo so a
non-zero result from one repository is handled without triggering set -e
termination. Preserve recording or reporting the failure as appropriate, then
continue processing every remaining entry in REPOS.
---
Outside diff comments:
In `@tests/test_bootstrap_new_repo.bats`:
- Around line 40-63: Extend tests for step_gitignore to cover the non-dry-run
existing-content path, including fetching .gitignore content, calling
upsert_gitignore_baseline, and invoking _cross_repo_file_pr. Update _stub_gh
with a contents/.gitignore-specific response containing realistic base64
content, then assert the write path and resulting behavior; retain the existing
dry-run and missing-canonical-file coverage.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b3fbefb0-84a4-449c-9e0f-202667b2b33d
📒 Files selected for processing (8)
.dev-lead/scripts/seed-repo-template.shscripts/bootstrap-new-repo.shscripts/lib/gitignore-baseline.shscripts/sync-gitignore-baseline.shtest/scripts/lib/gitignore-baseline.batstest/scripts/sync-gitignore-baseline/dry-run.batstests/test_bootstrap_new_repo.batstests/test_seed_repo_template_gitignore.bats
|
@coderabbitai resolve |
Dev-Lead — review-changes (applied)Changes committed and pushed. |
✅ Action performedComments resolved and changes approved. |
|
Note @don-petry I reviewed this PR and no code changes were needed, but it still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews), so I cannot mark it done yet. I'll re-check automatically. |
Dev-Lead — waiting on PR blockers (intent: review-changes)PR: #805 |
… scripts/ The seed script was committed under .dev-lead/scripts/ — dev-lead's internal working directory — so the deliverable lived in a git-ignored, ephemeral location and the test invoked it from there. Move it to scripts/, adjust the STANDARDS_DIR default depth (one level up now, not two) and the shellcheck source directive, and point the bats test at the committed path. Resolves the Copilot review threads on PR #805. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fa6TNhxEXj6WAKpaJLHvNK
…te.sh The dedicated CI runner still referenced the old .dev-lead/scripts path in its shellcheck target and PR/push path filters, so the relocation broke the gate. Point all references at the committed scripts/ path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fa6TNhxEXj6WAKpaJLHvNK
|
donpetry-bot
left a comment
There was a problem hiding this comment.
Automated review — APPROVED ✓
Risk: MEDIUM
Reviewed commit: 663289b6986aa107152e1fa7aa15f16ab541baea
Review mode: triage-approved (single reviewer)
Summary
Implements issue #798 (SEED + DISTRIBUTE .gitignore secrets baseline): a pure-text shared lib (upsert_gitignore_baseline / gib_extract_baseline_block), a PR-based bootstrap step (6/6), a fleet-wide sync sweep script, a repo-template generator, a dedicated hardened test workflow, and thorough bats coverage. Triage assessment confirmed; no blocking findings.
Linked issue analysis
Issue #798 deliverables are substantively addressed: (1) template seeding via scripts/seed-repo-template.sh --emit-baseline .gitignore, which emits the marker-wrapped L1 block on top and ecosystem L2 below END, with tests enforcing the STORY3 anchors (.env, *.pem, *.key) and the negation discipline (no L2 re-ignore of !.env.example); (2) distribution via a new step_gitignore in bootstrap-new-repo.sh (PR-based, never a direct push) and the dedicated sync-gitignore-baseline.sh sweep (the issue explicitly allowed a dedicated helper); (3) reusable, idempotent upsert_gitignore_baseline() in scripts/lib/, unit-tested for absent→insert, present→replace-in-place, L2 preservation, negation ordering, idempotency, and half-open marker refusal. Cross-file assumptions verified on the head SHA: sd_deploy_via_pr() exists in scripts/lib/standards-deploy.sh, _cross_repo_file_pr() exists in bootstrap, and the canonical /.gitignore carries the BEGIN/END markers.
Findings
No blocking issues. Verified: new workflow is least-privilege (permissions: contents: read), has a concurrency group and timeout, and pins actions/checkout to 9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0, confirmed via the GitHub API as the real v7.0.0 tag commit. The lib is pure text (no gh/network), refuses half-open marker states rather than duplicating markers, and preserves bytes it did not author. Non-blocking nits: (a) scripts/sync-gitignore-baseline.sh is mode 100644 while sibling scripts are 755 (always invoked via bash, so harmless); (b) branch-date formats differ between bootstrap (%Y-%m-%d) and sync (%Y%m%d) — cosmetic; (c) in sync_repo, temp files are appended to the EXIT-trap array and also removed inline, leaving stale array entries (harmless with rm -f); (d) step_gitignore sets/clears its own EXIT trap — safe today since bootstrap-new-repo.sh defines no other EXIT trap, but a future trap elsewhere in that script would be clobbered. Secret scan: the run_secret_scanning MCP tool is not available in this environment; the gitleaks CI check passed and no secret-like content appears in the diff (patterns only, no values).
CI status
All validating checks green on 663289b: Lint and bats (new Gitignore Baseline Tests workflow), ShellCheck, bats, CodeQL, Secret scan (gitleaks), Agent Security Scan, AgentShield, SonarCloud Quality Gate (0 new issues), npm audit. CANCELLED entries are superseded dev-lead dispatch/ci-relay automation runs, not validators. 0 unresolved review threads; CodeRabbit's final review state is APPROVED (earlier CHANGES_REQUESTED was addressed and dismissed through two dev-lead fix cycles).
Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.



Closes #798
Implemented by dev-lead agent. Please review.
Summary by CodeRabbit
New Features
.gitignorefiles.Bug Fixes
.gitignorebaseline setup.Tests