Skip to content

Commit eb4e98c

Browse files
committed
Set up trusted publishing and harden workflows
1 parent a8140ce commit eb4e98c

File tree

5 files changed

+166
-9
lines changed

5 files changed

+166
-9
lines changed

.github/workflows/audit.yaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ name: Audit
99
- trunk
1010
schedule:
1111
- cron: "0 0 * * TUE"
12-
permissions:
13-
contents: read # required to checkout
12+
permissions: {}
1413
concurrency:
1514
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
1615
cancel-in-progress: true
1716
jobs:
1817
ruby:
1918
name: Audit Ruby Dependencies
2019
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read # required to checkout repository
2122

2223
steps:
2324
- name: Checkout repository
@@ -42,6 +43,8 @@ jobs:
4243
checks:
4344
- advisories
4445
- bans licenses sources
46+
permissions:
47+
contents: read # required to checkout repository
4548

4649
# Prevent sudden announcement of a new advisory from failing ci:
4750
continue-on-error: ${{ matrix.checks == 'advisories' }}
@@ -53,7 +56,9 @@ jobs:
5356
persist-credentials: false
5457

5558
- name: Install Rust toolchain
56-
uses: artichoke/setup-rust/audit@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
59+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
60+
with:
61+
toolchain: stable
5762

5863
- name: Generate Cargo.lock
5964
run: |
@@ -71,7 +76,8 @@ jobs:
7176
name: Run zizmor 🌈
7277
runs-on: ubuntu-latest
7378
permissions:
74-
security-events: write # required to write security events via sarif
79+
contents: read # required to checkout repository
80+
security-events: write # required to add findings via sarif
7581
steps:
7682
- name: Checkout repository
7783
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

.github/workflows/ci.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
persist-credentials: false
3333

3434
- name: Install Rust toolchain
35-
uses: artichoke/setup-rust/build-and-test@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
35+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
3636
with:
3737
toolchain: stable
3838

@@ -65,7 +65,7 @@ jobs:
6565
persist-credentials: false
6666

6767
- name: Install Rust toolchain
68-
uses: artichoke/setup-rust/build-and-test@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
68+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
6969
with:
7070
toolchain: "1.76.0"
7171

@@ -97,9 +97,10 @@ jobs:
9797
persist-credentials: false
9898

9999
- name: Install Rust toolchain
100-
uses: artichoke/setup-rust/lint-and-format@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
100+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
101101
with:
102102
toolchain: stable
103+
components: rustfmt,clippy
103104

104105
- name: Check formatting
105106
run: cargo fmt --check

.github/workflows/code-coverage.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ jobs:
3030
persist-credentials: false
3131

3232
- name: Install nightly Rust toolchain
33-
uses: artichoke/setup-rust/code-coverage@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
33+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
34+
with:
35+
toolchain: nightly
36+
components: llvm-tools-preview
3437

3538
- name: Setup grcov
3639
env:

