From 89cf816b6a8cac2c1cda72dbc28d65df0f965417 Mon Sep 17 00:00:00 2001 From: Don Petry <36422719+don-petry@users.noreply.github.com> Date: Sat, 10 Oct 2026 22:01:21 -0500 Subject: [PATCH] =?UTF-8?q?refactor:=20rename=20this=20repo's=20seed-repo-?= =?UTF-8?q?template.sh=20to=20emit-standard-file.sh=20=E2=80=94=20the=20se?= =?UTF-8?q?eder=20has=20one=20home=20(petry-projects/.github-private#1927)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two scripts in two repos were both called seed-repo-template.sh and were taken for diverged copies of one tool. They are different tools: - petry-projects/.github-private/scripts/seed-repo-template.sh is the seeder. It writes the baseline scaffold into repo-template and opens the seed PR. - This repo's script only prints one standard file (the .gitignore baseline, or a workflow stub verbatim) from a local checkout. It never writes anywhere. So the name now has one home. This repo's script becomes scripts/emit-standard-file.sh, with no behaviour change. - Rename the script and its two test suites. The tests change only the script path they call; every assertion is unchanged. - Add tests/test_seed_repo_template_single_home.bats, which fails if a file named seed-repo-template.sh reappears in this repo, and run it whenever such a file is added. - AGENTS.md documents the home of the seeder. The bootstrap doc and the versioning standard name the right script. Co-Authored-By: Claude Opus 5.5 --- .../workflows/gitignore-baseline-tests.yml | 31 ++++++----- AGENTS.md | 9 ++++ docs/bootstrap/new-repo-validation.md | 8 +-- ...repo-template.sh => emit-standard-file.sh} | 13 +++-- standards/standards-versioning.md | 2 +- ...=> test_emit_standard_file_gitignore.bats} | 4 +- ...=> test_emit_standard_file_workflows.bats} | 6 +-- .../test_seed_repo_template_single_home.bats | 53 +++++++++++++++++++ 8 files changed, 102 insertions(+), 24 deletions(-) rename scripts/{seed-repo-template.sh => emit-standard-file.sh} (90%) rename tests/{test_seed_repo_template_gitignore.bats => test_emit_standard_file_gitignore.bats} (96%) rename tests/{test_seed_repo_template_workflows.bats => test_emit_standard_file_workflows.bats} (98%) create mode 100644 tests/test_seed_repo_template_single_home.bats diff --git a/.github/workflows/gitignore-baseline-tests.yml b/.github/workflows/gitignore-baseline-tests.yml index 497b79755..0f95c15ec 100644 --- a/.github/workflows/gitignore-baseline-tests.yml +++ b/.github/workflows/gitignore-baseline-tests.yml @@ -3,13 +3,15 @@ # Triggered on any PR that touches: # - scripts/lib/gitignore-baseline.sh # - scripts/sync-gitignore-baseline.sh -# - scripts/seed-repo-template.sh +# - scripts/emit-standard-file.sh # - scripts/compliance-remediate.sh # - test/scripts/lib/gitignore-baseline.bats # - test/scripts/sync-gitignore-baseline/** # - test/scripts/compliance-remediate/** -# - tests/test_seed_repo_template_gitignore.bats -# - tests/test_seed_repo_template_workflows.bats +# - tests/test_emit_standard_file_gitignore.bats +# - tests/test_emit_standard_file_workflows.bats +# - tests/test_seed_repo_template_single_home.bats +# - any file named seed-repo-template.sh (it must not exist here, #1927) # # Gates (all must pass before merge): # 1. shellcheck — static analysis of the lib + sync + seed + remediate scripts @@ -23,13 +25,15 @@ on: paths: - 'scripts/lib/gitignore-baseline.sh' - 'scripts/sync-gitignore-baseline.sh' - - 'scripts/seed-repo-template.sh' + - 'scripts/emit-standard-file.sh' + - '**/seed-repo-template.sh' - 'scripts/compliance-remediate.sh' - 'test/scripts/lib/gitignore-baseline.bats' - 'test/scripts/sync-gitignore-baseline/**' - 'test/scripts/compliance-remediate/**' - - 'tests/test_seed_repo_template_gitignore.bats' - - 'tests/test_seed_repo_template_workflows.bats' + - 'tests/test_emit_standard_file_gitignore.bats' + - 'tests/test_emit_standard_file_workflows.bats' + - 'tests/test_seed_repo_template_single_home.bats' - '.github/workflows/gitignore-baseline-tests.yml' push: branches: @@ -37,13 +41,15 @@ on: paths: - 'scripts/lib/gitignore-baseline.sh' - 'scripts/sync-gitignore-baseline.sh' - - 'scripts/seed-repo-template.sh' + - 'scripts/emit-standard-file.sh' + - '**/seed-repo-template.sh' - 'scripts/compliance-remediate.sh' - 'test/scripts/lib/gitignore-baseline.bats' - 'test/scripts/sync-gitignore-baseline/**' - 'test/scripts/compliance-remediate/**' - - 'tests/test_seed_repo_template_gitignore.bats' - - 'tests/test_seed_repo_template_workflows.bats' + - 'tests/test_emit_standard_file_gitignore.bats' + - 'tests/test_emit_standard_file_workflows.bats' + - 'tests/test_seed_repo_template_single_home.bats' - '.github/workflows/gitignore-baseline-tests.yml' permissions: @@ -95,7 +101,7 @@ jobs: shellcheck --severity=warning -x \ scripts/lib/gitignore-baseline.sh \ scripts/sync-gitignore-baseline.sh \ - scripts/seed-repo-template.sh \ + scripts/emit-standard-file.sh \ scripts/compliance-remediate.sh - name: Run bats suite @@ -104,5 +110,6 @@ jobs: test/scripts/lib/gitignore-baseline.bats \ test/scripts/sync-gitignore-baseline/ \ test/scripts/compliance-remediate/ \ - tests/test_seed_repo_template_gitignore.bats \ - tests/test_seed_repo_template_workflows.bats + tests/test_emit_standard_file_gitignore.bats \ + tests/test_emit_standard_file_workflows.bats \ + tests/test_seed_repo_template_single_home.bats diff --git a/AGENTS.md b/AGENTS.md index 1df4a2f71..2d9d4cbe1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,6 +54,15 @@ and have `.github-private` **consume** it — the way repo-seeding tooling fetch `standards/workflows/` from `.github`. Do **not** add new org-wide standards or rulesets to `.github-private`. +**`seed-repo-template.sh` has one home: `petry-projects/.github-private`.** That script writes +the baseline scaffold into `petry-projects/repo-template` and opens the seed PR. It reads this +repo's `standards/` at a pinned ref, so it is a consumer of the standards, not a standard. This +repo's `scripts/emit-standard-file.sh` is a different tool: it only prints one standard file (the +`.gitignore` baseline, or a workflow stub verbatim) from a local checkout. The two used to share a +name and were mistaken for diverged copies (`petry-projects/.github-private#1927`). Do not add a +`seed-repo-template.sh` here; `tests/test_seed_repo_template_single_home.bats` fails if one +reappears. + > **Known exception being remediated:** `code-quality.json` and `pr-quality.json` > currently live in `.github-private/.github/rulesets/` (added ad-hoc under > compliance fix #60, before this boundary was documented) and are being relocated diff --git a/docs/bootstrap/new-repo-validation.md b/docs/bootstrap/new-repo-validation.md index b8c37c548..8f61a8a80 100644 --- a/docs/bootstrap/new-repo-validation.md +++ b/docs/bootstrap/new-repo-validation.md @@ -9,7 +9,7 @@ produces a fully org-compliant repo, exercised under `DRY_RUN` with no drift. ## Primary onboarding path (one-click + one-command) 1. **Use this template.** Create the repo from `petry-projects/repo-template` - (`seed-repo-template.sh` keeps that template in sync with `petry-projects/.github` + (`seed-repo-template.sh`, in `petry-projects/.github-private`, keeps that template in sync with `petry-projects/.github` `standards/`). This seeds day-0 only: the thin-caller workflow stubs pinned to their published `@/stable` channel tags plus the root/baseline files (CODEOWNERS, AGENTS.md/CLAUDE.md pointers, LICENSE, SECURITY.md, `.gitignore`, @@ -121,5 +121,7 @@ this branch. The cutover content to apply: ## See also - `scripts/bootstrap-new-repo.sh` — the orchestrator (issues #967, #968) -- `scripts/seed-repo-template.sh` — day-0 template seeding + the generated `BOOTSTRAP.md` (#966) -- `tests/test_bootstrap_new_repo.bats`, `tests/test_seed_repo_template.bats` — the executable validation +- `scripts/seed-repo-template.sh` in `petry-projects/.github-private` — day-0 template seeding + the generated + `BOOTSTRAP.md` (#966), with its suite `tests/test_seed_repo_template.bats` there. That repo is the one home of + the seeder; this repo's `scripts/emit-standard-file.sh` only prints a standard file. +- `tests/test_bootstrap_new_repo.bats` — the executable validation of the orchestrator diff --git a/scripts/seed-repo-template.sh b/scripts/emit-standard-file.sh similarity index 90% rename from scripts/seed-repo-template.sh rename to scripts/emit-standard-file.sh index 79d39e1a1..ab98c4b1c 100755 --- a/scripts/seed-repo-template.sh +++ b/scripts/emit-standard-file.sh @@ -1,10 +1,17 @@ #!/usr/bin/env bash -# scripts/seed-repo-template.sh — emit standard file content for the +# scripts/emit-standard-file.sh — emit standard file content for the # org repo-template to distribute to all new repos (#798, Story: SEED + DISTRIBUTE). # +# This script only PRINTS a file. It does not seed anything. The tool that writes +# the scaffold into petry-projects/repo-template is `scripts/seed-repo-template.sh` +# in petry-projects/.github-private, the one home of that name. This file used to +# share the name, which made the two look like diverged copies of one script +# (petry-projects/.github-private#1927). Do not add a `seed-repo-template.sh` here: +# tests/test_seed_repo_template_single_home.bats fails if one reappears. +# # Usage: -# STANDARDS_DIR= bash scripts/seed-repo-template.sh --emit-baseline .gitignore -# STANDARDS_DIR= bash scripts/seed-repo-template.sh --emit-workflow dev-lead.yml +# STANDARDS_DIR= bash scripts/emit-standard-file.sh --emit-baseline .gitignore +# STANDARDS_DIR= bash scripts/emit-standard-file.sh --emit-workflow dev-lead.yml # # --emit-baseline .gitignore # Print the seeded .gitignore: the marker-wrapped L1 secrets baseline on top diff --git a/standards/standards-versioning.md b/standards/standards-versioning.md index c0ddb1deb..694718056 100644 --- a/standards/standards-versioning.md +++ b/standards/standards-versioning.md @@ -104,5 +104,5 @@ degrades cleanly to "accepts current" while `previous` is empty. - **No behavior change for anything that does not opt in.** Scripts and repos that pass an explicit ref or a local standards directory keep resolving exactly as they do; this channel adds a tag, it does not change any existing - resolution path in this repo. In particular `scripts/seed-repo-template.sh` + resolution path in this repo. In particular `scripts/emit-standard-file.sh` (which reads a local `STANDARDS_DIR` checkout) is untouched. diff --git a/tests/test_seed_repo_template_gitignore.bats b/tests/test_emit_standard_file_gitignore.bats similarity index 96% rename from tests/test_seed_repo_template_gitignore.bats rename to tests/test_emit_standard_file_gitignore.bats index 5a5d70eaa..8ceb68ef5 100644 --- a/tests/test_seed_repo_template_gitignore.bats +++ b/tests/test_emit_standard_file_gitignore.bats @@ -1,6 +1,6 @@ #!/usr/bin/env bats # Tests for the repo-template .gitignore generator in -# scripts/seed-repo-template.sh (#798). +# scripts/emit-standard-file.sh (#798). # # The seeded template must carry the marker-wrapped org secrets baseline (L1) on # top, with the template's own ecosystem/OS entries (L2) below the END marker — @@ -12,7 +12,7 @@ setup() { REPO_ROOT="$(cd -- "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)" - SEED="${REPO_ROOT}/scripts/seed-repo-template.sh" + SEED="${REPO_ROOT}/scripts/emit-standard-file.sh" export STANDARDS_DIR="$REPO_ROOT" } diff --git a/tests/test_seed_repo_template_workflows.bats b/tests/test_emit_standard_file_workflows.bats similarity index 98% rename from tests/test_seed_repo_template_workflows.bats rename to tests/test_emit_standard_file_workflows.bats index f5ec397e4..5abe98c1a 100644 --- a/tests/test_seed_repo_template_workflows.bats +++ b/tests/test_emit_standard_file_workflows.bats @@ -1,6 +1,6 @@ #!/usr/bin/env bats # Tests for the repo-template WORKFLOW-STUB generator in -# scripts/seed-repo-template.sh (#886). +# scripts/emit-standard-file.sh (#886). # # The repo-template baseline re-seed ("chore: seed org baseline file scaffold") # must source its workflow stubs from the canonical standards/workflows/ — which @@ -21,7 +21,7 @@ setup() { REPO_ROOT="$(cd -- "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)" - SEED="${REPO_ROOT}/scripts/seed-repo-template.sh" + SEED="${REPO_ROOT}/scripts/emit-standard-file.sh" WF_DIR="${REPO_ROOT}/standards/workflows" export STANDARDS_DIR="$REPO_ROOT" } @@ -151,7 +151,7 @@ RESEEDED_STUBS="dev-lead.yml auto-rebase.yml dependabot-automerge.yml" } @test "STANDARDS_REF defaults to standards/v1-stable when unset (environment variable resolution)" { - # Verify that seed-repo-template.sh accepts STANDARDS_REF and defaults to v1-stable + # Verify that emit-standard-file.sh accepts STANDARDS_REF and defaults to v1-stable # when unset. The script should complete successfully with default reference. run env -u STANDARDS_REF STANDARDS_DIR="$REPO_ROOT" bash "$SEED" --emit-workflow dev-lead.yml [ "$status" -eq 0 ] diff --git a/tests/test_seed_repo_template_single_home.bats b/tests/test_seed_repo_template_single_home.bats new file mode 100644 index 000000000..9c4a539f4 --- /dev/null +++ b/tests/test_seed_repo_template_single_home.bats @@ -0,0 +1,53 @@ +#!/usr/bin/env bats +# Guard: this repo carries no `seed-repo-template.sh` +# (petry-projects/.github-private#1927). +# +# The seeder that writes the baseline scaffold into petry-projects/repo-template +# lives in petry-projects/.github-private, the one home of that name. This repo +# once had a different, smaller script under the same name. It only printed a +# standard file, yet the two were read as diverged copies of one tool and nothing +# said which was authoritative. That script is now scripts/emit-standard-file.sh. +# This guard keeps a second `seed-repo-template.sh` from reappearing here. + +setup() { + REPO_ROOT="$(cd -- "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)" + : "${SINGLE_HOME_ROOT:=$REPO_ROOT}" +} + +# seed_copies — every tracked or untracked-but-not-ignored file named +# seed-repo-template.sh under the repo, one path per line. +seed_copies() { + git -C "$SINGLE_HOME_ROOT" ls-files --cached --others --exclude-standard \ + | grep -E '(^|/)seed-repo-template\.sh$' || true +} + +@test "no seed-repo-template.sh exists in this repo — its one home is petry-projects/.github-private" { + run seed_copies + [ "$status" -eq 0 ] + if [ -n "$output" ]; then + echo "Found a seed-repo-template.sh in petry-projects/.github:" + echo "$output" + echo "The seeder's one home is petry-projects/.github-private/scripts/seed-repo-template.sh." + echo "Change it there. To print a standard file from this repo, use scripts/emit-standard-file.sh." + return 1 + fi +} + +@test "the guard finds a copy when one is added, at any depth" { + SINGLE_HOME_ROOT="$BATS_TEST_TMPDIR/repo" + mkdir -p "$SINGLE_HOME_ROOT/scripts" "$SINGLE_HOME_ROOT/tools/nested" + git -C "$SINGLE_HOME_ROOT" init -q + : > "$SINGLE_HOME_ROOT/scripts/emit-standard-file.sh" + : > "$SINGLE_HOME_ROOT/scripts/not-seed-repo-template.sh" + run seed_copies + [ -z "$output" ] + : > "$SINGLE_HOME_ROOT/scripts/seed-repo-template.sh" + : > "$SINGLE_HOME_ROOT/tools/nested/seed-repo-template.sh" + run seed_copies + [ "$output" = "$(printf 'scripts/seed-repo-template.sh\ntools/nested/seed-repo-template.sh')" ] +} + +@test "the emitter exists under its own name and says where the seeder lives" { + [ -f "$REPO_ROOT/scripts/emit-standard-file.sh" ] + grep -q 'petry-projects/.github-private' "$REPO_ROOT/scripts/emit-standard-file.sh" +}