-
Notifications
You must be signed in to change notification settings - Fork 0
199 lines (173 loc) · 6.36 KB
/
Copy pathrelease.yaml
File metadata and controls
199 lines (173 loc) · 6.36 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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
name: Release
# ------------------------------------------------------------------------------
# Workflow Settings
# ------------------------------------------------------------------------------
#
# Tag-driven release pipeline in two phases:
#
# Phase 1 (version tag push): validate the tag against the workspace
# version, run the full test suite, verify crates package cleanly
# (publish dry run), then cut a DRAFT pre-release. Nothing is pushed to
# any registry yet.
#
# Phase 2 (a maintainer publishes the draft): publishing the draft --
# whether left as a pre-release or promoted to a full release -- fires
# the `release: published` event, which builds and pushes the container
# image to GHCR and publishes the crates to crates.io. crates.io
# publishing is a real publish when the RUST_CRATES_PUBLISH_TOKEN secret
# is configured, and a dry run otherwise.
#
# In other words, cutting the final release stays in human hands: the tag
# push only prepares a reviewable draft, and no artifacts are emitted until
# a maintainer publishes it.
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
release:
types: [published]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
permissions: {}
env:
CARGO_TERM_COLOR: always
jobs:
# ----------------------------------------------------------------------------
# Phase 1 (tag push): validate the tag matches Cargo.toml
# ----------------------------------------------------------------------------
validate:
if: github.event_name == 'push'
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: read
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Extract version from tag
id: version
env:
TAG: ${{ github.ref_name }}
run: |
TAG_VERSION="${TAG#v}"
CARGO_VERSION=$(perl -ne 'print $1 if /^version\s*=\s*"(.+)"/' Cargo.toml)
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "::error::Tag version ($TAG_VERSION) does not match Cargo.toml ($CARGO_VERSION)"
exit 1
fi
echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
# ----------------------------------------------------------------------------
# Phase 1 (tag push): run the full test suite
# ----------------------------------------------------------------------------
test:
if: github.event_name == 'push'
needs: [validate]
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Rust
uses: ./.github/actions/setup-rust
- name: Run all tests
run: make test
# ----------------------------------------------------------------------------
# Phase 1 (tag push): verify crates package cleanly (publish dry run)
# ----------------------------------------------------------------------------
publish-dry-run:
if: github.event_name == 'push'
needs: [validate]
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Rust
uses: ./.github/actions/setup-rust
with:
cache-suffix: publish
- name: Publish dry run
run: make publish-dry-run
# ----------------------------------------------------------------------------
# Phase 1 (tag push): cut the draft pre-release
#
# A maintainer must review and publish this draft to trigger Phase 2.
# ----------------------------------------------------------------------------
draft-release:
if: github.event_name == 'push'
needs: [validate, test, publish-dry-run]
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Create draft pre-release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
run: gh release create "$TAG" --generate-notes --prerelease --draft
# ----------------------------------------------------------------------------
# Phase 2 (draft published): build and publish the container image
# ----------------------------------------------------------------------------
container:
if: github.event_name == 'release'
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.event.release.tag_name }}
- name: Build and publish container
uses: ./.github/actions/ghcr-publish
with:
image-name: ${{ github.repository }}
# ----------------------------------------------------------------------------
# Phase 2 (draft published): publish crates to crates.io
#
# Real publish when RUST_CRATES_PUBLISH_TOKEN is configured, dry run
# otherwise.
# ----------------------------------------------------------------------------
crates-publish:
if: github.event_name == 'release'
needs: [container]
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
ref: ${{ github.event.release.tag_name }}
- name: Set up Rust
uses: ./.github/actions/setup-rust
with:
cache-suffix: publish
- name: Publish crates
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.RUST_CRATES_PUBLISH_TOKEN }}
run: |
if [ -n "$CARGO_REGISTRY_TOKEN" ]; then
echo "RUST_CRATES_PUBLISH_TOKEN detected; publishing to crates.io"
make publish
else
echo "RUST_CRATES_PUBLISH_TOKEN not set; performing publish dry run"
make publish-dry-run
fi