From 9672fe0679e4c2dd5714b75e92f1cc13487c9430 Mon Sep 17 00:00:00 2001 From: OB Date: Sat, 5 Sep 2026 18:40:50 +0200 Subject: [PATCH 1/4] fix(docs): share repository instructions --- AGENTS.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ CHANGELOG.md | 5 +++++ CLAUDE.md | 50 +------------------------------------------------- package.json | 2 +- 4 files changed, 56 insertions(+), 50 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ee13f72 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,49 @@ +# coroboros/ci + +Reusable GitHub Actions workflows + composite actions for the Coroboros stack. + +## Commands + +- `actionlint -shellcheck=shellcheck` — workflows, `action.yml`, inline shell. +- `yamllint -c .yamllint .` — YAML lint. + +## Important files + +- `.github/workflows/javascript-npm-packages.yml` — bundled NPM pipeline (`preflight` / `security-gate` / `publish-package` / `security`). +- `.github/workflows/rust-packages.yml` — bundled Cargo pipeline (`preflight` matrix / `security-gate` / `verify-package` / `publish-package` / `security`) + opt-in cargo-dist binary layer (`dist-plan` / `dist-build` / `dist-host` / `dist-publish`, gated on `[package.metadata.dist]` or `[workspace.metadata.dist]`). +- `.github/workflows/security-gate.yml` — blocking gate `publish-package` `needs:`. `scan-supply-chain` (auto-routed: `Cargo.toml` → `security/rust/cargo-deny` advisories+bans+sources, else `security/osv-scanner`) + `scan-secrets` (gitleaks). A separate reusable workflow so the caller's `publish` can `needs:` the whole gate as one job, running each scan once. Imposed via the package workflows, importable standalone by a non-package repo. +- `.github/workflows/security.yml` — advisory layer, never blocks: `review-dependencies` (PR-only) + `check-licenses` (Rust, `security/rust/cargo-deny` `checks: licenses`). License/quality policy lives here, off the gate. +- `.github/workflows/{self-lint,self-test,self-security,self-release}.yml` — self-CI: lint, the security composites + `security-gate`/`security` workflows via local `./`, the `v0` rolling-tag move, and `self-test` smoke-testing every composite (plus `javascript/base`/`rust/base` on `test/fixtures/`) every PR. Workflow self-tests resolve their `@v0` composites against the released `v0`, so a brand-new composite is testable only once a release moves `v0` onto it. +- `.github/actions/{check-docs,javascript/base,rust/{base,native-deps,test-deps,install-dist,pin-version,harden-homebrew-formula},security/{gitleaks,osv-scanner,rust/cargo-deny},release/{verify-tag,generate-changelog,github-release,commit-artifacts}}/action.yml` — composites. +- `.github/dependabot.yml` — auto-PRs for pinned action SHAs. `renovate.json` + `.github/workflows/renovate.yml` — self-hosted Renovate (needs the `RENOVATE_TOKEN` PAT secret, scope `repo` + `workflow`) auto-bumps the version-pinned tooling; `.github/renovate/sync-tool-sha.sh` re-syncs each paired tarball SHA-256 in the same PR. +- `security/.gitleaks.toml` — canonical gitleaks ruleset. +- `security/deny.toml` — canonical cargo-deny ruleset, imposed via `--config` (consumer `deny.toml` ignored; `deny.exceptions.toml` rejected). An unfixable transitive advisory → PR a justified `ignore = ["RUSTSEC-…"]` (with `# why`) to this file, never a per-repo override. +- `README.md` — public documentation (single source for pipelines, composables, structure, flow, env, security, examples). + +## Rules + +- **Imposed, not proposed.** Zero `inputs:` / `secrets:` on reusable workflows unless variation is legitimate. +- **Pin third-party actions by commit SHA**, inline `# vX` comment. No `@main`, `@master`, `@vX`. +- **Pin tooling binaries by version.** SHA-256 verification on binary release tarballs. No `curl | bash`. +- **Composite refs**: `coroboros/ci/.github/actions/@v0` from reusable workflows and consumers. Exception — `self-security.yml` uses local `./.github/actions/security/` so a PR self-tests its own composites; a reusable workflow's `./` resolves to the caller's checkout, so `security.yml` must pin `@v0`. +- **`secrets:`** declares only what the job consumes. Never `secrets: inherit`. +- **`gitleaks` CLI direct**, not `gitleaks/gitleaks-action@v2` (paid org license). +- **House style**: + - Env values quoted: `KEY: "value"`. + - GH workflow log commands: `::error::`, `::warning::`, `::notice::`. No ANSI codes. + - Declare env keys only where consumed. + - Job ids: `verb-noun`, kebab-case (imperative verb + object), mirroring the GitLab CI pipelines — `verify-package`, `publish-package`, `generate-changelog`, `commit-artifacts`, `verify-tag`. Phase call-jobs that `uses:` another workflow may stay single-word (`preflight`, `security-gate`, `security`); the cargo-dist `dist-plan`/`dist-build`/`dist-host`/`dist-publish` jobs mirror its subcommands. Reusable-workflow job ids are consumer-visible — rename deliberately. +- **Action and workflow files = implementation only.** Rationale lives in `AGENTS.md` or `CHANGELOG.md`. + +## Adding a workflow or composite + +1. Update `README.md` (Pipelines / Composables table + Examples + Environment). +2. `actionlint -shellcheck=shellcheck` must exit 0. + +## Release flow + +- PR-only; no direct commits to `main`. +- In the PR (before merge): bump `package.json:version` + prepend `CHANGELOG.md` section (`## vX.Y.Z - DD/MM/YYYY`). +- Squash-merge. +- `git tag X.Y.Z && git push origin X.Y.Z` (no `v` prefix). `self-release.yml` then moves the rolling `v0` tag — no manual `git tag -f v0`. +- `gh release create X.Y.Z --title X.Y.Z --notes-file `. diff --git a/CHANGELOG.md b/CHANGELOG.md index 320eb7c..ace8f77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v0.2.11 - 05/09/2026 + +### Fixes +- Use `AGENTS.md` as the shared repository instruction source, imported by `CLAUDE.md`. + ## v0.2.10 - 08/07/2026 ### Fixes diff --git a/CLAUDE.md b/CLAUDE.md index 3ab9de1..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,49 +1 @@ -# coroboros/ci - -Reusable GitHub Actions workflows + composite actions for the Coroboros stack. - -## Commands - -- `actionlint -shellcheck=shellcheck` — workflows, `action.yml`, inline shell. -- `yamllint -c .yamllint .` — YAML lint. - -## Important files - -- `.github/workflows/javascript-npm-packages.yml` — bundled NPM pipeline (`preflight` / `security-gate` / `publish-package` / `security`). -- `.github/workflows/rust-packages.yml` — bundled Cargo pipeline (`preflight` matrix / `security-gate` / `verify-package` / `publish-package` / `security`) + opt-in cargo-dist binary layer (`dist-plan` / `dist-build` / `dist-host` / `dist-publish`, gated on `[package.metadata.dist]` or `[workspace.metadata.dist]`). -- `.github/workflows/security-gate.yml` — blocking gate `publish-package` `needs:`. `scan-supply-chain` (auto-routed: `Cargo.toml` → `security/rust/cargo-deny` advisories+bans+sources, else `security/osv-scanner`) + `scan-secrets` (gitleaks). A separate reusable workflow so the caller's `publish` can `needs:` the whole gate as one job, running each scan once. Imposed via the package workflows, importable standalone by a non-package repo. -- `.github/workflows/security.yml` — advisory layer, never blocks: `review-dependencies` (PR-only) + `check-licenses` (Rust, `security/rust/cargo-deny` `checks: licenses`). License/quality policy lives here, off the gate. -- `.github/workflows/{self-lint,self-test,self-security,self-release}.yml` — self-CI: lint, the security composites + `security-gate`/`security` workflows via local `./`, the `v0` rolling-tag move, and `self-test` smoke-testing every composite (plus `javascript/base`/`rust/base` on `test/fixtures/`) every PR. Workflow self-tests resolve their `@v0` composites against the released `v0`, so a brand-new composite is testable only once a release moves `v0` onto it. -- `.github/actions/{check-docs,javascript/base,rust/{base,native-deps,test-deps,install-dist,pin-version,harden-homebrew-formula},security/{gitleaks,osv-scanner,rust/cargo-deny},release/{verify-tag,generate-changelog,github-release,commit-artifacts}}/action.yml` — composites. -- `.github/dependabot.yml` — auto-PRs for pinned action SHAs. `renovate.json` + `.github/workflows/renovate.yml` — self-hosted Renovate (needs the `RENOVATE_TOKEN` PAT secret, scope `repo` + `workflow`) auto-bumps the version-pinned tooling; `.github/renovate/sync-tool-sha.sh` re-syncs each paired tarball SHA-256 in the same PR. -- `security/.gitleaks.toml` — canonical gitleaks ruleset. -- `security/deny.toml` — canonical cargo-deny ruleset, imposed via `--config` (consumer `deny.toml` ignored; `deny.exceptions.toml` rejected). An unfixable transitive advisory → PR a justified `ignore = ["RUSTSEC-…"]` (with `# why`) to this file, never a per-repo override. -- `README.md` — public documentation (single source for pipelines, composables, structure, flow, env, security, examples). - -## Rules - -- **Imposed, not proposed.** Zero `inputs:` / `secrets:` on reusable workflows unless variation is legitimate. -- **Pin third-party actions by commit SHA**, inline `# vX` comment. No `@main`, `@master`, `@vX`. -- **Pin tooling binaries by version.** SHA-256 verification on binary release tarballs. No `curl | bash`. -- **Composite refs**: `coroboros/ci/.github/actions/@v0` from reusable workflows and consumers. Exception — `self-security.yml` uses local `./.github/actions/security/` so a PR self-tests its own composites; a reusable workflow's `./` resolves to the caller's checkout, so `security.yml` must pin `@v0`. -- **`secrets:`** declares only what the job consumes. Never `secrets: inherit`. -- **`gitleaks` CLI direct**, not `gitleaks/gitleaks-action@v2` (paid org license). -- **House style**: - - Env values quoted: `KEY: "value"`. - - GH workflow log commands: `::error::`, `::warning::`, `::notice::`. No ANSI codes. - - Declare env keys only where consumed. - - Job ids: `verb-noun`, kebab-case (imperative verb + object), mirroring the GitLab CI pipelines — `verify-package`, `publish-package`, `generate-changelog`, `commit-artifacts`, `verify-tag`. Phase call-jobs that `uses:` another workflow may stay single-word (`preflight`, `security-gate`, `security`); the cargo-dist `dist-plan`/`dist-build`/`dist-host`/`dist-publish` jobs mirror its subcommands. Reusable-workflow job ids are consumer-visible — rename deliberately. -- **Action and workflow files = implementation only.** Rationale lives in `CLAUDE.md` or `CHANGELOG.md`. - -## Adding a workflow or composite - -1. Update `README.md` (Pipelines / Composables table + Examples + Environment). -2. `actionlint -shellcheck=shellcheck` must exit 0. - -## Release flow - -- PR-only; no direct commits to `main`. -- In the PR (before merge): bump `package.json:version` + prepend `CHANGELOG.md` section (`## vX.Y.Z - DD/MM/YYYY`). -- Squash-merge. -- `git tag X.Y.Z && git push origin X.Y.Z` (no `v` prefix). `self-release.yml` then moves the rolling `v0` tag — no manual `git tag -f v0`. -- `gh release create X.Y.Z --title X.Y.Z --notes-file `. +@AGENTS.md diff --git a/package.json b/package.json index c2243b2..40c467a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@coroboros/ci", - "version": "0.2.10", + "version": "0.2.11", "private": true, "description": "Reusable GitHub Actions CI for the Coroboros stack.", "license": "SEE LICENSE IN LICENSE.md", From 7ad3c8fd1a219a6c7f8bace6e59581bfadc7df94 Mon Sep 17 00:00:00 2001 From: OB Date: Sat, 5 Sep 2026 19:21:15 +0200 Subject: [PATCH 2/4] docs(instructions): correct workflow lint coverage --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index ee13f72..01cdc67 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ Reusable GitHub Actions workflows + composite actions for the Coroboros stack. ## Commands -- `actionlint -shellcheck=shellcheck` — workflows, `action.yml`, inline shell. +- `actionlint -shellcheck=shellcheck` — workflows and their inline shell. - `yamllint -c .yamllint .` — YAML lint. ## Important files From 9f5b96aa7a73cd2b87e7eb8c48059d9fc662389b Mon Sep 17 00:00:00 2001 From: OB Date: Sat, 5 Sep 2026 23:18:33 +0200 Subject: [PATCH 3/4] chore(deps): combine pending action updates --- .github/workflows/javascript-npm-packages.yml | 4 ++-- .github/workflows/renovate.yml | 2 +- .github/workflows/rust-packages.yml | 20 +++++++++---------- .github/workflows/security-gate.yml | 4 ++-- .github/workflows/security.yml | 4 ++-- .github/workflows/self-lint.yml | 6 +++--- .github/workflows/self-release.yml | 2 +- .github/workflows/self-security.yml | 4 ++-- .github/workflows/self-test.yml | 18 ++++++++--------- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/.github/workflows/javascript-npm-packages.yml b/.github/workflows/javascript-npm-packages.yml index ad7fd9e..bcc154e 100644 --- a/.github/workflows/javascript-npm-packages.yml +++ b/.github/workflows/javascript-npm-packages.yml @@ -36,7 +36,7 @@ jobs: if: ${{ github.ref_type == 'branch' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: coroboros/ci/.github/actions/check-docs@v0 - uses: coroboros/ci/.github/actions/javascript/base@v0 @@ -51,7 +51,7 @@ jobs: contents: write # for GitHub Release creation + commit-back to main id-token: write # for npm OIDC Trusted Publisher steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: main fetch-depth: 0 diff --git a/.github/workflows/renovate.yml b/.github/workflows/renovate.yml index 9611533..55c8508 100644 --- a/.github/workflows/renovate.yml +++ b/.github/workflows/renovate.yml @@ -17,7 +17,7 @@ jobs: renovate: runs-on: ubuntu-latest steps: - - uses: renovatebot/github-action@8217b3fc286df088d7c27f3255fe8414463bc0fd # v46.1.15 + - uses: renovatebot/github-action@316d7cd859606d6039a2182b7d69199e9b036835 # v46.2.1 with: token: ${{ secrets.RENOVATE_TOKEN }} env: diff --git a/.github/workflows/rust-packages.yml b/.github/workflows/rust-packages.yml index c25fec3..d63b688 100644 --- a/.github/workflows/rust-packages.yml +++ b/.github/workflows/rust-packages.yml @@ -29,7 +29,7 @@ jobs: os: [ubuntu-latest, macos-14, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: coroboros/ci/.github/actions/check-docs@v0 - uses: coroboros/ci/.github/actions/rust/base@v0 @@ -40,7 +40,7 @@ jobs: if: ${{ github.ref_type == 'branch' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: coroboros/ci/.github/actions/rust/native-deps@v0 - name: Verify the published crate builds shell: bash @@ -54,7 +54,7 @@ jobs: matrix: ${{ steps.plan.outputs.matrix }} tap: ${{ steps.detect.outputs.tap }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ github.sha }} @@ -112,12 +112,12 @@ jobs: env: CARGO_DIST_TARGET: "${{ join(matrix.targets, ' ') }}" steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ github.sha }} - name: Cache cargo + target - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: ${{ join(matrix.targets, '_') }} @@ -155,7 +155,7 @@ jobs: env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: main fetch-depth: 0 @@ -173,7 +173,7 @@ jobs: - name: Mint a short-lived crates.io token via OIDC id: auth if: ${{ env.CARGO_REGISTRY_TOKEN == '' }} - uses: rust-lang/crates-io-auth-action@bbd81622f20ce9e2dd9622e3218b975523e45bbe # v1.0.4 + uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 - name: Publish to crates.io shell: bash @@ -208,7 +208,7 @@ jobs: permissions: contents: write # upload release assets + undraft the release publish created steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ github.sha }} @@ -324,7 +324,7 @@ jobs: - name: Checkout Homebrew tap if: ${{ env.HOMEBREW_TAP_TOKEN != '' && needs.dist-plan.outputs.tap != '' }} - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: ${{ needs.dist-plan.outputs.tap }} token: ${{ secrets.HOMEBREW_TAP_TOKEN }} @@ -360,7 +360,7 @@ jobs: done - name: Setup Node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" registry-url: "https://registry.npmjs.org" diff --git a/.github/workflows/security-gate.yml b/.github/workflows/security-gate.yml index 900dfa5..16c591e 100644 --- a/.github/workflows/security-gate.yml +++ b/.github/workflows/security-gate.yml @@ -11,7 +11,7 @@ jobs: scan-supply-chain: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - id: detect name: Route supply-chain scan by ecosystem @@ -38,7 +38,7 @@ jobs: scan-secrets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: coroboros/ci/.github/actions/security/gitleaks@v0 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index ce4c9fd..43294b4 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v4 with: fail-on-severity: high @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: true steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - id: detect name: Detect a Rust manifest shell: bash diff --git a/.github/workflows/self-lint.yml b/.github/workflows/self-lint.yml index fd8746d..78255f1 100644 --- a/.github/workflows/self-lint.yml +++ b/.github/workflows/self-lint.yml @@ -18,7 +18,7 @@ jobs: check-actions: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install actionlint shell: bash @@ -41,7 +41,7 @@ jobs: check-yaml: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install yamllint shell: bash @@ -54,7 +54,7 @@ jobs: check-shell: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Run shellcheck on inline workflow scripts uses: ludeeus/action-shellcheck@00cae500b08a931fb5698e11e79bfbd38e612a38 # v2.0.0 env: diff --git a/.github/workflows/self-release.yml b/.github/workflows/self-release.yml index 1f817cc..389ab58 100644 --- a/.github/workflows/self-release.yml +++ b/.github/workflows/self-release.yml @@ -18,7 +18,7 @@ jobs: permissions: contents: write # force-push the rolling major tag steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Move rolling major tag shell: bash diff --git a/.github/workflows/self-security.yml b/.github/workflows/self-security.yml index 44020ee..c339ff3 100644 --- a/.github/workflows/self-security.yml +++ b/.github/workflows/self-security.yml @@ -14,7 +14,7 @@ jobs: scan-secrets: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: ./.github/actions/security/gitleaks @@ -22,7 +22,7 @@ jobs: scan-deps: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: ./.github/actions/security/osv-scanner security-gate: diff --git a/.github/workflows/self-test.yml b/.github/workflows/self-test.yml index 0b66149..4831e57 100644 --- a/.github/workflows/self-test.yml +++ b/.github/workflows/self-test.yml @@ -19,7 +19,7 @@ jobs: test-verify-tag: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Pass — HEAD matches the run SHA uses: ./.github/actions/release/verify-tag - name: Move HEAD so it diverges from the run SHA @@ -42,7 +42,7 @@ jobs: test-generate-changelog: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: SemVer gate rejects a non-tag ref id: gate continue-on-error: true @@ -57,7 +57,7 @@ jobs: test-commit-artifacts: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: path: _src - name: Build a fixture repo + local bare remote @@ -105,7 +105,7 @@ jobs: test-cargo-deny: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Plant a forbidden consumer override shell: bash run: | @@ -131,7 +131,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: ./.github/actions/rust/install-dist - name: Assert dist is installed and runnable shell: bash @@ -143,7 +143,7 @@ jobs: test-native-deps: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Plant a fixture ci/setup.sh that records CARGO_DIST_TARGET shell: bash run: | @@ -177,7 +177,7 @@ jobs: test-test-deps: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Absent hooks → no-op uses: ./.github/actions/rust/test-deps - name: Plant ci/test.env and ci/test-setup.sh @@ -205,7 +205,7 @@ jobs: env: NPM_CONFIG_FILE: "registry=https://registry.npmjs.org/" steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: path: _src - name: Stage the npm fixture at the workspace root @@ -224,7 +224,7 @@ jobs: test-rust-base: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: path: _src - name: Stage the rust fixture at the workspace root From abbb3835200db250dd89751c464a0c8643359fdd Mon Sep 17 00:00:00 2001 From: OB Date: Sat, 5 Sep 2026 23:44:13 +0200 Subject: [PATCH 4/4] docs: clarify shared constraints and release ownership --- AGENTS.md | 58 +++++++++++++++------------------------------------- CHANGELOG.md | 3 ++- 2 files changed, 19 insertions(+), 42 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 01cdc67..0196fb8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,49 +1,25 @@ # coroboros/ci -Reusable GitHub Actions workflows + composite actions for the Coroboros stack. +Reusable GitHub Actions workflows and composite actions for the Coroboros stack. `README.md` owns pipeline contracts, environment variables, security policy and consumer examples. -## Commands +## Project constraints -- `actionlint -shellcheck=shellcheck` — workflows and their inline shell. -- `yamllint -c .yamllint .` — YAML lint. +- Reusable workflows impose shared defaults; add inputs or secrets only for legitimate variation. Declare only consumed secrets; prohibit `secrets: inherit`. +- Pin third-party actions by full commit SHA with a version comment, and tooling binaries by version plus verified SHA-256. Do not pipe remote scripts into a shell. +- Reusable workflows and consumers reference composites at `coroboros/ci/.github/actions/@v0`. Local `./` refs resolve against the caller checkout; self-tests use them deliberately to exercise PR code. +- Security gates fail closed. `security/deny.toml` owns Cargo advisory, ban and source policy; consumer `deny.toml` is ignored and exception files are rejected. Propose justified transitive-advisory exceptions centrally. The separate advisory workflow owns non-blocking license/quality checks. +- Use the gitleaks CLI directly; the third-party action requires a paid organization licence. `security/.gitleaks.toml` is the canonical ruleset. +- Keep consumer-visible workflow job IDs stable: imperative kebab-case, with existing phase-call and cargo-dist names as exceptions. Quote environment values, declare them where consumed, and use GitHub log commands without ANSI escapes. +- Keep action/workflow files focused on implementation. Put rationale in the owning documentation or changelog; update affected README contracts and examples with behavior changes. -## Important files +## Validation -- `.github/workflows/javascript-npm-packages.yml` — bundled NPM pipeline (`preflight` / `security-gate` / `publish-package` / `security`). -- `.github/workflows/rust-packages.yml` — bundled Cargo pipeline (`preflight` matrix / `security-gate` / `verify-package` / `publish-package` / `security`) + opt-in cargo-dist binary layer (`dist-plan` / `dist-build` / `dist-host` / `dist-publish`, gated on `[package.metadata.dist]` or `[workspace.metadata.dist]`). -- `.github/workflows/security-gate.yml` — blocking gate `publish-package` `needs:`. `scan-supply-chain` (auto-routed: `Cargo.toml` → `security/rust/cargo-deny` advisories+bans+sources, else `security/osv-scanner`) + `scan-secrets` (gitleaks). A separate reusable workflow so the caller's `publish` can `needs:` the whole gate as one job, running each scan once. Imposed via the package workflows, importable standalone by a non-package repo. -- `.github/workflows/security.yml` — advisory layer, never blocks: `review-dependencies` (PR-only) + `check-licenses` (Rust, `security/rust/cargo-deny` `checks: licenses`). License/quality policy lives here, off the gate. -- `.github/workflows/{self-lint,self-test,self-security,self-release}.yml` — self-CI: lint, the security composites + `security-gate`/`security` workflows via local `./`, the `v0` rolling-tag move, and `self-test` smoke-testing every composite (plus `javascript/base`/`rust/base` on `test/fixtures/`) every PR. Workflow self-tests resolve their `@v0` composites against the released `v0`, so a brand-new composite is testable only once a release moves `v0` onto it. -- `.github/actions/{check-docs,javascript/base,rust/{base,native-deps,test-deps,install-dist,pin-version,harden-homebrew-formula},security/{gitleaks,osv-scanner,rust/cargo-deny},release/{verify-tag,generate-changelog,github-release,commit-artifacts}}/action.yml` — composites. -- `.github/dependabot.yml` — auto-PRs for pinned action SHAs. `renovate.json` + `.github/workflows/renovate.yml` — self-hosted Renovate (needs the `RENOVATE_TOKEN` PAT secret, scope `repo` + `workflow`) auto-bumps the version-pinned tooling; `.github/renovate/sync-tool-sha.sh` re-syncs each paired tarball SHA-256 in the same PR. -- `security/.gitleaks.toml` — canonical gitleaks ruleset. -- `security/deny.toml` — canonical cargo-deny ruleset, imposed via `--config` (consumer `deny.toml` ignored; `deny.exceptions.toml` rejected). An unfixable transitive advisory → PR a justified `ignore = ["RUSTSEC-…"]` (with `# why`) to this file, never a per-repo override. -- `README.md` — public documentation (single source for pipelines, composables, structure, flow, env, security, examples). +- Workflow/composite changes: `actionlint -shellcheck=shellcheck`, `yamllint -c .yamllint .`, and the relevant self-tests. +- Check consumer impact when changing reusable contracts. Self-tests that reference `@v0` exercise the released composites; local-ref tests exercise the PR. Tag-only behavior needs evidence from an authorized release. +- Documentation changes: check claims against source, affected links and `git diff --check`. -## Rules +## Release -- **Imposed, not proposed.** Zero `inputs:` / `secrets:` on reusable workflows unless variation is legitimate. -- **Pin third-party actions by commit SHA**, inline `# vX` comment. No `@main`, `@master`, `@vX`. -- **Pin tooling binaries by version.** SHA-256 verification on binary release tarballs. No `curl | bash`. -- **Composite refs**: `coroboros/ci/.github/actions/@v0` from reusable workflows and consumers. Exception — `self-security.yml` uses local `./.github/actions/security/` so a PR self-tests its own composites; a reusable workflow's `./` resolves to the caller's checkout, so `security.yml` must pin `@v0`. -- **`secrets:`** declares only what the job consumes. Never `secrets: inherit`. -- **`gitleaks` CLI direct**, not `gitleaks/gitleaks-action@v2` (paid org license). -- **House style**: - - Env values quoted: `KEY: "value"`. - - GH workflow log commands: `::error::`, `::warning::`, `::notice::`. No ANSI codes. - - Declare env keys only where consumed. - - Job ids: `verb-noun`, kebab-case (imperative verb + object), mirroring the GitLab CI pipelines — `verify-package`, `publish-package`, `generate-changelog`, `commit-artifacts`, `verify-tag`. Phase call-jobs that `uses:` another workflow may stay single-word (`preflight`, `security-gate`, `security`); the cargo-dist `dist-plan`/`dist-build`/`dist-host`/`dist-publish` jobs mirror its subcommands. Reusable-workflow job ids are consumer-visible — rename deliberately. -- **Action and workflow files = implementation only.** Rationale lives in `AGENTS.md` or `CHANGELOG.md`. - -## Adding a workflow or composite - -1. Update `README.md` (Pipelines / Composables table + Examples + Environment). -2. `actionlint -shellcheck=shellcheck` must exit 0. - -## Release flow - -- PR-only; no direct commits to `main`. -- In the PR (before merge): bump `package.json:version` + prepend `CHANGELOG.md` section (`## vX.Y.Z - DD/MM/YYYY`). -- Squash-merge. -- `git tag X.Y.Z && git push origin X.Y.Z` (no `v` prefix). `self-release.yml` then moves the rolling `v0` tag — no manual `git tag -f v0`. -- `gh release create X.Y.Z --title X.Y.Z --notes-file `. +- PR-only into `main`, then squash merge. Manually bump `package.json:version` and prepend the matching `CHANGELOG.md` entry before merge. +- After authorization, create an annotated SemVer tag without a `v` prefix on the reviewed merge commit, then a GitHub release using that version as its title and the changelog entry as notes. +- `self-release.yml` owns the rolling `v0` update. It does not bump manifests or create the GitHub release; do not move `v0` manually. diff --git a/CHANGELOG.md b/CHANGELOG.md index ace8f77..f0f8518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ## v0.2.11 - 05/09/2026 ### Fixes -- Use `AGENTS.md` as the shared repository instruction source, imported by `CLAUDE.md`. +- Update pinned GitHub Actions dependencies across reusable workflows and self-CI. +- Share concise project constraints and release ownership through `AGENTS.md`, imported by `CLAUDE.md`. ## v0.2.10 - 08/07/2026