Repository navigation
292 lines (287 loc) · 15.3 KB
/
Copy pathrelease.yml
File metadata and controls
292 lines (287 loc) · 15.3 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
name: Bridge Stable Release
on:
push:
tags: ["v*"]
permissions:
contents: write
env:
# The Node.js runtime bundled into native-hid/node/ so Bridge can push
# DPI/polling-rate settings to non-Pulsar mice without end users needing
# Node.js installed separately. Bump by hand when a newer LTS ships.
NATIVE_HID_NODE_VERSION: v24.18.1
jobs:
windows:
name: Windows x64
runs-on: windows-latest
env:
WINDOWS_CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_BASE64 }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: native-hid/package-lock.json
- run: cargo fmt --check
- run: cargo test --locked
- run: cargo clippy --locked --all-targets -- -D warnings
- run: cargo build --release --locked
- name: Sign executable
if: env.WINDOWS_CERTIFICATE_BASE64 != ''
shell: pwsh
run: |
$certificate = Join-Path $env:RUNNER_TEMP "openmouse-bridge.pfx"
[IO.File]::WriteAllBytes($certificate, [Convert]::FromBase64String($env:WINDOWS_CERTIFICATE_BASE64))
& signtool sign /fd SHA256 /td SHA256 /tr http://timestamp.digicert.com /f $certificate /p $env:WINDOWS_CERTIFICATE_PASSWORD target/release/openmouse-bridge.exe
- name: Prepare native-hid (deps + bundled Node.js runtime)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
npm ci --prefix native-hid --omit=dev
# Trim node-hid's other-platform prebuilt bindings — this archive
# only ever runs on win32-x64.
Get-ChildItem native-hid/node_modules/node-hid/prebuilds -Directory |
Where-Object { $_.Name -ne "HID-win32-x64" } |
Remove-Item -Recurse -Force
Invoke-WebRequest -Uri "https://nodejs.org/dist/$env:NATIVE_HID_NODE_VERSION/node-$env:NATIVE_HID_NODE_VERSION-win-x64.zip" -OutFile node.zip
Expand-Archive node.zip -DestinationPath node-extracted
New-Item -ItemType Directory -Force -Path native-hid/node | Out-Null
Copy-Item "node-extracted/node-$env:NATIVE_HID_NODE_VERSION-win-x64/node.exe" native-hid/node/node.exe
- name: Package
shell: pwsh
run: |
Copy-Item assets/fonts/DM-Sans-OFL.txt DM-Sans-OFL.txt
Compress-Archive -Path target/release/openmouse-bridge.exe,README.md,DM-Sans-OFL.txt,native-hid -DestinationPath openmouse-bridge-windows-x64-full.zip
(Get-FileHash openmouse-bridge-windows-x64-full.zip -Algorithm SHA256).Hash.ToLower() + " openmouse-bridge-windows-x64-full.zip" | Set-Content openmouse-bridge-windows-x64-full.zip.sha256
# Small bridge archive under the original name for the older updaters
# (they cannot open archives over 16 MiB); see
# packaging/bridge/build-bridge-package.sh.
$stage = Join-Path $env:RUNNER_TEMP "bridge-package"
New-Item -ItemType Directory -Force -Path "$stage/native-hid/node", "$stage/native-hid/node_modules/node-hid", "$stage/native-hid/node_modules/@openmouse/protocol", "$stage/native-hid/node_modules/@openmouse/keyboard-protocol" | Out-Null
Copy-Item target/release/openmouse-bridge.exe, README.md, DM-Sans-OFL.txt $stage
Copy-Item native-hid/package.json "$stage/native-hid/"
Copy-Item native-hid/src "$stage/native-hid/src" -Recurse
Copy-Item native-hid/node_modules/node-hid/package.json "$stage/native-hid/node_modules/node-hid/"
Copy-Item native-hid/node_modules/@openmouse/protocol/package.json "$stage/native-hid/node_modules/@openmouse/protocol/"
Copy-Item native-hid/node_modules/@openmouse/keyboard-protocol/package.json "$stage/native-hid/node_modules/@openmouse/keyboard-protocol/"
Set-Content "$stage/native-hid/node/node.exe" "Placeholder: Bridge replaces this with the real Node.js runtime on first launch."
Compress-Archive -Path "$stage/*" -DestinationPath openmouse-bridge-windows-x64.zip -CompressionLevel Optimal
$size = (Get-Item openmouse-bridge-windows-x64.zip).Length
Write-Host "openmouse-bridge-windows-x64.zip: $size bytes (limit 16252928)"
if ($size -gt 16252928) { throw "bridge archive is over the older updaters' 16 MiB read budget" }
(Get-FileHash openmouse-bridge-windows-x64.zip -Algorithm SHA256).Hash.ToLower() + " openmouse-bridge-windows-x64.zip" | Set-Content openmouse-bridge-windows-x64.zip.sha256
- uses: actions/upload-artifact@v4
with:
name: bridge-windows
path: |
openmouse-bridge-windows-x64.zip
openmouse-bridge-windows-x64.zip.sha256
openmouse-bridge-windows-x64-full.zip
openmouse-bridge-windows-x64-full.zip.sha256
macos:
name: macOS universal
runs-on: macos-14
# Signing and notarization are automatic when these secrets exist;
# without them the app is ad-hoc signed.
env:
MACOS_CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE_BASE64 }}
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
MACOS_SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
targets: aarch64-apple-darwin,x86_64-apple-darwin
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: native-hid/package-lock.json
- run: cargo fmt --check
- run: cargo test --locked
env:
OPENMOUSE_SKIP_IOHID_TEST: "1"
- run: cargo clippy --locked --all-targets -- -D warnings
- run: cargo build --release --locked --target aarch64-apple-darwin
- run: cargo build --release --locked --target x86_64-apple-darwin
- name: Prepare native-hid (deps + bundled Node.js runtime)
run: |
set -euo pipefail
npm ci --prefix native-hid --omit=dev
# Trim node-hid's non-macOS prebuilt bindings; keep both Apple
# silicon and Intel since the Bridge binary itself is universal.
find native-hid/node_modules/node-hid/prebuilds -mindepth 1 -maxdepth 1 -type d \
! -name HID-darwin-arm64 ! -name HID-darwin-x64 -exec rm -rf {} +
curl -fsSL "https://nodejs.org/dist/$NATIVE_HID_NODE_VERSION/node-$NATIVE_HID_NODE_VERSION-darwin-arm64.tar.gz" | tar -xz
curl -fsSL "https://nodejs.org/dist/$NATIVE_HID_NODE_VERSION/node-$NATIVE_HID_NODE_VERSION-darwin-x64.tar.gz" | tar -xz
mkdir -p native-hid/node/bin
lipo -create \
"node-$NATIVE_HID_NODE_VERSION-darwin-arm64/bin/node" \
"node-$NATIVE_HID_NODE_VERSION-darwin-x64/bin/node" \
-output native-hid/node/bin/node
chmod +x native-hid/node/bin/node
- name: Package universal binary (existing bare-binary installs)
run: |
lipo -create \
target/aarch64-apple-darwin/release/openmouse-bridge \
target/x86_64-apple-darwin/release/openmouse-bridge \
-output openmouse-bridge
chmod +x openmouse-bridge
cp assets/fonts/DM-Sans-OFL.txt ./DM-Sans-OFL.txt
zip -r openmouse-bridge-macos-universal-full.zip openmouse-bridge README.md DM-Sans-OFL.txt native-hid
shasum -a 256 openmouse-bridge-macos-universal-full.zip > openmouse-bridge-macos-universal-full.zip.sha256
# Small bridge archive under the original name for the older updaters.
packaging/bridge/build-bridge-package.sh openmouse-bridge openmouse-bridge-macos-universal.zip
shasum -a 256 openmouse-bridge-macos-universal.zip > openmouse-bridge-macos-universal.zip.sha256
- name: Import signing certificate
if: env.MACOS_CERTIFICATE_BASE64 != ''
run: |
set -euo pipefail
keychain="$RUNNER_TEMP/openmouse-signing.keychain-db"
keychain_password="$(uuidgen)"
echo "$MACOS_CERTIFICATE_BASE64" | base64 --decode > "$RUNNER_TEMP/certificate.p12"
security create-keychain -p "$keychain_password" "$keychain"
security set-keychain-settings -lut 21600 "$keychain"
security unlock-keychain -p "$keychain_password" "$keychain"
security import "$RUNNER_TEMP/certificate.p12" -P "$MACOS_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$keychain"
security set-key-partition-list -S apple-tool:,apple: -s -k "$keychain_password" "$keychain"
security list-keychains -d user -s "$keychain" login.keychain-db
echo "MACOS_SIGN_IDENTITY=$MACOS_SIGN_IDENTITY" >> "$GITHUB_ENV"
- name: Build OpenMouse Bridge.app
run: |
version="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)"
mkdir -p dist
packaging/macos/build-app.sh openmouse-bridge native-hid "$version" dist
- name: Notarize app
if: env.MACOS_CERTIFICATE_BASE64 != '' && env.APPLE_ID != ''
run: |
set -euo pipefail
ditto -c -k --keepParent "dist/OpenMouse Bridge.app" notarize-app.zip
xcrun notarytool submit notarize-app.zip --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD" --wait
xcrun stapler staple "dist/OpenMouse Bridge.app"
- name: Package DMG and app update archive
run: |
set -euo pipefail
# Homebrew Python is externally managed (PEP 668), so use a venv.
python3 -m venv "$RUNNER_TEMP/dmgbuild-venv"
"$RUNNER_TEMP/dmgbuild-venv/bin/python" -m pip install --quiet dmgbuild
export PATH="$RUNNER_TEMP/dmgbuild-venv/bin:$PATH"
packaging/macos/build-dmg.sh "dist/OpenMouse Bridge.app" OpenMouse-Bridge-macos-universal.dmg
# Plain Info-ZIP (not ditto): the updater's strict extractor expects ordinary zip entries.
(cd dist && zip -r -X -q "../openmouse-bridge-macos-app.zip" "OpenMouse Bridge.app")
shasum -a 256 openmouse-bridge-macos-app.zip > openmouse-bridge-macos-app.zip.sha256
- name: Notarize DMG
if: env.MACOS_CERTIFICATE_BASE64 != '' && env.APPLE_ID != ''
run: |
set -euo pipefail
xcrun notarytool submit OpenMouse-Bridge-macos-universal.dmg --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_PASSWORD" --wait
xcrun stapler staple OpenMouse-Bridge-macos-universal.dmg
- name: Verify DMG
run: |
set -euo pipefail
hdiutil attach OpenMouse-Bridge-macos-universal.dmg -nobrowse -readonly -mountpoint "$RUNNER_TEMP/dmg"
test -d "$RUNNER_TEMP/dmg/OpenMouse Bridge.app"
codesign --verify --deep --strict "$RUNNER_TEMP/dmg/OpenMouse Bridge.app"
hdiutil detach "$RUNNER_TEMP/dmg"
- uses: actions/upload-artifact@v4
with:
name: bridge-macos
path: |
openmouse-bridge-macos-universal.zip
openmouse-bridge-macos-universal.zip.sha256
openmouse-bridge-macos-universal-full.zip
openmouse-bridge-macos-universal-full.zip.sha256
openmouse-bridge-macos-app.zip
openmouse-bridge-macos-app.zip.sha256
OpenMouse-Bridge-macos-universal.dmg
linux:
name: Linux x64
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Linux HID and GUI dependencies
run: sudo apt-get update && sudo apt-get install -y libudev-dev libgtk-3-dev libayatana-appindicator3-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libgl1-mesa-dev pkg-config
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
cache-dependency-path: native-hid/package-lock.json
- run: cargo fmt --check
- run: cargo test --locked
- run: cargo clippy --locked --all-targets -- -D warnings
- run: cargo build --release --locked
- name: Prepare native-hid (deps + bundled Node.js runtime)
run: |
set -euo pipefail
npm ci --prefix native-hid --omit=dev
# Trim node-hid's non-Linux prebuilt bindings; this archive only
# ever runs on linux-x64.
find native-hid/node_modules/node-hid/prebuilds -mindepth 1 -maxdepth 1 -type d \
! -name HID-linux-x64 -exec rm -rf {} +
curl -fsSL "https://nodejs.org/dist/$NATIVE_HID_NODE_VERSION/node-$NATIVE_HID_NODE_VERSION-linux-x64.tar.xz" | tar -xJ
mkdir -p native-hid/node/bin
cp "node-$NATIVE_HID_NODE_VERSION-linux-x64/bin/node" native-hid/node/bin/node
chmod +x native-hid/node/bin/node
- name: Package
run: |
cp target/release/openmouse-bridge ./openmouse-bridge
chmod +x openmouse-bridge
cp assets/openmouse-app-icon.png ./openmouse-app-icon.png
cp assets/fonts/DM-Sans-OFL.txt ./DM-Sans-OFL.txt
zip -r openmouse-bridge-linux-x64-full.zip openmouse-bridge openmouse-app-icon.png README.md DM-Sans-OFL.txt native-hid
sha256sum openmouse-bridge-linux-x64-full.zip > openmouse-bridge-linux-x64-full.zip.sha256
# Small bridge archive under the original name for the older updaters.
packaging/bridge/build-bridge-package.sh openmouse-bridge openmouse-bridge-linux-x64.zip openmouse-app-icon.png
rm openmouse-bridge openmouse-app-icon.png
sha256sum openmouse-bridge-linux-x64.zip > openmouse-bridge-linux-x64.zip.sha256
- uses: actions/upload-artifact@v4
with:
name: bridge-linux
path: |
openmouse-bridge-linux-x64.zip
openmouse-bridge-linux-x64.zip.sha256
openmouse-bridge-linux-x64-full.zip
openmouse-bridge-linux-x64-full.zip.sha256
release:
name: Publish stable release
needs: [windows, macos, linux]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify tag matches Cargo version
run: test "v$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)" = "${{ github.ref_name }}"
- uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Publish changelog and artifacts
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
# Re-cutting a tag replaces the assets of the existing release
# instead of deleting it, so the release is never missing.
if gh release view "${{ github.ref_name }}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
gh release upload "${{ github.ref_name }}" --repo "${{ github.repository }}" --clobber artifacts/*
else
gh release create "${{ github.ref_name }}" \
--repo "${{ github.repository }}" \
--verify-tag \
--generate-notes \
--latest \
artifacts/*
fi