diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e88169..b123f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `claude-baseline-review.yml` reusable-workflow caller in generated + projects' `.github/workflows/`, so new repos inherit the Tier 0 Claude + baseline PR reviewer at scaffold time. Thin caller of the org reusable in + `ByronWilliamsCPA/.github`, pinned at SHA `8de6560`; `repo-description` is + templated from `project_short_description`; the `ANTHROPIC_API_KEY` secret + reference is wrapped in a Jinja `{% raw %}{% endraw %}` guard so the + GitHub Actions `${{ ... }}` expression survives template rendering. No + caller-level `concurrency` block (the reusable owns concurrency). Part of + the org-wide tiered-pr-review rollout. - `qlty.yml` reusable-workflow caller in generated projects' `.github/workflows/` (satisfies CI-013 manifest gap); pins upstream `python-qlty-coverage.yml` at SHA `1b2d33c4`; runs on CI workflow_run diff --git a/{{cookiecutter.project_slug}}/.github/workflows/claude-baseline-review.yml b/{{cookiecutter.project_slug}}/.github/workflows/claude-baseline-review.yml new file mode 100644 index 0000000..bc2cef8 --- /dev/null +++ b/{{cookiecutter.project_slug}}/.github/workflows/claude-baseline-review.yml @@ -0,0 +1,59 @@ +# ============================================================================ +# Claude Baseline Review -- caller for {{ cookiecutter.project_name }} +# ============================================================================ +# Thin caller for the Tier 0 baseline reviewer. The reviewer logic, security +# posture, and prompt live in the reusable workflow in ByronWilliamsCPA/.github; +# this file only supplies the trigger, the permission ceiling, and this repo's +# framing. Generated from the org cookiecutter-python-template; part of the +# tiered-pr-review baseline that every org repo inherits. +# +# #CRITICAL: a called (reusable) workflow runs with a token bounded by the +# CALLER job's permissions. The four scopes below are the ceiling the reusable +# needs (id-token for the Claude App OIDC exchange); omitting any one fails the +# run at startup. +# #CRITICAL: do NOT add a workflow-level `concurrency` block here. The reusable +# already declares one; a caller block resolves to the same group for a +# pull_request event, and a called workflow that shares its caller's +# concurrency group cancels its own parent, failing the run at startup. +# ============================================================================ +name: Claude Baseline Review + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review, edited] + branches: + - main + +permissions: {} + +jobs: + review: + permissions: + contents: read + pull-requests: write + issues: write + id-token: write + # #VERIFY before bumping the pin: the target SHA must stay reachable from + # ByronWilliamsCPA/.github main. `gh api + # repos/ByronWilliamsCPA/.github/compare/main... --jq .status` must not + # return "diverged". Renovate tracks this pin. + uses: ByronWilliamsCPA/.github/.github/workflows/claude-baseline-review.yml@8de6560ef6089fa95d56c77186648186dac6ce26 # main + with: + repo-description: >- + {{ cookiecutter.project_short_description }} + sensitive-paths: >- + .github/workflows/, pyproject.toml, src/, scripts/ + escalation-guidance: | + - Changes to .github/workflows/ that touch permissions:, secrets, + id-token, or on: triggers. + - Changes to dependency manifests (pyproject.toml, requirements files, + lockfiles) that add or change a dependency source. + - Changes that touch secret handling, authentication, or credential + storage. + - Changes under scripts/ that perform writes via gh api, handle secrets, + or transfer or delete resources. + # Least-privilege: pass only the one secret the reusable declares in its + # workflow_call.secrets contract (ANTHROPIC_API_KEY, required: true), rather + # than forwarding every inherited secret via `secrets: inherit`. + secrets: + ANTHROPIC_API_KEY: {% raw %}${{ secrets.ANTHROPIC_API_KEY }}{% endraw %} # pragma: allowlist secret