-
Notifications
You must be signed in to change notification settings - Fork 6
193 lines (167 loc) · 7.95 KB
/
Copy pathrelease.yml
File metadata and controls
193 lines (167 loc) · 7.95 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
name: Release binaries
# Builds the CLI + GUI release binaries for Linux, macOS, and Windows when a
# version tag is pushed (e.g. `git tag v0.3.0 && git push origin v0.3.0`), then
# publishes a public GitHub Release with the three archives attached.
# `workflow_dispatch` runs the same build manually (off a branch) to smoke-test
# packaging without cutting a tag — it builds and collects but never publishes,
# since the publish step is guarded on a tag ref.
on:
push:
tags: ['v*']
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
# Read-only by default; only the publish job below escalates to
# contents: write. Build jobs compile third-party code (proc-macros run at
# build time) and must never hold a write-capable token.
permissions:
contents: read
# These jobs produce the binaries users run against real security keys, so
# all third-party actions are pinned to commit SHAs (a hijacked upstream tag
# would otherwise ship trojaned artifacts), and no shared build cache is
# restored — tag builds fall back to default-branch caches, which would let
# poisoned cache entries feed release binaries. Clean builds are cheap
# insurance at release cadence.
jobs:
linux-x86_64:
name: Linux x86_64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libpcsclite-dev \
libxkbcommon-dev libwayland-dev \
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
libx11-dev libxrandr-dev libxcb1-dev libdbus-1-dev \
libgl1-mesa-dev libssl-dev
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-06
with:
toolchain: stable
- name: Build release binaries
run: cargo build --release --locked -p keyroostctl -p keyroost --features keyroost/qr
- name: Package
run: |
ref="${GITHUB_REF_NAME//\//-}" # sanitize branch slashes for dispatch
mkdir -p dist
tar -czf "dist/keyroost-${ref}-linux-x86_64.tar.gz" \
-C target/release keyroostctl keyroost
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: keyroost-linux-x86_64
path: dist/*.tar.gz
macos-universal2:
name: macOS universal2
runs-on: macos-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# PC/SC (PCSC.framework) and the FIDO HID backend (IOKit via hidapi) come
# from the system SDK — no extra packages. Build both arches and lipo them
# into one universal2 binary that runs on Apple Silicon and Intel.
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-06
with:
toolchain: stable
targets: aarch64-apple-darwin, x86_64-apple-darwin
- name: Build release binaries (both arches)
run: |
cargo build --release --locked --target aarch64-apple-darwin -p keyroostctl -p keyroost --features keyroost/qr
cargo build --release --locked --target x86_64-apple-darwin -p keyroostctl -p keyroost --features keyroost/qr
- name: Combine into universal2 + package
run: |
ref="${GITHUB_REF_NAME//\//-}"
mkdir -p dist bin
for b in keyroostctl keyroost; do
lipo -create -output "bin/$b" \
"target/aarch64-apple-darwin/release/$b" \
"target/x86_64-apple-darwin/release/$b"
done
tar -czf "dist/keyroost-${ref}-macos-universal2.tar.gz" -C bin keyroostctl keyroost
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: keyroost-macos-universal2
path: dist/*.tar.gz
windows-x86_64:
name: Windows x86_64
runs-on: windows-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# PC/SC (WinSCard) and the FIDO HID backend (hid.dll via hidapi) are part
# of Windows — no extra packages. The GUI is built with the windows
# subsystem (see keyroost/src/main.rs) so it opens no console window.
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-06
with:
toolchain: stable
- name: Build release binaries
run: cargo build --release --locked -p keyroostctl -p keyroost --features keyroost/qr
- name: Package
shell: pwsh
run: |
$ref = $Env:GITHUB_REF_NAME -replace '/','-'
New-Item -ItemType Directory -Force -Path dist | Out-Null
Compress-Archive -Path target/release/keyroostctl.exe, target/release/keyroost.exe `
-DestinationPath "dist/keyroost-$ref-windows-x86_64.zip"
- name: Upload build artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: keyroost-windows-x86_64
path: dist/*.zip
publish:
name: Collect & publish
needs: [linux-x86_64, macos-universal2, windows-x86_64]
runs-on: ubuntu-latest
# `gh release create` writes a Release, so the default token needs write.
# id-token + attestations let attest-build-provenance sign a statement
# that these exact archives were built by this workflow run — users (and
# `gh attestation verify`) can check a download against it.
# actions: write lets the last step chain-dispatch the publish fanout.
permissions:
contents: write
id-token: write
attestations: write
actions: write
steps:
- name: Download all build artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
merge-multiple: true
- name: List artifacts
run: ls -lR dist
# Checksums ship with the release so users can verify downloads with
# plain `sha256sum -c`; the provenance attestation covers the stronger
# "built by this workflow from this commit" claim.
- name: Generate checksums
run: (cd dist && sha256sum *.tar.gz *.zip > SHA256SUMS)
- name: Attest build provenance
if: startsWith(github.ref, 'refs/tags/')
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: |
dist/*.tar.gz
dist/*.zip
# Publish a public GitHub Release with the three archives attached. Guarded
# on a tag ref, so a manual workflow_dispatch still builds + collects but
# never publishes. Uses the built-in token (no third-party action);
# --generate-notes writes the notes from commits/PRs since the last tag.
# This job downloads artifacts but never checks out the repo, so `gh` has
# no local git to infer the target from — pass it explicitly via --repo
# (GITHUB_REPOSITORY is always "owner/name" in the runner env).
- name: Publish GitHub Release
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: gh release create "${GITHUB_REF_NAME}" dist/*.tar.gz dist/*.zip dist/SHA256SUMS --repo "${GITHUB_REPOSITORY}" --generate-notes
# publish.yml's `on: release` trigger never fires for this release:
# GitHub suppresses workflow runs for events created with the default
# workflow token (anti-recursion). workflow_dispatch is exempt from
# that rule, so chain the fanout explicitly. Discovered live on
# v0.4.0, which needed a manual dispatch.
- name: Dispatch publish fanout
if: startsWith(github.ref, 'refs/tags/')
env:
GH_TOKEN: ${{ github.token }}
run: gh workflow run publish.yml -f tag="${GITHUB_REF_NAME}" --repo "${GITHUB_REPOSITORY}"