Skip to content

Publish crates

Publish crates #1

# 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/<crate>/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 }}