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
name: Publish
on:
push:
tags:
- "v*"
permissions:
contents: write
id-token: write
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
- uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable
- name: Install cargo-set-version
run: cargo install cargo-set-version --locked --version 0.0.4
- name: Set version from tag
run: |
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
CURRENT=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
if [ "$TAG_VERSION" != "$CURRENT" ]; then
cargo set-version "$TAG_VERSION"
fi
# No cache: fetch the conformance fixtures fresh (see test.yml rationale).
# tests/concat_errors_test.rs, tests/s8_unquoted_starts.rs, and other
# sidecar-driven conformance tests need tests/testdata/{hocon,expected}/
# populated. Those dirs are gitignored (sidecars are fetched, not
# vendored), so without this step the publish-time `cargo test` fails with
# "no expected sidecar" panics on ce01-ce15 / us02-us30 etc.
- name: Fetch testdata fixtures
run: make testdata
- run: cargo test
- run: cargo test --features serde
# Publishing ships the adapter features, so the release gate has to run
# their tests: without --all-features the adapter suites compile to empty
# binaries and a broken adapter reaches crates.io green.
- run: cargo test --all-features
- name: Extract CHANGELOG section for this tag
# Pulls the section between `## [VERSION]` and the next `## [`
# from CHANGELOG.md so the GitHub Release body matches what's
# already committed and reviewed.
#
# Uses `index($0, str) == 1` (prefix match) rather than awk regex
# so SemVer build metadata (`+...`) and other regex metacharacters
# in version strings can't break or overmatch the section header.
#
# Runs BEFORE `cargo publish` (and the GitHub Release step below)
# so that a missing/incorrect CHANGELOG heading fails the run
# without first publishing to crates.io — crates.io doesn't allow
# republishing the same version, so an irreversible publish
# followed by a failed release step would leave a half-shipped tag.
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
awk -v ver="$VERSION" '
index($0, "## [" ver "]") == 1 { flag=1; next }
flag && index($0, "## [") == 1 { flag=0 }
flag
' CHANGELOG.md > /tmp/release-notes.md
if [ ! -s /tmp/release-notes.md ]; then
echo "::error::No CHANGELOG section found for v${VERSION}; aborting release so an empty body doesn't ship"
exit 1
fi
- name: Create GitHub Release
# Runs before `cargo publish` so a Release-creation failure doesn't
# leave us with a crate published but no GitHub Release entry
# (crates.io forbids republishing the same version, so a retry
# would fail at `cargo publish` and never reach this step again).
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
body_path: /tmp/release-notes.md
fail_on_unmatched_files: false
make_latest: true
- name: Authenticate with crates.io
id: auth
uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1
- name: Publish
run: cargo publish --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}