-
Notifications
You must be signed in to change notification settings - Fork 0
135 lines (123 loc) · 5.52 KB
/
Copy pathrelease.yml
File metadata and controls
135 lines (123 loc) · 5.52 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# SPDX-License-Identifier: Apache-2.0
name: Release
on:
push:
tags:
# Per-crate tags of the form ferro-<name>-vX.Y.Z[-pre]
- "ferro-*-v[0-9]+.[0-9]+.[0-9]+*"
jobs:
publish:
name: cargo publish
runs-on: [self-hosted, Linux, X64, kvm]
permissions:
contents: write # for creating the GitHub Release
id-token: write # for cosign keyless (OIDC) signing
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.91.1
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@v2
with:
tool: cargo-deny
- name: Parse tag → crate, version
id: tag
run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/}"
# Tag pattern: ferro-<crate>-v<version>
# Extract crate (everything between leading 'ferro-' and last '-v')
# and version (everything after last '-v').
CRATE="${TAG%-v*}"
VERSION="${TAG##*-v}"
if [ -z "$CRATE" ] || [ -z "$VERSION" ] || [ "$CRATE" = "$TAG" ]; then
echo "::error::Could not parse tag '$TAG' as ferro-<crate>-v<version>"
exit 1
fi
if [ ! -d "crates/$CRATE" ]; then
echo "::error::Tag references unknown crate '$CRATE' (no crates/$CRATE directory)"
exit 1
fi
echo "crate=$CRATE" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "Releasing crate=$CRATE version=$VERSION (tag $TAG)"
- name: Verify Cargo.toml version matches tag
run: |
set -euo pipefail
CRATE="${{ steps.tag.outputs.crate }}"
VERSION="${{ steps.tag.outputs.version }}"
MANIFEST_VERSION=$(awk -F'"' '/^version = "/ {print $2; exit}' "crates/$CRATE/Cargo.toml")
if [ "$MANIFEST_VERSION" != "$VERSION" ]; then
echo "::error::Cargo.toml version ($MANIFEST_VERSION) does not match tag version ($VERSION)"
exit 1
fi
- name: Pre-publish gate (clippy / fmt / test / deny)
run: |
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-features
cargo deny --all-features check
- name: cargo publish (dry-run)
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
cd "crates/${{ steps.tag.outputs.crate }}"
cargo publish --dry-run
- name: cargo publish
if: ${{ !contains(steps.tag.outputs.version, '-') }} # skip pre-release tags by default
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
cd "crates/${{ steps.tag.outputs.crate }}"
cargo publish
# Build the packaged .crate so we have a stable artifact to sign and to
# attach to the GitHub Release. `cargo package` produces the same
# tarball that `cargo publish` uploaded.
- name: Package crate artifact
id: pkg
if: ${{ !contains(steps.tag.outputs.version, '-') }} # skip pre-release tags
run: |
set -euo pipefail
CRATE="${{ steps.tag.outputs.crate }}"
VERSION="${{ steps.tag.outputs.version }}"
(cd "crates/$CRATE" && cargo package --no-verify)
ARTIFACT="target/package/${CRATE}-${VERSION}.crate"
test -f "$ARTIFACT" || { echo "::error::packaged artifact $ARTIFACT not found"; exit 1; }
echo "artifact=$ARTIFACT" >> "$GITHUB_OUTPUT"
# Keyless (OIDC) Sigstore signing of the published .crate tarball.
# Produces <artifact>.sig (signature) and <artifact>.crt (cert) that are
# attached to the GitHub Release for supply-chain provenance.
- name: Install cosign
if: ${{ !contains(steps.tag.outputs.version, '-') }}
uses: sigstore/cosign-installer@v3
- name: Sign crate artifact (cosign keyless)
if: ${{ !contains(steps.tag.outputs.version, '-') }}
env:
COSIGN_YES: "true" # non-interactive keyless flow
run: |
set -euo pipefail
ARTIFACT="${{ steps.pkg.outputs.artifact }}"
cosign sign-blob \
--output-signature "${ARTIFACT}.sig" \
--output-certificate "${ARTIFACT}.crt" \
"${ARTIFACT}"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.tag.outputs.tag }}
name: "${{ steps.tag.outputs.crate }} v${{ steps.tag.outputs.version }}"
body: |
See [`crates/${{ steps.tag.outputs.crate }}/CHANGELOG.md`](crates/${{ steps.tag.outputs.crate }}/CHANGELOG.md) for the entries in this release.
Supply-chain: the attached `.crate` tarball is signed with
cosign keyless (Sigstore). Verify with:
`cosign verify-blob --signature <crate>.sig --certificate <crate>.crt <crate>`
generate_release_notes: false
# Attach the signed tarball + signature + cert (only for stable,
# non-pre-release tags where the package/sign steps ran).
files: |
target/package/${{ steps.tag.outputs.crate }}-${{ steps.tag.outputs.version }}.crate
target/package/${{ steps.tag.outputs.crate }}-${{ steps.tag.outputs.version }}.crate.sig
target/package/${{ steps.tag.outputs.crate }}-${{ steps.tag.outputs.version }}.crate.crt
fail_on_unmatched_files: false