1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
name: Publish
# Publishes to crates.io via Trusted Publishing (OIDC) — no long-lived token.
#
# One-time setup on crates.io (after the crate exists): crate Settings ->
# Trusted Publishing -> GitHub, with repository zhxiaogg/async-anthropic and
# workflow publish.yml.
#
# Bootstrap caveat: trusted publishing can only be configured for crates that
# already exist on crates.io, so the very first publish falls back to the
# CARGO_REGISTRY_TOKEN repo secret. Delete the secret once OIDC is configured.
on:
push:
tags:
workflow_dispatch:
permissions:
contents: read
env:
# Match tests.yml — single source of truth for the pinned toolchain.
RUST_TOOLCHAIN: "1.96.0"
jobs:
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
permissions:
id-token: write # mint the OIDC token exchanged for a temp crates.io token
contents: read
steps:
- uses: actions/checkout@v7
- name: Install Rust ${{ env.RUST_TOOLCHAIN }}
uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
- name: Authenticate with crates.io (OIDC)
id: auth
uses: rust-lang/crates-io-auth-action@v1
# First-ever publish has no trusted-publishing config yet; fall through
# to the token secret below instead of failing the run.
continue-on-error: true
- name: cargo publish
run: cargo publish --locked
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token || secrets.CARGO_REGISTRY_TOKEN }}