.github/workflows/publish.yaml

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
---
2+
name: Publish
3+
"on":
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
permissions: {}
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: false
12+
13+
jobs:
14+
crates-io:
15+
name: Publish to crates.io
16+
if: github.event.created == true
17+
runs-on: ubuntu-latest
18+
environment:
19+
name: crates-io-publish
20+
permissions:
21+
actions: read # required to inspect CI workflow run status
22+
contents: read # required to checkout repository
23+
id-token: write # required for trusted publishing to crates.io
24+
env:
25+
CARGO_INCREMENTAL: 0
26+
CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
27+
RUST_BACKTRACE: 1
28+
steps:
29+
- name: Checkout repository
30+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
31+
with:
32+
persist-credentials: false
33+
fetch-depth: 1
34+
35+
- name: Configure ephemeral Rust homes
36+
shell: bash
37+
run: |
38+
set -euo pipefail
39+
# Use per-job temporary directories and avoid cross-run caches.
40+
mkdir -p "${RUNNER_TEMP}/cargo-home" "${RUNNER_TEMP}/rustup-home"
41+
echo "CARGO_HOME=${RUNNER_TEMP}/cargo-home" >> "$GITHUB_ENV"
42+
echo "RUSTUP_HOME=${RUNNER_TEMP}/rustup-home" >> "$GITHUB_ENV"
43+
44+
- name: Validate release tag
45+
shell: bash
46+
env:
47+
TAG: ${{ github.ref_name }}
48+
run: |
49+
set -euo pipefail
50+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
51+
echo "release tag '$TAG' does not match vX.Y.Z"
52+
exit 1
53+
fi
54+
55+
- name: Install Rust toolchain
56+
shell: bash
57+
run: |
58+
set -euo pipefail
59+
rustup set profile minimal
60+
rustup toolchain install stable --no-self-update
61+
rustup default stable
62+
rustc -Vv
63+
cargo -V
64+
65+
- name: Ensure Cargo.toml version matches tag
66+
shell: bash
67+
env:
68+
TAG_VERSION: ${{ github.ref_name }}
69+
run: |
70+
set -euo pipefail
71+
TAG_VERSION="${TAG_VERSION#v}"
72+
CARGO_VERSION="$(sed -n 's/^version = "\([0-9][0-9.]*\)".*/\1/p' Cargo.toml | head -n1)"
73+
if [[ -z "$CARGO_VERSION" ]]; then
74+
echo "failed to parse crate version from Cargo.toml"
75+
exit 1
76+
fi
77+
if [[ "$TAG_VERSION" != "$CARGO_VERSION" ]]; then
78+
echo "tag version '$TAG_VERSION' does not match crate version '$CARGO_VERSION'"
79+
exit 1
80+
fi
81+
82+
- name: Wait for CI on tagged commit
83+
shell: bash
84+
env:
85+
GH_TOKEN: ${{ github.token }}
86+
REPO: ${{ github.repository }}
87+
SHA: ${{ github.sha }}
88+
CI_WORKFLOW_NAME: CI
89+
POLL_INTERVAL_SECONDS: 20
90+
MAX_WAIT_SECONDS: 10800
91+
run: |
92+
set -euo pipefail
93+
94+
deadline="$(( $(date +%s) + MAX_WAIT_SECONDS ))"
95+
run_list=(
96+
gh run list
97+
--repo "${REPO}"
98+
--workflow "${CI_WORKFLOW_NAME}"
99+
--commit "${SHA}"
100+
--limit 50
101+
)
102+
103+
while true; do
104+
ci_count="$(
105+
"${run_list[@]}" --json status --jq 'length'
106+
)"
107+
108+
if [[ "${ci_count}" -eq 0 ]]; then
109+
echo "no '${CI_WORKFLOW_NAME}' workflow runs found yet for ${SHA}; waiting..."
110+
else
111+
pending_count="$(
112+
"${run_list[@]}" --json status --jq '[.[] | select(.status != "completed")] | length'
113+
)"
114+
if [[ "${pending_count}" -gt 0 ]]; then
115+
echo "${pending_count} '${CI_WORKFLOW_NAME}' runs pending for ${SHA}; waiting..."
116+
else
117+
non_success_count="$(
118+
"${run_list[@]}" --json conclusion --jq '[.[] | select(.conclusion != "success")] | length'
119+
)"
120+
if [[ "${non_success_count}" -eq 0 ]]; then
121+
echo "all '${CI_WORKFLOW_NAME}' runs for ${SHA} completed successfully."
122+
break
123+
fi
124+
echo "'${CI_WORKFLOW_NAME}' is not green for ${SHA}:"
125+
"${run_list[@]}" --json conclusion,url --jq '.[] | select(.conclusion != "success") | "- \(.url) => \(.conclusion)"'
126+
exit 1
127+
fi
128+
fi
129+
130+
if [[ "$(date +%s)" -ge "${deadline}" ]]; then
131+
echo "timed out waiting for '${CI_WORKFLOW_NAME}' to complete for ${SHA}"
132+
exit 1
133+
fi
134+
sleep "${POLL_INTERVAL_SECONDS}"
135+
done
136+
137+
- name: Authenticate with crates.io
138+
id: auth
139+
uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1.0.3
140+
141+
- name: Publish crate
142+
shell: bash
143+
env:
144+
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
145+
run: cargo publish

.github/workflows/rustdoc.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ jobs:
4040
persist-credentials: false
4141

4242
- name: Install Rust toolchain
43-
uses: artichoke/setup-rust/rustdoc@68e0ebb3b406970de1cc2ca807797c9156a198a7 # v2.0.1
43+
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master
44+
with:
45+
toolchain: nightly
4446

4547
- name: Check docs with no default features
4648
run: cargo doc --workspace --no-default-features

0 commit comments

Comments
 (0)