diff --git a/standards/github-settings.md b/standards/github-settings.md index 0cd850ca7..634b1928b 100644 --- a/standards/github-settings.md +++ b/standards/github-settings.md @@ -242,14 +242,21 @@ but the categories are universal. #### Required Check Categories -| Check | Required | Check Name(s) | Notes | -|-------|----------|---------------|-------| -| **SonarCloud** | All repos | `SonarCloud` | Code quality, maintainability, security hotspots | -| **CodeQL** | All repos | `CodeQL` | SAST via GitHub-managed default setup — auto-detects all supported languages (see [ci-standards.md §2](ci-standards.md#2-codeql-analysis-github-managed-default-setup)) | -| **Dev-Lead Agent** | All repos | `Dev-Lead Agent / dev-lead` | AI code review and agent automation on every PR | -| **CI Pipeline** | All repos | Repo-specific (e.g., `build-and-test`, `TypeScript`, `Go`) | Lint, format, typecheck, test | -| **Coverage** | All repos | `coverage` or embedded in CI job | Must meet repo-defined thresholds | -| **Secret Scan** | All repos | `Secret scan (gitleaks)` | Full-history gitleaks scan — see [Push Protection Standard](push-protection.md#layer-3--ci-secret-scanning-secondary-defense) | +The `code-quality` ruleset enforces a fixed set of **required status-check contexts**. +The single source of truth for those contexts is the codified ruleset JSON, +[`.github-private/.github/rulesets/code-quality.json`](https://github.com/petry-projects/.github-private/blob/main/.github/rulesets/code-quality.json), +applied by `apply-rulesets.sh` / `bootstrap-new-repo.sh`. This table MUST match it. + +| Check | In `code-quality` ruleset | Check Name | Notes | +|-------|---------------------------|------------|-------| +| **SonarCloud** | ✅ required | `SonarCloud` | Code quality, maintainability, security hotspots | +| **CodeQL** | ✅ required | `CodeQL` | SAST via GitHub-managed default setup — auto-detects all supported languages (see [ci-standards.md §2](ci-standards.md#2-codeql-analysis-github-managed-default-setup)) | +| **AgentShield** | ✅ required | `agent-shield / AgentShield` | Agent-config security scan on every PR | +| **Dependency Audit** | ✅ required | `dependency-audit / Detect ecosystems` | Multi-ecosystem vulnerability audit (the per-ecosystem jobs skip and must NOT be required) | +| **Secret Scan** | ✅ required | `Secret scan (gitleaks)` | Full-history gitleaks scan in `ci.yml` — free on public repos, `GITLEAKS_LICENSE` on private (see [Push Protection Standard](push-protection.md#layer-3--ci-secret-scanning-secondary-defense)) | +| **Coverage** | ✅ required | `coverage` | Stack-aware `coverage` job in `ci.yml`: defaults to shell (bats) line-coverage via kcov and is green until tests exist, then expands per stack (Node/Go/Python). Thresholds are opt-in per stack — see BOOTSTRAP.md | +| **Dev-Lead Agent** | Runs per-PR | `Dev-Lead Agent / dev-lead` | AI review/automation on every PR; supplies the org-leads CODEOWNER approval for the `pr-quality` ruleset. Not a required status-check context here | +| **CI Pipeline** | Repo-specific | e.g. `build-and-test`, `TypeScript`, `Go` | Lint/format/typecheck/unit-test. The job name varies by stack, so it is not a universal required context; require it per-repo if desired | > **Check names must match exactly.** GitHub-managed CodeQL produces a check named > `CodeQL` — **not** `Analyze (actions)`, `Analyze (javascript-typescript)`, or diff --git a/standards/workflows/ci.yml b/standards/workflows/ci.yml index 1e3592444..31d75628c 100644 --- a/standards/workflows/ci.yml +++ b/standards/workflows/ci.yml @@ -4,15 +4,21 @@ # # ADOPTING THIS WORKFLOW: # 1. This ships verbatim into repos created from petry-projects/repo-template. -# 2. It is a CUSTOMIZE-PER-STACK stub: it passes out of the box so a fresh repo -# is green on day 0. Replace the placeholder step with your stack's -# lint / format / typecheck / unit-test / coverage steps (see the standard). -# 3. The job name `build-and-test` is the required CI status check. Keep it — or, -# if you split into per-language jobs (e.g. TypeScript, Go, Python), update the -# repo's branch-protection required checks to match the new job names. +# 2. `build-and-test` is a CUSTOMIZE-PER-STACK stub: it passes out of the box so +# a fresh repo is green on day 0. Replace its placeholder step with your +# stack's lint / format / typecheck / unit-test steps (see the standard). If +# you split it into per-language jobs (TypeScript, Go, Python), that is fine — +# it is not a required status check. +# 3. `secret-scan` (check name `Secret scan (gitleaks)`) and `coverage` ARE +# required status checks in the org `code-quality` ruleset. Keep both. +# • secret-scan is stack-agnostic gitleaks; free on public repos, and uses the +# org `GITLEAKS_LICENSE` secret on private org repos. +# • coverage defaults to shell (bats) line-coverage via kcov — the current +# YAML/Shell stack — and is green until you add tests. Uncomment the per-stack +# block as you add Node / Go / Python. See BOOTSTRAP.md. # # CONVENTIONS (enforced by the standard): -# • permissions: {} at top, least-privilege per job (CI needs contents: read) +# • permissions: {} at top, least-privilege per job # • triggers: push + pull_request to main # • concurrency keyed by ref+sha so a new push cancels the stale run # • SHA-pin every third-party action (never a tag/branch) @@ -42,12 +48,68 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # ── Replace the step below with your stack's checks ─────────────────────── - # Standard CI stages: lint, format check, type check, unit tests, coverage - # (plus integration / e2e / build where applicable). For example, a Node repo: + # Standard CI stages: lint, format check, type check, unit tests (coverage is + # the separate `coverage` job below). For example, a Node repo: # - uses: actions/setup-node@ # vX (with node-version + cache) # - run: npm ci # - run: npm run lint && npm run typecheck && npm test # See BOOTSTRAP.md and the CI standard. Until you add real steps, the - # placeholder below keeps the required `build-and-test` check green. + # placeholder below keeps this job green. - name: Placeholder — replace with real build/test steps - run: echo "CI stub — add your stack's lint/format/typecheck/test/coverage steps; see BOOTSTRAP.md." + run: echo "CI stub — add your stack's lint/format/typecheck/test steps; see BOOTSTRAP.md." + + secret-scan: + name: Secret scan (gitleaks) + runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + steps: + - name: Checkout (full history) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + - name: Run gitleaks + # Free on public repos; org private repos use the GITLEAKS_LICENSE secret. + # Refresh with: gh api repos/gitleaks/gitleaks-action/git/refs/tags/v3.0.0 --jq '.object.sha' + uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0 + with: + args: detect --source . --redact --verbose --exit-code 1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} + + coverage: + name: coverage + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + # Default lane: shell (bats) line-coverage via kcov — the current YAML/Shell + # stack. Real coverage runs automatically once tests/**/*.bats exist; a fresh + # repo with no tests passes green so it is not blocked on day 0. + - name: Shell (bats) coverage + run: | + shopt -s nullglob globstar + bats_tests=(tests/**/*.bats) + if [ "${#bats_tests[@]}" -eq 0 ]; then + echo "No tests/**/*.bats found — no coverage-bearing shell tests yet." + echo "Real shell coverage activates automatically once you add bats tests." + echo "For other stacks, uncomment the block below; see BOOTSTRAP.md." + echo "Passing so a fresh repo is green on day 0." + exit 0 + fi + sudo apt-get update -qq + sudo apt-get install -y -qq bats kcov + mkdir -p coverage + kcov --include-path=. --exclude-pattern=/tests/,/.git/ coverage bats -r tests + echo "Shell line-coverage report written to ./coverage (open index.html)." + + # ── Expand per stack as you add them (uncomment + set a threshold) ────────── + # Node: npx c8 --check-coverage --lines 80 npm test + # Go: go test ./... -coverprofile=cover.out && go tool cover -func=cover.out + # Python: pytest --cov --cov-fail-under=80 + # Wire your stack's coverage threshold here; see BOOTSTRAP.md.