From bb3320d5e97ff2d4c4b3083ba8525cf62beb7053 Mon Sep 17 00:00:00 2001 From: Ben Breslauer Date: Wed, 7 Oct 2026 16:02:21 -0700 Subject: [PATCH 1/2] Replace publish-crates workflow with release-plz workflows Mirror github/twirp-rs: a manual Create release PR workflow and a publish-release workflow that runs release-plz on pushes to main. Keep crates.io Trusted Publishing via OIDC instead of a registry token. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/create-release-pr.yaml | 36 ++++++++++ .github/workflows/publish-crates.yaml | 92 ------------------------ .github/workflows/publish-release.yaml | 42 +++++++++++ CONTRIBUTING.md | 29 ++++---- release-plz.toml | 23 ++++++ 5 files changed, 118 insertions(+), 104 deletions(-) create mode 100644 .github/workflows/create-release-pr.yaml delete mode 100644 .github/workflows/publish-crates.yaml create mode 100644 .github/workflows/publish-release.yaml create mode 100644 release-plz.toml diff --git a/.github/workflows/create-release-pr.yaml b/.github/workflows/create-release-pr.yaml new file mode 100644 index 0000000..b1b5fca --- /dev/null +++ b/.github/workflows/create-release-pr.yaml @@ -0,0 +1,36 @@ +# Launch this workflow with the "Run workflow" button in the Actions tab of the repository. +# +# See https://github.com/github/rust-gems/blob/main/CONTRIBUTING.md#releasing-a-crate for more details. +name: Create release PR + +permissions: + pull-requests: write + contents: write + +on: workflow_dispatch + +jobs: + # Create a PR with the new versions and changelog, preparing the next release. When merged to main, + # the publish-release.yaml workflow will automatically publish any Rust package versions. + create-release-pr: + name: Create release PR + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + concurrency: # Don't run overlapping instances of this workflow + group: release-plz-${{ github.ref }} + cancel-in-progress: false + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + - name: Run release-plz + uses: release-plz/action@b8d6b54b02889ff2ae2bb82e8b57c3a8fc1683a5 # v0.5.139 + with: + command: release-pr + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish-crates.yaml b/.github/workflows/publish-crates.yaml deleted file mode 100644 index 1dcb670..0000000 --- a/.github/workflows/publish-crates.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# Publishes a single crate from this workspace to crates.io using Trusted Publishing. -# -# There is no `CARGO_REGISTRY_TOKEN` secret: `rust-lang/crates-io-auth-action` exchanges this -# workflow's GitHub OIDC identity for a short-lived crates.io token that expires after the run. -# -# One-time setup per crate, on https://crates.io/crates//settings/trusted-publishing: -# Repository owner: github -# Repository name: rust-gems -# Workflow name: publish-crates.yaml -# Environment: crates-io -# The environment name must match the `environment:` value below exactly, or crates.io rejects -# the token exchange. A crate must be published manually once before it can be configured. -name: Publish crates - -on: - workflow_dispatch: - inputs: - crate: - description: Crate to publish, at the version in its Cargo.toml - required: true - type: choice - options: - - bpe - - bpe-openai - - casefold - - commutative_hasher - - consistent-choose-k - - geo_filters - - hash-sorted-map - - sparse-ngrams - - string-offsets - crate_name_override: - description: Crate name to publish instead, for crates missing from the list above - required: false - type: string - dry_run: - description: Package and verify the crate without uploading it - type: boolean - default: false - -permissions: - contents: read - id-token: write # Required to mint the crates.io OIDC token. - -jobs: - publish: - name: Publish ${{ inputs.crate_name_override || inputs.crate }} - runs-on: ubuntu-latest - # Gate releases behind an environment so protection rules apply, and so the OIDC claim - # matches the trusted publisher configured on crates.io. - environment: crates-io - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - - - uses: rui314/setup-mold@7e4f20ad28a2e8ca6fd0892ccf72e2abb706b9c3 - - # `crate_name_override` wins when set, because a choice input always has one option - # selected and so can't express "none of these". - - name: Resolve crate - id: resolve - env: - CHOICE: ${{ inputs.crate }} - OVERRIDE: ${{ inputs.crate_name_override }} - run: | - crate=$(printf '%s' "${OVERRIDE:-$CHOICE}" | tr -d '[:space:]') - # Check the name against the workspace so a typo fails here with a clear message, - # and so nothing unvetted reaches the cargo commands below. - publishable=$(cargo metadata --no-deps --format-version 1 | - jq -r '.packages[] | select(.publish != []) | .name') - if ! printf '%s\n' "$publishable" | grep -qxF "$crate"; then - echo "::error::'$crate' is not a publishable crate. Available: $(echo $publishable)" - exit 1 - fi - echo "crate=$crate" >> "$GITHUB_OUTPUT" - - - name: Package and verify - run: cargo publish --package "$CRATE" --dry-run - env: - CRATE: ${{ steps.resolve.outputs.crate }} - - - name: Get crates.io token - if: ${{ !inputs.dry_run }} - id: auth - uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 - - # Verification already happened in the dry run above, on this exact tree. - - name: Publish - if: ${{ !inputs.dry_run }} - run: cargo publish --package "$CRATE" --no-verify - env: - CRATE: ${{ steps.resolve.outputs.crate }} - CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} diff --git a/.github/workflows/publish-release.yaml b/.github/workflows/publish-release.yaml new file mode 100644 index 0000000..a0d8a3b --- /dev/null +++ b/.github/workflows/publish-release.yaml @@ -0,0 +1,42 @@ +# This workflow only publishes releases for PR's created by create-release-pr.yaml +# +# Crates are published with crates.io Trusted Publishing: release-plz exchanges this workflow's +# GitHub OIDC identity for a short-lived crates.io token, so there is no `CARGO_REGISTRY_TOKEN` +# secret. Each crate's trusted publisher on crates.io must be configured with workflow +# `publish-release.yaml` and environment `crates-io`. +# +# See https://github.com/github/rust-gems/blob/main/CONTRIBUTING.md#releasing-a-crate for more details. +name: Release any unpublished crates + +permissions: + contents: write + +on: + push: + branches: + - main + +jobs: + # Release any unpublished packages + release-plz-release: + name: Release-plz release + runs-on: ubuntu-latest + # Gate releases behind an environment so protection rules apply, and so the OIDC claim + # matches the trusted publisher configured on crates.io. + environment: crates-io + permissions: + contents: write + id-token: write # Required to mint the crates.io OIDC token. + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable + - name: Run release-plz + uses: release-plz/action@b8d6b54b02889ff2ae2bb82e8b57c3a8fc1683a5 # v0.5.139 + with: + command: release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aa154f7..1549309 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,21 +31,26 @@ Here are a few things you can do that will increase the likelihood of your pull ## Releasing a crate -Crates are published to [crates.io](https://crates.io) with -[Trusted Publishing](https://crates.io/docs/trusted-publishing), so there is no long-lived API -token stored in this repository. The `Publish crates` workflow exchanges its GitHub OIDC identity -for a token that is revoked when the run ends. - -1. Bump `version` in the crate's `Cargo.toml` and merge that change to `main`. -2. Run the [`Publish crates`](../../actions/workflows/publish-crates.yaml) workflow via - *Run workflow*, pick the crate, and optionally tick *dry-run* first to package and verify it - without uploading. If a newly added crate isn't in the dropdown yet, type its name into - *crate_name_override* instead — and add it to the dropdown in `publish-crates.yaml` while - you're there. +Releases are managed with [release-plz](https://release-plz.dev). Crates are published to +[crates.io](https://crates.io) with [Trusted Publishing](https://crates.io/docs/trusted-publishing), +so there is no long-lived API token stored in this repository. release-plz exchanges the +workflow's GitHub OIDC identity for a token that is revoked when the run ends. + +1. Run the [`Create release PR`](../../actions/workflows/create-release-pr.yaml) workflow via + *Run workflow*. This uses `release-plz` to open a PR that bumps the versions and updates the + changelogs of any crates that changed since their last release. +2. Adjust the generated changelog(s) and version number(s) as necessary. +3. Get PR approval. +4. Merge the PR. The [`publish-release.yaml`](../../actions/workflows/publish-release.yaml) + workflow will automatically publish a new release of any crate whose version has changed, + and create the matching git tag and GitHub release. + +Development-only crates (benchmarks and tests) are excluded from releases in +[`release-plz.toml`](release-plz.toml). Add new ones there too. A crate has to be published manually once before crates.io will let you configure a trusted publisher for it. Configure it at `https://crates.io/crates//settings/trusted-publishing` -with repository `github/rust-gems`, workflow `publish-crates.yaml`, and environment `crates-io`. +with repository `github/rust-gems`, workflow `publish-release.yaml`, and environment `crates-io`. The environment name must match the workflow's `environment:` exactly or the token exchange fails. ## Resources diff --git a/release-plz.toml b/release-plz.toml new file mode 100644 index 0000000..6bcfbff --- /dev/null +++ b/release-plz.toml @@ -0,0 +1,23 @@ +[workspace] +release_always = false + +# Development-only crates that are never published. +[[package]] +name = "bpe-benchmarks" +release = false + +[[package]] +name = "bpe-tests" +release = false + +[[package]] +name = "casefold-benchmarks" +release = false + +[[package]] +name = "consistent-choose-k-benchmarks" +release = false + +[[package]] +name = "hash-sorted-map-benchmarks" +release = false From 65ef08f8510e300b80f324399c39cd4c60ebc71c Mon Sep 17 00:00:00 2001 From: Ben Breslauer Date: Wed, 7 Oct 2026 16:15:23 -0700 Subject: [PATCH 2/2] Serialize release runs and fix comment typo Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish-release.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-release.yaml b/.github/workflows/publish-release.yaml index a0d8a3b..c3f3216 100644 --- a/.github/workflows/publish-release.yaml +++ b/.github/workflows/publish-release.yaml @@ -1,4 +1,4 @@ -# This workflow only publishes releases for PR's created by create-release-pr.yaml +# This workflow only publishes releases for PRs created by create-release-pr.yaml # # Crates are published with crates.io Trusted Publishing: release-plz exchanges this workflow's # GitHub OIDC identity for a short-lived crates.io token, so there is no `CARGO_REGISTRY_TOKEN` @@ -27,6 +27,9 @@ jobs: permissions: contents: write id-token: write # Required to mint the crates.io OIDC token. + concurrency: # Serialize releases so runs don't race to publish the same version or tag + group: release-plz-release-${{ github.ref }} + cancel-in-progress: false steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1