From b30560fa17c3a6881ba670cb27c0f1e7385d2df1 Mon Sep 17 00:00:00 2001 From: Ronald Tse Date: Fri, 7 Aug 2026 18:06:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(rake):=20cascade=20input=20on=20generic-ra?= =?UTF-8?q?ke.yml=20=E2=80=94=20one=20reusable,=20least-privilege=20caller?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #362. Supersedes #376's sibling-workflow approach. One reusable. One concern. Extended via input: - generic-rake.yml gains cascade boolean (default true) - tests-passed job gated by if: inputs.cascade - master/rake_test_only.yml is a thin caller (cascade: false, permissions: contents: read) — not a 144-line duplicate reusable - VARIANT_REGISTRY row for the caller-template pair (class g) Existing cascade consumers unchanged (cascade defaults true). --- .github/scripts/cimas-drift-audit.rb | 6 +++ .github/workflows/generic-rake.yml | 11 +++++ .../gh-actions/master/rake_test_only.yml | 32 +++++++++++++++ docs/generic-rake.md | 40 +++++++++++++++++-- 4 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 cimas-config/gh-actions/master/rake_test_only.yml diff --git a/.github/scripts/cimas-drift-audit.rb b/.github/scripts/cimas-drift-audit.rb index 35ca008..0cf818c 100644 --- a/.github/scripts/cimas-drift-audit.rb +++ b/.github/scripts/cimas-drift-audit.rb @@ -136,6 +136,12 @@ def supplementary_entries expected_delta_lines: 28, note: "Auto-generated GitHub Release notes opt-out (no-bundle-install variant) — introduced in ci#354, floor landed in ci#355.", }, + { + variant: "cimas-config/gh-actions/master/rake_test_only.yml", + parent: "cimas-config/gh-actions/master/rake.yml", + expected_delta_lines: 18, + note: "Least-privilege cascade-off caller — same generic-rake.yml reusable with cascade: false. Introduced with cascade input (closes ci#362).", + }, ].freeze # ---------- Data model ---------- diff --git a/.github/workflows/generic-rake.yml b/.github/workflows/generic-rake.yml index 9f251b0..47797cb 100644 --- a/.github/workflows/generic-rake.yml +++ b/.github/workflows/generic-rake.yml @@ -3,6 +3,16 @@ name: rake on: workflow_call: inputs: + cascade: + description: > + When true (default), fire tests-passed / do-release repository_dispatch + after the matrix succeeds. When false, skip the cascade job entirely so + callers can declare permissions: contents: read (least privilege). + Use false for sample/model repos and any gem whose release is triggered + externally rather than via do-release. + type: boolean + default: true + required: false tests-passed-event: description: Name of event sent with repository-dispatch after rake tests are passed successfully default: 'tests-passed' @@ -131,6 +141,7 @@ jobs: - run: bundle exec rake tests-passed: + if: ${{ inputs.cascade }} needs: rake runs-on: ubuntu-latest permissions: diff --git a/cimas-config/gh-actions/master/rake_test_only.yml b/cimas-config/gh-actions/master/rake_test_only.yml new file mode 100644 index 0000000..51cd6d1 --- /dev/null +++ b/cimas-config/gh-actions/master/rake_test_only.yml @@ -0,0 +1,32 @@ +# Least-privilege caller for repositories that run rake but do not participate +# in the release cascade. Thin variant of rake.yml — same reusable, cascade off. +# +# Use for repos that: +# - run `bundle exec rake` for CI, but +# - do NOT publish a gem on tag push (no do-release consumer), and +# - do NOT participate in the tests-passed downstream cascade. +# +# Gains `permissions: contents: read` by setting cascade: false on the single +# generic-rake.yml reusable (no sibling reusable — matrix body stays in one place). +# +# To switch a repo back to the cascade variant, replace this template mapping +# with `master/rake.yml` in the repo's cimas.yml entry. + +name: rake + +on: + push: + branches: [ master, main ] + tags: [ v* ] + pull_request: + +permissions: + contents: read + +jobs: + rake: + uses: metanorma/ci/.github/workflows/generic-rake.yml@main + with: + cascade: false + secrets: + pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }} diff --git a/docs/generic-rake.md b/docs/generic-rake.md index 120722a..b7f299c 100644 --- a/docs/generic-rake.md +++ b/docs/generic-rake.md @@ -26,8 +26,9 @@ jobs: | Input | Required | Default | Description | |-------|----------|---------|-------------| -| `tests-passed-event` | no | `tests-passed` | Event name dispatched after tests pass | -| `release-event` | no | `do-release` | Event name dispatched when tests pass on a tag ref | +| `cascade` | no | `true` | When true, fire `tests-passed` / `do-release` repository_dispatch after the matrix. When false, skip the cascade job so callers can declare `permissions: contents: read` | +| `tests-passed-event` | no | `tests-passed` | Event name dispatched after tests pass (only when `cascade: true`) | +| `release-event` | no | `do-release` | Event name dispatched when tests pass on a tag ref (only when `cascade: true`) | | `before-setup-ruby` | no | `''` | Command to run before Ruby setup | | `after-setup-ruby` | no | `''` | Command to run after Ruby setup | | `shell` | no | `bash` | Shell for running commands | @@ -48,7 +49,38 @@ jobs: 1. Calls `prepare-rake.yml` to resolve the test matrix. 2. Runs `bundle exec rake` across all Ruby versions and OSes. -3. On success, dispatches `tests-passed` event. -4. If the ref is a tag (`refs/tags/v*`), also dispatches `do-release` event (triggers the release pipeline). +3. When `cascade: true` (default): on success, dispatches `tests-passed` event; if the ref is a tag (`refs/tags/v*`), also dispatches `do-release` (triggers the release pipeline). +4. When `cascade: false`: matrix only — no repository_dispatch. Callers may declare `permissions: contents: read`. The test matrix is defined in [ruby-matrix.json](../.github/workflows/ruby-matrix.json). + +## Least-privilege caller (cascade off) + +One reusable. One concern. Extended via the `cascade` input — no sibling reusable. + +Cimas template: [`cimas-config/gh-actions/master/rake_test_only.yml`](../cimas-config/gh-actions/master/rake_test_only.yml) + +```yaml +# master/rake_test_only.yml (thin caller) +permissions: + contents: read +jobs: + rake: + uses: metanorma/ci/.github/workflows/generic-rake.yml@main + with: + cascade: false +``` + +### When to use cascade: false + +- Sample repositories (`mn-samples-*`) that CI but do not gem-release. +- Model repositories (`metanorma-model-*`) that validate grammar/schema but do not gem-release. +- Any gem whose release is triggered externally rather than via `do-release`. + +### When NOT to use cascade: false + +Any gem mapped to a release template (`master/release.yml`, `master/release_manual_notes.yml`, etc.). Those consume the `do-release` event that only fires when `cascade: true`. Switching a release-participating repo to cascade-off silently breaks its release chain. + +### How to switch + +In the target repo's `cimas.yml` entry, replace the `master/rake.yml` mapping with `master/rake_test_only.yml`, then run the cimas sync wave. Reverse to restore cascade.