Repository navigation
316 lines (299 loc) · 11 KB
/
Copy pathrelease.yaml
File metadata and controls
316 lines (299 loc) · 11 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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
name: release
on:
workflow_dispatch:
push:
branches: [main]
paths:
- cmd/scip/version.txt
jobs:
setup:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.resolve.outputs.version }}
steps:
- uses: actions/checkout@v7
with:
ref: main
- id: resolve
run: |
# tr strips CRLF, trailing whitespace, blank lines, etc.
VERSION=$(tr -d '[:space:]' < cmd/scip/version.txt)
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "::error::cmd/scip/version.txt ($VERSION) must be MAJOR.MINOR.PATCH"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
publish:
needs: setup
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version: ${{ needs.setup.outputs.version }}
steps:
- uses: actions/checkout@v7
with:
ref: main
- name: Create and push tags
run: |
TAG="v${{ needs.setup.outputs.version }}"
BINDINGS_TAG="bindings/go/scip/$TAG"
for t in "$TAG" "$BINDINGS_TAG"; do
if git rev-parse "$t" &>/dev/null; then
if [ "$(git rev-parse "$t"^{})" != "$(git rev-parse HEAD)" ]; then
echo "::error::Tag $t exists but points to a different commit"
exit 1
fi
echo "Tag $t already exists at HEAD, skipping"
else
git tag "$t"
fi
done
git push origin "$TAG" "$BINDINGS_TAG" 2>/dev/null || echo "Tags already pushed"
- name: Create draft GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="v${{ needs.setup.outputs.version }}"
if gh release view "$TAG" &>/dev/null; then
DRAFT=$(gh release view "$TAG" --json isDraft -q '.isDraft')
if [ "$DRAFT" = "false" ]; then
echo "::error::Release $TAG is already published"
exit 1
fi
echo "Draft release $TAG already exists, skipping creation"
exit 0
fi
{
echo 'Download the CLI for your current platform using:'
echo ''
echo '```bash'
echo 'env \'
echo " TAG=\"$TAG\" \\"
echo ' OS="$(uname -s | tr '"'"'[:upper:]'"'"' '"'"'[:lower:]'"'"')" \'
echo ' ARCH="$(uname -m | sed -e '"'"'s/x86_64/amd64/'"'"')" \'
echo ' bash -c '"'"'curl -L "https://github.com/scip-code/scip/releases/download/$TAG/scip-$OS-$ARCH.tar.gz"'"'"' \'
echo '| tar xzf - scip'
echo '```'
} | gh release create "$TAG" --title "scip $TAG" --generate-notes --draft --notes-file -
release-crate:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: DeterminateSystems/nix-installer-action@v23
- uses: DeterminateSystems/magic-nix-cache-action@v15
with:
use-flakehub: "disabled"
- name: Publish crate
run: |
OUTPUT=$(nix develop -c cargo publish --token '${{ secrets.CRATES_TOKEN }}' 2>&1) && exit 0
if echo "$OUTPUT" | grep -q "already uploaded"; then
echo "Crate version already published, skipping"
else
echo "$OUTPUT"
exit 1
fi
working-directory: bindings/rust
publish-dotnet-bindings:
needs: publish
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # NuGet trusted-publishing OIDC
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: DeterminateSystems/nix-installer-action@v23
- uses: DeterminateSystems/magic-nix-cache-action@v15
with:
use-flakehub: "disabled"
# LICENSE and README.md are packed into the nupkg; LICENSE is a symlink
# in-tree (matches bindings/{haskell,rust,typescript}) and dotnet pack
# follows it, so no materialization step is needed.
- name: Pack
working-directory: bindings/dotnet
run: nix develop -c dotnet pack -c Release
# Trusted publishing: exchange this job's GitHub OIDC token for a
# short-lived nuget.org API key, so no long-lived secret exists. The
# trust policy on nuget.org must name this repository and this workflow
# file (`release.yaml`, no environment); `user` is the nuget.org account
# that owns the policy - a profile name, not an email. The key expires
# after an hour, so this step stays immediately before the push.
# See docs/Development.md for the nuget.org side of the setup.
- uses: NuGet/login@v1
id: nuget-login
with:
user: ${{ secrets.NUGET_USER }}
- name: Publish to NuGet
working-directory: bindings/dotnet
# --skip-duplicate keeps re-runs of a partially failed release green;
# NuGet publications are irreversible, like the other registries here.
run: |
nix develop -c dotnet nuget push \
'bin/Release/Scip.${{ needs.publish.outputs.version }}.nupkg' \
--source https://api.nuget.org/v3/index.json \
--api-key '${{ steps.nuget-login.outputs.NUGET_API_KEY }}' \
--skip-duplicate
publish-haskell-bindings:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: DeterminateSystems/nix-installer-action@v23
- uses: DeterminateSystems/magic-nix-cache-action@v15
with:
use-flakehub: "disabled"
- name: Build sdist
working-directory: bindings/haskell
run: |
nix develop -c cabal check
nix develop -c cabal sdist
- name: Publish to Hackage
uses: haskell-actions/hackage-publish@v1.1
with:
hackageServer: https://hackage.haskell.org
hackageToken: ${{ secrets.HACKAGE_TOKEN }}
packagesPath: bindings/haskell/dist-newstyle/sdist
publish: true
publish-jvm-bindings:
needs: publish
runs-on: ubuntu-latest
# Maven Central publication with waitUntil=published can block for
# 10-30 min per module while Sonatype mirrors propagate. Two
# sequential deploys (Java then Kotlin, which resolves Java from
# Central) means worst-case ~60 min.
timeout-minutes: 90
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: actions/setup-java@v6
with:
distribution: temurin
java-version: 25.0.4+101.0.LTS
cache: maven
server-id: central
server-username: MAVEN_USERNAME
server-password: MAVEN_PASSWORD
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
# scip-kotlin-bindings depends on scip-java-bindings at the same
# version and resolves it from Central, not from this runner. The
# release profile sets waitUntil=published, so the Java step
# blocks until the artifact is live on repo1.maven.org before the
# Kotlin step runs.
- name: Deploy scip-java-bindings to Maven Central
run: mvn -B -ntp -Prelease -f bindings/java/pom.xml deploy
env:
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
- name: Deploy scip-kotlin-bindings to Maven Central
run: mvn -B -ntp -Prelease -f bindings/kotlin/pom.xml deploy
env:
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
publish-npm:
needs: publish
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # npm trusted-publishing OIDC
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: actions/setup-node@v7
with:
# Trusted publishing needs npm >=11.5.1; Node 22 LTS ships npm 10.x.
node-version: 24
cache: npm
cache-dependency-path: bindings/typescript/package-lock.json
- name: Install dependencies
run: npm ci
working-directory: bindings/typescript
- name: Build
run: npm run build
working-directory: bindings/typescript
# LICENSE is a symlink in-tree (matches bindings/{haskell,rust}); npm-pack drops symlinks.
- name: Materialize LICENSE for npm pack
run: |
rm -f bindings/typescript/LICENSE
cp LICENSE bindings/typescript/LICENSE
- uses: JS-DevTools/npm-publish@v4
with:
package: bindings/typescript
access: public
provenance: true
build-go-binaries:
needs: publish
permissions:
contents: write
strategy:
matrix:
include:
- runner: ubuntu-latest
goos: linux
goarch: amd64
asset_name: scip-linux-amd64
- runner: ubuntu-latest
goos: linux
goarch: arm64
asset_name: scip-linux-arm64
- runner: macos-latest
goos: darwin
goarch: arm64
asset_name: scip-darwin-arm64
- runner: macos-latest
goos: darwin
goarch: amd64
asset_name: scip-darwin-amd64
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v7
with:
ref: v${{ needs.publish.outputs.version }}
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
- name: Build
env:
CGO_ENABLED: '0'
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
GOWORK: 'off'
run: go build -ldflags '-X main.Reproducible=true' -o scip ./cmd/scip
- name: Package
env:
ASSET: ${{ matrix.asset_name }}
run: |
tar czf "$ASSET.tar.gz" scip LICENSE
sha256sum "$ASSET.tar.gz" > "$ASSET.tar.gz.sha256" 2>/dev/null || \
shasum -a 256 "$ASSET.tar.gz" > "$ASSET.tar.gz.sha256"
- name: Upload release assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ASSET: ${{ matrix.asset_name }}
run: |
TAG="v${{ needs.publish.outputs.version }}"
DRAFT=$(gh release view "$TAG" --json isDraft -q '.isDraft')
if [ "$DRAFT" = "false" ]; then
echo "::error::Release $TAG is already published, refusing to upload"
exit 1
fi
gh release upload "$TAG" "$ASSET.tar.gz" "$ASSET.tar.gz.sha256" --clobber
finalize-release:
needs: [publish, release-crate, publish-dotnet-bindings, publish-haskell-bindings, build-go-binaries, publish-jvm-bindings, publish-npm]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- name: Mark release as non-draft
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release edit "v${{ needs.publish.outputs.version }}" --draft=false