From 23fac8771c70a09c0d7fef8bd4ca13afc9930a62 Mon Sep 17 00:00:00 2001 From: Steve Morin Date: Fri, 5 Jun 2026 23:20:59 -0700 Subject: [PATCH] ci: publish to crates.io via trusted publishing (OIDC), drop token secret Switch the publish-crates job to crates.io Trusted Publishing: - run in `environment: crates` (matches the per-crate Trusted Publisher config) - grant `id-token: write` (mint the OIDC token) + `contents: read` - mint a short-lived token with `rust-lang/crates-io-auth-action` and pass it to each `cargo publish` via CARGO_REGISTRY_TOKEN - remove the `secrets.CARGO_REGISTRY_TOKEN` env and the token-presence check No stored API token is needed anymore. Trusted Publishers must exist on crates.io for both `togl-lib` and `togl` (repo smorin/toggle, workflow release.yml, environment `crates`); togl-lib was bootstrapped with a manual 0.0.0 publish since crates.io TP requires the crate to exist first. Refs P11. --- .github/workflows/release.yml | 32 +++++++++++++++++++------------- PROJECTS.md | 14 +++++++++----- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a9ceea5..ac12274 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,18 +57,23 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # Publish the library and CLI crates to crates.io. `togl-lib` is published - # first because `togl` depends on it (cargo waits for it to be available - # before the dependent publish). `togl-ffi` is `publish = false`. + # Publish the library and CLI crates to crates.io via Trusted Publishing + # (OIDC — no stored API token). `togl-lib` is published first because `togl` + # depends on it (cargo waits for it to be available). `togl-ffi` is + # `publish = false`. # - # Requires the `CARGO_REGISTRY_TOKEN` secret. Until it is set, this job fails - # loudly with a clear message but does not affect the binary-build job above. + # Setup (one-time): each published crate (`togl-lib`, `togl`) has a Trusted + # Publisher on crates.io pointing at this repo, workflow `release.yml`, and + # environment `crates`. The job runs in that environment and mints a + # short-lived token via `crates-io-auth-action`; no secret is required. publish-crates: name: Publish to crates.io runs-on: ubuntu-latest timeout-minutes: 30 - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + environment: crates + permissions: + id-token: write # required to mint the OIDC token for trusted publishing + contents: read steps: - name: Validate tag ref if: github.ref_type != 'tag' @@ -80,12 +85,9 @@ jobs: - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable - - name: Require crates.io token - run: | - if [ -z "${CARGO_REGISTRY_TOKEN}" ]; then - echo "::error::CARGO_REGISTRY_TOKEN secret is not set. Add it under repo Settings → Secrets to enable crates.io publishing." - exit 1 - fi + - name: Authenticate to crates.io (trusted publishing) + id: auth + uses: rust-lang/crates-io-auth-action@bbd81622f20ce9e2dd9622e3218b975523e45bbe # v1.0.4 # release-please bumps the workspace version but not the inter-crate dep # requirement, so pin togl-lib's `version` to this release before publish. @@ -99,6 +101,10 @@ jobs: # release-time edit. - name: Publish togl-lib run: cargo publish -p togl-lib --allow-dirty + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} - name: Publish togl run: cargo publish -p togl --allow-dirty + env: + CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} diff --git a/PROJECTS.md b/PROJECTS.md index 43445d9..d886f06 100644 --- a/PROJECTS.md +++ b/PROJECTS.md @@ -289,12 +289,16 @@ the CLI and auto-publish the library + CLI on each release tag. - [x] [P11-T01] Rename CLI package → `togl`; add `version` to `togl-lib` dep/dev-dep; `togl-ffi` `publish = false`; update `-p togl-cli` refs (flake, test script) - [x] [P11-T02] `publish-crates` job in `release.yml` (sync dep version → tag, - publish `togl-lib` then `togl`, `CARGO_REGISTRY_TOKEN`) + publish `togl-lib` then `togl`) +- [x] [P11-T03] Trusted Publishing (OIDC): job runs in `environment: crates` with + `id-token: write` + `rust-lang/crates-io-auth-action`; no API-token secret - [x] [P11-TS01] `cargo publish --dry-run` (togl-lib full; togl manifest), full test suite + `nix build .#togl` green after the rename ### Manual Steps (maintainer) -- Add repo secret `CARGO_REGISTRY_TOKEN` (crates.io API token). Until then the - publish job fails loudly but does not block the binary build. -- First publish fires on the next release tag (e.g. v0.6.0); crates.io versions - jump 0.2.3 → that release (allowed — versions only need to increase). +- crates.io uses **Trusted Publishing** (no `CARGO_REGISTRY_TOKEN` secret). Per + crate (`togl-lib`, `togl`) add a Trusted Publisher: repo `smorin/toggle`, + workflow `release.yml`, environment `crates`. (Done: `togl-lib` bootstrapped + with a manual `0.0.0` publish since crates.io TP needs the crate to exist first.) +- First real publish fires on the next release tag (e.g. v0.6.0); crates.io + versions jump 0.2.3 → that release (allowed — versions only need to increase).