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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
name: Publish
on:
push:
tags:
- 'v*'
jobs:
publish:
runs-on: ubuntu-latest
environment: crates-io
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Verify version matches tag
run: |
TAG="${GITHUB_REF#refs/tags/v}"
CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
if [ "$TAG" != "$CARGO_VERSION" ]; then
echo "Tag v$TAG does not match Cargo.toml version $CARGO_VERSION"
exit 1
fi
echo "VERSION=$CARGO_VERSION" >> "$GITHUB_ENV"
- name: rustfmt
run: cargo fmt --all --check
- name: clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: no-default feature build
run: cargo test --no-default-features --lib
- name: doc
run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
- name: no-default docs
run: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --no-default-features
- name: examples
run: cargo build --examples --all-features
- name: test
run: cargo test --all-features
- name: Install MSRV Rust
run: rustup toolchain install 1.80.0 --profile minimal --no-self-update
- name: MSRV all-features library check
run: cargo +1.80.0 check --lib --all-features
- name: MSRV raw library check
run: cargo +1.80.0 check --lib --no-default-features
- name: Check crates.io version
id: crates
run: |
status=$(curl -sS -o /tmp/crate-version.json -w '%{http_code}' \
-A 'durability-publish-workflow' \
"https://crates.io/api/v1/crates/durability/${VERSION}")
case "$status" in
200)
echo "published=true" >> "$GITHUB_OUTPUT"
;;
404)
echo "published=false" >> "$GITHUB_OUTPUT"
;;
*)
cat /tmp/crate-version.json
echo "Unexpected crates.io status: $status"
exit 1
;;
esac
- name: Dry run
if: steps.crates.outputs.published != 'true'
run: cargo publish --dry-run
- name: cargo-semver-checks
if: steps.crates.outputs.published != 'true'
uses: obi1kenobi/cargo-semver-checks-action@v2
- name: Authenticate (OIDC trusted publishing)
if: steps.crates.outputs.published != 'true'
# Pin to a specific tag: rust-lang/crates-io-auth-action does not
# publish a sliding `v1` major tag, so `@v1` resolves to v1.0.0
# (Node 20). v1.0.4 uses Node 24 and avoids the deprecation
# warning enforced June 2026.
uses: rust-lang/crates-io-auth-action@v1.0.4
id: auth
- name: Publish
if: steps.crates.outputs.published != 'true'
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}