-
Notifications
You must be signed in to change notification settings - Fork 15
383 lines (350 loc) Β· 15.2 KB
/
Copy pathbuild.yml
File metadata and controls
383 lines (350 loc) Β· 15.2 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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
name: Build and release OpenSAK
# Runs on version tags e.g. v1.0.0
# Create release: git tag v1.0.0 && git push origin v1.0.0
# Manual trigger: GitHub β Actions β Run workflow
on:
push:
tags:
- "v*"
workflow_dispatch:
env:
PYTHON_VERSION: "3.11"
# Opt into Homebrew's upcoming trust enforcement (default in 5.2/6.0) so the
# macOS jobs silently ignore the runners' pre-installed untrusted taps
# (aws/tap, azure/bicep) instead of printing a migration notice. create-dmg
# lives in the always-trusted core tap, so the build is unaffected.
HOMEBREW_REQUIRE_TAP_TRUST: "1"
jobs:
# ============================================================
# Tests β single gate; every build job runs only after this
# ============================================================
test:
uses: ./.github/workflows/tests.yml
# ============================================================
# Windows .exe
# ============================================================
build-windows:
name: "Build Windows .exe"
runs-on: windows-latest
needs: test
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e . pyinstaller
- name: Fetch boundary baseline
run: python scripts/fetch_boundary_baseline.py
- name: Build .exe
run: pyinstaller opensak.spec --clean --noconfirm
env:
PYTHONPATH: src
- name: Create ZIP
shell: powershell
run: Compress-Archive -Path dist/OpenSAK -DestinationPath dist/OpenSAK-${{ github.ref_name }}-Windows.zip
- uses: actions/upload-artifact@v7
with:
name: OpenSAK-${{ github.ref_name }}-Windows
path: dist/OpenSAK-${{ github.ref_name }}-Windows.zip
retention-days: 7
# ============================================================
# Linux AppImage
# ============================================================
build-linux:
name: "Build Linux AppImage"
runs-on: ubuntu-22.04
needs: test
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
- name: Install system packages
run: |
# Same mitigations as .github/actions/setup-qt/action.yml β
# confirmed root cause (from a cancelled run's raw log) was
# apt-get silently blocking on the dpkg/apt lock, still held by
# a background apt-daily/unattended-upgrades process right after
# runner boot, with zero output until cancelled. Clear/wait for
# that lock first, then route around a potentially degraded
# regional mirror as a second layer of defence.
sudo systemctl stop apt-daily.service apt-daily-upgrade.service \
apt-daily.timer apt-daily-upgrade.timer unattended-upgrades \
2>/dev/null || true
sudo killall -q apt apt-get unattended-upgrade 2>/dev/null || true
while sudo fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 || \
sudo fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do
echo "Waiting for another apt process to release the lock..."
sleep 2
done
sudo dpkg --configure -a || true
sudo sed -i \
-e 's|http://azure\.archive\.ubuntu\.com/ubuntu/|http://archive.ubuntu.com/ubuntu/|g' \
-e 's|http://azure\.archive\.ubuntu\.com/ubuntu|http://archive.ubuntu.com/ubuntu|g' \
/etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null || true
APT_OPTS="-o Acquire::Retries=3 -o Acquire::http::Timeout=15 -o Acquire::https::Timeout=15"
for attempt in 1 2 3; do
if sudo apt-get update -qq $APT_OPTS && \
sudo apt-get install -y $APT_OPTS \
libxcb-cursor0 libxcb-xinerama0 libxkbcommon-x11-0 libglib2.0-0 \
libegl1 libgl1-mesa-dev libdbus-1-3 xvfb libfuse2 imagemagick; then
exit 0
fi
echo "::warning::apt-get attempt $attempt failed, retrying in 15s..."
sleep 15
done
echo "::error::apt-get failed after 3 attempts"
exit 1
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e . pyinstaller
- name: Fetch boundary baseline
run: python scripts/fetch_boundary_baseline.py
- name: Build Linux binary
run: xvfb-run -a pyinstaller opensak.spec --clean --noconfirm
env:
PYTHONPATH: src
- name: Download appimagetool
run: |
wget -q https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool
chmod +x appimagetool
- name: Build AppDir
run: python3 scripts/make_appdir.py
- name: Build AppImage
run: ARCH=x86_64 ./appimagetool --appimage-extract-and-run AppDir OpenSAK-${{ github.ref_name }}-Linux-x86_64.AppImage
env:
ARCH: x86_64
- name: Verify output and create fallback tar.gz
run: |
if [ -f OpenSAK-${{ github.ref_name }}-Linux-x86_64.AppImage ]; then
echo "AppImage OK"
ls -lh OpenSAK-${{ github.ref_name }}-Linux-x86_64.AppImage
chmod +x OpenSAK-${{ github.ref_name }}-Linux-x86_64.AppImage
else
echo "AppImage failed - creating tar.gz fallback"
tar -czf OpenSAK-${{ github.ref_name }}-Linux-x86_64.tar.gz -C dist OpenSAK/
fi
- uses: actions/upload-artifact@v7
with:
name: OpenSAK-${{ github.ref_name }}-Linux
path: |
OpenSAK-${{ github.ref_name }}-Linux-x86_64.AppImage
OpenSAK-${{ github.ref_name }}-Linux-x86_64.tar.gz
retention-days: 7
# ============================================================
# macOS arm64 (Apple Silicon β M1/M2/M3/M4)
# ============================================================
build-macos-arm64:
name: "Build macOS arm64 (Apple Silicon)"
runs-on: macos-latest
needs: test
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e . pyinstaller
- name: Fetch boundary baseline
run: python scripts/fetch_boundary_baseline.py
- name: Build macOS .app (arm64)
run: pyinstaller opensak.spec --clean --noconfirm
env:
PYTHONPATH: src
# Code signing / notarization only run when the certificate secret is
# present, so the build still succeeds unsigned on forks and PRs that
# don't have access to the OpenSAK org's secrets. `if:` conditions
# can't reference `secrets` directly (GitHub Actions restriction), so
# the check is done once here and reused via this step's output.
- name: Check for Apple signing secrets
id: signing
run: echo "enabled=${{ secrets.APPLE_CERTIFICATE_P12_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
- name: Import signing certificate
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-import-certificate
with:
p12-base64: ${{ secrets.APPLE_CERTIFICATE_P12_BASE64 }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Codesign app bundle
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-codesign
with:
target-path: dist/OpenSAK.app
- name: Create .dmg (arm64)
run: |
brew install create-dmg
create-dmg \
--volname "OpenSAK" \
--window-size 500 300 \
--icon-size 100 \
--app-drop-link 350 150 \
OpenSAK-${{ github.ref_name }}-macOS-arm64.dmg \
dist/OpenSAK.app \
|| (cd dist && zip -r ../OpenSAK-${{ github.ref_name }}-macOS-arm64.zip OpenSAK.app && echo "Fallback ZIP created")
- name: Codesign .dmg
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-codesign
with:
target-path: OpenSAK-${{ github.ref_name }}-macOS-arm64.dmg
- name: Notarize .dmg
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-notarize
with:
target-path: OpenSAK-${{ github.ref_name }}-macOS-arm64.dmg
apple-id: ${{ secrets.APPLE_ID }}
app-specific-password: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
team-id: ${{ secrets.APPLE_TEAM_ID }}
- uses: actions/upload-artifact@v7
with:
name: OpenSAK-${{ github.ref_name }}-macOS-arm64
path: |
OpenSAK-${{ github.ref_name }}-macOS-arm64.dmg
OpenSAK-${{ github.ref_name }}-macOS-arm64.zip
retention-days: 7
# ============================================================
# macOS x86_64 (Intel)
# ============================================================
build-macos-x86:
name: "Build macOS x86_64 (Intel)"
runs-on: macos-15-intel
needs: test
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e . pyinstaller
- name: Fetch boundary baseline
run: python scripts/fetch_boundary_baseline.py
- name: Build macOS .app (x86_64)
run: pyinstaller opensak.spec --clean --noconfirm
env:
PYTHONPATH: src
- name: Check for Apple signing secrets
id: signing
run: echo "enabled=${{ secrets.APPLE_CERTIFICATE_P12_BASE64 != '' }}" >> "$GITHUB_OUTPUT"
- name: Import signing certificate
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-import-certificate
with:
p12-base64: ${{ secrets.APPLE_CERTIFICATE_P12_BASE64 }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Codesign app bundle
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-codesign
with:
target-path: dist/OpenSAK.app
- name: Create .dmg (x86_64)
run: |
brew install create-dmg
create-dmg \
--volname "OpenSAK" \
--window-size 500 300 \
--icon-size 100 \
--app-drop-link 350 150 \
OpenSAK-${{ github.ref_name }}-macOS-x86_64.dmg \
dist/OpenSAK.app \
|| (cd dist && zip -r ../OpenSAK-${{ github.ref_name }}-macOS-x86_64.zip OpenSAK.app && echo "Fallback ZIP created")
- name: Codesign .dmg
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-codesign
with:
target-path: OpenSAK-${{ github.ref_name }}-macOS-x86_64.dmg
- name: Notarize .dmg
if: steps.signing.outputs.enabled == 'true'
uses: ./.github/actions/macos-notarize
with:
target-path: OpenSAK-${{ github.ref_name }}-macOS-x86_64.dmg
apple-id: ${{ secrets.APPLE_ID }}
app-specific-password: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
team-id: ${{ secrets.APPLE_TEAM_ID }}
- uses: actions/upload-artifact@v7
with:
name: OpenSAK-${{ github.ref_name }}-macOS-x86_64
path: |
OpenSAK-${{ github.ref_name }}-macOS-x86_64.dmg
OpenSAK-${{ github.ref_name }}-macOS-x86_64.zip
retention-days: 7
# ============================================================
# Create GitHub Release
# ============================================================
create-release:
name: "Create GitHub Release"
runs-on: ubuntu-latest
needs: [build-windows, build-linux, build-macos-arm64, build-macos-x86]
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: actions/download-artifact@v8
with:
name: OpenSAK-${{ github.ref_name }}-Windows
path: release-files/
- uses: actions/download-artifact@v8
with:
name: OpenSAK-${{ github.ref_name }}-Linux
path: release-files/
- uses: actions/download-artifact@v8
with:
name: OpenSAK-${{ github.ref_name }}-macOS-arm64
path: release-files/
- uses: actions/download-artifact@v8
with:
name: OpenSAK-${{ github.ref_name }}-macOS-x86_64
path: release-files/
- name: List release files
run: ls -lh release-files/
- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ steps.version.outputs.VERSION }}
name: "OpenSAK ${{ steps.version.outputs.VERSION }}"
draft: false
prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
body: |
## OpenSAK ${{ steps.version.outputs.VERSION }}
### Download
| Platform | File | Instructions |
|----------|------|--------------|
| πͺ Windows | `OpenSAK-${{ steps.version.outputs.VERSION }}-Windows.zip` | Unzip and double-click `OpenSAK.exe` |
| π§ Linux | `OpenSAK-${{ steps.version.outputs.VERSION }}-Linux-x86_64.AppImage` | See instructions below |
| π macOS Apple Silicon (M1/M2/M3/M4) | `OpenSAK-${{ steps.version.outputs.VERSION }}-macOS-arm64.dmg` | Open and drag OpenSAK to Applications |
| π macOS Intel | `OpenSAK-${{ steps.version.outputs.VERSION }}-macOS-x86_64.dmg` | Open and drag OpenSAK to Applications |
> **Not sure which Mac you have?** Click the Apple menu () β "About This Mac".
> If it says "Apple M1/M2/M3/M4" choose **arm64**. If it says "Intel" choose **x86_64**.
### Linux
```bash
chmod +x OpenSAK-${{ steps.version.outputs.VERSION }}-Linux-x86_64.AppImage
./OpenSAK-${{ steps.version.outputs.VERSION }}-Linux-x86_64.AppImage
```
Or right-click β Properties β Allow executing as program, then double-click.
### Windows
1. Download `OpenSAK-${{ steps.version.outputs.VERSION }}-Windows.zip`
2. Right-click β Extract All
3. Open the extracted folder and double-click `OpenSAK.exe`
### macOS
1. Download the correct .dmg for your Mac (arm64 or x86_64)
2. Open the .dmg and drag OpenSAK to your Applications folder β the app is signed and notarized by Apple, so it opens normally on first launch
---
See [CHANGELOG.md](https://github.com/OpenSAK-Org/OpenSAK/blob/${{ steps.version.outputs.VERSION }}/CHANGELOG.md) for details.
files: release-files/**/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}