diff --git a/scripts/seed-repo-template.sh b/scripts/seed-repo-template.sh index 7a6452e07..9f092aa6e 100755 --- a/scripts/seed-repo-template.sh +++ b/scripts/seed-repo-template.sh @@ -425,10 +425,7 @@ EOF EOF ;; sonar-project.properties) cat <<'EOF' -# Customize sonar.projectKey / sonar.organization for this repo before enabling -# the sonarcloud workflow. See BOOTSTRAP.md. -sonar.projectKey=combsmith_repo-template -sonar.organization=combsmith +# Project key / organization are derived from the repo by .github/workflows/sonarcloud.yml. sonar.sources=. sonar.exclusions=**/node_modules/**,**/vendor/**,**/dist/** EOF @@ -513,7 +510,7 @@ verification checks, and the short list of org-admin steps a human finishes. | CI (`build-and-test`, `Secret scan (gitleaks)`, `coverage`) and SonarCloud | `ci.yml`, `sonarcloud.yml` | Green out of the box; replace the shell steps with your stack's | | Copilot cloud-agent setup | `copilot-setup-steps.yml` | Uncomment your stack block | | Dependabot | `.github/dependabot.yml` | `frontend` stack by default; swap for yours | -| Baseline files | `CODEOWNERS`, `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `LICENSE`, `.gitignore` (secrets baseline), `.gitleaks.toml`, `sonar-project.properties`, `copilot-instructions.md` | Docs and Sonar key need the project's name | +| Baseline files | `CODEOWNERS`, `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `LICENSE`, `.gitignore` (secrets baseline), `.gitleaks.toml`, `sonar-project.properties`, `copilot-instructions.md` | Docs need the project's name; the Sonar key is derived from the repo by `sonarcloud.yml` | | Repo settings, rulesets, labels, GHAS | not files | Applied by `bootstrap-new-repo.sh` in `combsmith/.github` (org admin) | | Initiatives board (`add-to-project`) | stub only | Red until an org admin both grants the repo the `INITIATIVES_APP_*` org secrets (selected visibility) and adds it to the `combsmith-planner` app installation | @@ -555,7 +552,7 @@ that run._ | Input | Example | Used by | |---|---|---| -| `REPO` — `owner/name` of the new repo | `combsmith/hive-health` | `sonar-project.properties`, `README.md`, `copilot-instructions.md`, `feature-ideation.yml` | +| `REPO` — `owner/name` of the new repo | `combsmith/hive-health` | `README.md`, `copilot-instructions.md`, `feature-ideation.yml` | | `DESCRIPTION` — one sentence, what the repo is | `Beehive telemetry dashboard and alerting service` | `README.md`, `copilot-instructions.md`, repo description | | `STACK` — one of `frontend`, `backend-go`, `backend-python`, `backend-rust`, `fullstack`, `infra-terraform`, `none` | `backend-python` | `dependabot.yml`, `ci.yml`, `copilot-setup-steps.yml`, `.gitignore` L2, `.github/instructions/` | | `PROJECT_CONTEXT` — 3 to 5 sentences: product, target users, competitive landscape | see `feature-ideation.yml` header | `feature-ideation.yml` (`project_context`) | @@ -603,7 +600,7 @@ by PR, and the compliance audit flags any hand edit as drift): | `CLAUDE.md`, `SECURITY.md`, `LICENSE` | Org pointers and license. | | `.gitignore` — the block between `>>> BEGIN combsmith secrets baseline` and `<<< END` | Hash-checked by the compliance audit. Edit only **below** the END marker. | | `.gitleaks.toml` | Keep the file; you may only **append** allowlist paths under `[allowlist]`. | -| `.github/workflows/sonarcloud.yml` | Keep as shipped; the `SonarCloud` job name is a required check. | +| `.github/workflows/sonarcloud.yml` | Keep as shipped; the `SonarCloud` job name is a required check, and it derives `sonar.projectKey` / `sonar.organization` from the repo (`_` / ``), so no per-repo key is needed. | **Customize** (step numbers below): @@ -613,7 +610,7 @@ by PR, and the compliance audit flags any hand edit as drift): | `.github/workflows/ci.yml` | 3 | | `.github/workflows/copilot-setup-steps.yml` | 4 | | `.github/workflows/feature-ideation.yml` | 5 | -| `sonar-project.properties` | 6 | +| `sonar-project.properties` | 6 (only if `sonar.sources` / `sonar.tests` need narrowing) | | `README.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.github/instructions/` | 7 | | `.gitignore` (below the END marker), `.worktreeinclude` | 7 | @@ -759,26 +756,34 @@ Check: `! grep -q 'TODO: Replace this' .github/workflows/feature-ideation.yml` e --- -## 6. `sonar-project.properties` — set the project key +## 6. `sonar-project.properties` — nothing to set unless you narrow the sources -Set the values as follows. Java properties files only treat `#` as a comment -at the start of a line: a trailing `# note` after a value becomes part of the -value, so do not annotate the lines themselves. +`sonarcloud.yml` derives `sonar.projectKey` (`_`) and +`sonar.organization` (``) from the repo at run time, so the shipped +file needs no project key and **no edit** for most repos. SonarCloud +auto-provisions the project on the first scan; it is enabled org-wide and no +console step is needed for a public repo. Do not add `sonar.projectKey` or +`sonar.organization` to the file: the workflow's `-D` arguments take precedence +over the properties file, so a value there cannot override the derived identity +and would only mislead the next reader. -- `sonar.projectKey` — `REPO` with `/` replaced by `_` (`combsmith_`). -- `sonar.sources` — the source directories, e.g. `src`, or `.` for small repos. +Edit the file only if the defaults (`sonar.sources=.` plus the +`node_modules`/`vendor`/`dist` exclusions) are wrong for this repo: + +- `sonar.sources` — the source directories, e.g. `src`, if scanning `.` pulls + in generated or vendored code the exclusions do not cover. - `sonar.tests` — the test directory; omit the line if there are no tests yet. + If you add it, also narrow `sonar.sources` so the two do not overlap: with + `sonar.sources=.` and `sonar.tests=tests` every file under `tests/` is in + both scopes and the analysis fails with `can't be indexed twice`. -```properties -sonar.projectKey=combsmith_ -sonar.organization=combsmith -sonar.sources= -sonar.tests= -sonar.exclusions=**/node_modules/**,**/vendor/**,**/dist/** -``` +If the repo is ever renamed, the derived key changes with it. Keep the history +by updating the key on the existing SonarCloud project (Administration → Update +Key) to the new `_` rather than adding an override here. -Remove the two "Customize…" comment lines at the top. SonarCloud is enabled -org-wide; no console step is needed for a public repo. +Java properties files only treat `#` as a comment at the start of a line: a +trailing `# note` after a value becomes part of the value, so do not annotate +the lines themselves. --- @@ -936,7 +941,6 @@ because the CodeQL and check-suite-preference reads return 404 otherwise. - [ ] `ci.yml` runs the stack's lint / format / typecheck / tests / coverage; jobs `build-and-test`, `Secret scan (gitleaks)`, `coverage` still exist; workflow is still named `CI`. - [ ] `copilot-setup-steps.yml` has exactly the stack block(s) enabled. - [ ] `feature-ideation.yml` carries a real `project_context`. -- [ ] `sonar-project.properties` names `combsmith_`. - [ ] `README.md`, `AGENTS.md`, `copilot-instructions.md` describe this repo; language instruction files copied and listed. - [ ] `tests/*.bats` and `standards/` removed (step 8 exception aside). - [ ] No stub listed under *Keep verbatim* has a diff. diff --git a/tests/fixtures/seed-repo-template/repo-template-BOOTSTRAP.md b/tests/fixtures/seed-repo-template/repo-template-BOOTSTRAP.md index bcea59b3b..9afcd8869 100644 --- a/tests/fixtures/seed-repo-template/repo-template-BOOTSTRAP.md +++ b/tests/fixtures/seed-repo-template/repo-template-BOOTSTRAP.md @@ -24,7 +24,7 @@ that run._ | Input | Example | Used by | |---|---|---| -| `REPO` — `owner/name` of the new repo | `combsmith/hive-health` | `sonar-project.properties`, `README.md`, `copilot-instructions.md`, `feature-ideation.yml` | +| `REPO` — `owner/name` of the new repo | `combsmith/hive-health` | `README.md`, `copilot-instructions.md`, `feature-ideation.yml` | | `DESCRIPTION` — one sentence, what the repo is | `Beehive telemetry dashboard and alerting service` | `README.md`, `copilot-instructions.md`, repo description | | `STACK` — one of `frontend`, `backend-go`, `backend-python`, `backend-rust`, `fullstack`, `infra-terraform`, `none` | `backend-python` | `dependabot.yml`, `ci.yml`, `copilot-setup-steps.yml`, `.gitignore` L2, `.github/instructions/` | | `PROJECT_CONTEXT` — 3 to 5 sentences: product, target users, competitive landscape | see `feature-ideation.yml` header | `feature-ideation.yml` (`project_context`) | @@ -72,7 +72,7 @@ by PR, and the compliance audit flags any hand edit as drift): | `CLAUDE.md`, `SECURITY.md`, `LICENSE` | Org pointers and license. | | `.gitignore` — the block between `>>> BEGIN combsmith secrets baseline` and `<<< END` | Hash-checked by the compliance audit. Edit only **below** the END marker. | | `.gitleaks.toml` | Keep the file; you may only **append** allowlist paths under `[allowlist]`. | -| `.github/workflows/sonarcloud.yml` | Keep as shipped; the `SonarCloud` job name is a required check. | +| `.github/workflows/sonarcloud.yml` | Keep as shipped; the `SonarCloud` job name is a required check, and it derives `sonar.projectKey` / `sonar.organization` from the repo (`_` / ``), so no per-repo key is needed. | **Customize** (step numbers below): @@ -82,7 +82,7 @@ by PR, and the compliance audit flags any hand edit as drift): | `.github/workflows/ci.yml` | 3 | | `.github/workflows/copilot-setup-steps.yml` | 4 | | `.github/workflows/feature-ideation.yml` | 5 | -| `sonar-project.properties` | 6 | +| `sonar-project.properties` | 6 (only if `sonar.sources` / `sonar.tests` need narrowing) | | `README.md`, `AGENTS.md`, `.github/copilot-instructions.md`, `.github/instructions/` | 7 | | `.gitignore` (below the END marker), `.worktreeinclude` | 7 | @@ -228,26 +228,34 @@ Check: `! grep -q 'TODO: Replace this' .github/workflows/feature-ideation.yml` e --- -## 6. `sonar-project.properties` — set the project key +## 6. `sonar-project.properties` — nothing to set unless you narrow the sources -Set the values as follows. Java properties files only treat `#` as a comment -at the start of a line: a trailing `# note` after a value becomes part of the -value, so do not annotate the lines themselves. +`sonarcloud.yml` derives `sonar.projectKey` (`_`) and +`sonar.organization` (``) from the repo at run time, so the shipped +file needs no project key and **no edit** for most repos. SonarCloud +auto-provisions the project on the first scan; it is enabled org-wide and no +console step is needed for a public repo. Do not add `sonar.projectKey` or +`sonar.organization` to the file: the workflow's `-D` arguments take precedence +over the properties file, so a value there cannot override the derived identity +and would only mislead the next reader. -- `sonar.projectKey` — `REPO` with `/` replaced by `_` (`combsmith_`). -- `sonar.sources` — the source directories, e.g. `src`, or `.` for small repos. +Edit the file only if the defaults (`sonar.sources=.` plus the +`node_modules`/`vendor`/`dist` exclusions) are wrong for this repo: + +- `sonar.sources` — the source directories, e.g. `src`, if scanning `.` pulls + in generated or vendored code the exclusions do not cover. - `sonar.tests` — the test directory; omit the line if there are no tests yet. + If you add it, also narrow `sonar.sources` so the two do not overlap: with + `sonar.sources=.` and `sonar.tests=tests` every file under `tests/` is in + both scopes and the analysis fails with `can't be indexed twice`. -```properties -sonar.projectKey=combsmith_ -sonar.organization=combsmith -sonar.sources= -sonar.tests= -sonar.exclusions=**/node_modules/**,**/vendor/**,**/dist/** -``` +If the repo is ever renamed, the derived key changes with it. Keep the history +by updating the key on the existing SonarCloud project (Administration → Update +Key) to the new `_` rather than adding an override here. -Remove the two "Customize…" comment lines at the top. SonarCloud is enabled -org-wide; no console step is needed for a public repo. +Java properties files only treat `#` as a comment at the start of a line: a +trailing `# note` after a value becomes part of the value, so do not annotate +the lines themselves. --- @@ -405,7 +413,6 @@ because the CodeQL and check-suite-preference reads return 404 otherwise. - [ ] `ci.yml` runs the stack's lint / format / typecheck / tests / coverage; jobs `build-and-test`, `Secret scan (gitleaks)`, `coverage` still exist; workflow is still named `CI`. - [ ] `copilot-setup-steps.yml` has exactly the stack block(s) enabled. - [ ] `feature-ideation.yml` carries a real `project_context`. -- [ ] `sonar-project.properties` names `combsmith_`. - [ ] `README.md`, `AGENTS.md`, `copilot-instructions.md` describe this repo; language instruction files copied and listed. - [ ] `tests/*.bats` and `standards/` removed (step 8 exception aside). - [ ] No stub listed under *Keep verbatim* has a diff. diff --git a/tests/fixtures/seed-repo-template/repo-template-README.md b/tests/fixtures/seed-repo-template/repo-template-README.md index c3fd7433e..a6b17a8c3 100644 --- a/tests/fixtures/seed-repo-template/repo-template-README.md +++ b/tests/fixtures/seed-repo-template/repo-template-README.md @@ -20,7 +20,7 @@ verification checks, and the short list of org-admin steps a human finishes. | CI (`build-and-test`, `Secret scan (gitleaks)`, `coverage`) and SonarCloud | `ci.yml`, `sonarcloud.yml` | Green out of the box; replace the shell steps with your stack's | | Copilot cloud-agent setup | `copilot-setup-steps.yml` | Uncomment your stack block | | Dependabot | `.github/dependabot.yml` | `frontend` stack by default; swap for yours | -| Baseline files | `CODEOWNERS`, `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `LICENSE`, `.gitignore` (secrets baseline), `.gitleaks.toml`, `sonar-project.properties`, `copilot-instructions.md` | Docs and Sonar key need the project's name | +| Baseline files | `CODEOWNERS`, `AGENTS.md`, `CLAUDE.md`, `SECURITY.md`, `LICENSE`, `.gitignore` (secrets baseline), `.gitleaks.toml`, `sonar-project.properties`, `copilot-instructions.md` | Docs need the project's name; the Sonar key is derived from the repo by `sonarcloud.yml` | | Repo settings, rulesets, labels, GHAS | not files | Applied by `bootstrap-new-repo.sh` in `combsmith/.github` (org admin) | | Initiatives board (`add-to-project`) | stub only | Red until an org admin both grants the repo the `INITIATIVES_APP_*` org secrets (selected visibility) and adds it to the `combsmith-planner` app installation | diff --git a/tests/test_seed_repo_template.bats b/tests/test_seed_repo_template.bats index 5c9b4d929..9787aefb4 100644 --- a/tests/test_seed_repo_template.bats +++ b/tests/test_seed_repo_template.bats @@ -905,12 +905,12 @@ GHEOF # ── #2233: commercial-support sections + one open seed PR per repo ───────────── # Fixtures: standards/commercial-support-standard.md at standards/v1.2.0, and -# README.md / BOOTSTRAP.md / AGENTS.md from combsmith/repo-template main at e648a2eb (#255). +# README.md / BOOTSTRAP.md / AGENTS.md from combsmith/repo-template main at e0f994b0 (#258). SEED_FIXTURES="$SCRIPT_DIR/tests/fixtures/seed-repo-template" # Git blob SHAs of those two repo-template files (guards the fixtures themselves # against an editor/hook adding a trailing newline). -REPO_TEMPLATE_README_BLOB=c3fd7433e1b962846e569f3f2a9988a3a47967b4 -REPO_TEMPLATE_BOOTSTRAP_BLOB=bcea59b3be30f4cc3273b8de22212f826615db82 +REPO_TEMPLATE_README_BLOB=a6b17a8c32f6181248e55a17f9254bb0480f0f3d +REPO_TEMPLATE_BOOTSTRAP_BLOB=9afcd88693581dde1c2027970ae5174c4945a6eb REPO_TEMPLATE_AGENTS_BLOB=1c5e6cb3b131037b7a103ebf33c243fac9facd0c _fixture_commercial_standard() { @@ -928,7 +928,7 @@ _standard_readme_block() { # # newlines and _put_file encodes it with printf '%s'. _seeded_blob() { printf '%s' "$1" | git hash-object --stdin; } -@test "#2233: BOOTSTRAP.md emission is blob-identical to repo-template main (e648a2eb)" { +@test "#2233: BOOTSTRAP.md emission is blob-identical to repo-template main (e0f994b0)" { [ "$(git hash-object "$SEED_FIXTURES/repo-template-BOOTSTRAP.md")" = "$REPO_TEMPLATE_BOOTSTRAP_BLOB" ] run bash "$SEED" --emit-baseline BOOTSTRAP.md [ "$status" -eq 0 ] @@ -936,7 +936,7 @@ _seeded_blob() { printf '%s' "$1" | git hash-object --stdin; } [ "$(_seeded_blob "$output")" = "$REPO_TEMPLATE_BOOTSTRAP_BLOB" ] } -@test "repo-template#253: AGENTS.md emission is blob-identical to repo-template main (e648a2eb)" { +@test "repo-template#253: AGENTS.md emission is blob-identical to repo-template main (e0f994b0)" { [ "$(git hash-object "$SEED_FIXTURES/repo-template-AGENTS.md")" = "$REPO_TEMPLATE_AGENTS_BLOB" ] run bash "$SEED" --emit-baseline AGENTS.md [ "$status" -eq 0 ]