77# Artifacts:
88# OpenView-linux-x64.zip
99# OpenView-windows-x64.zip
10- # OpenView-macos-arm64.zip (Developer ID signed + notarized when the
11- # AC_CERTIFICATE / APPLE_* secrets are present)
12- # OpenView-android.apk (release-signed when the KEYSTORE_* secrets are
13- # present; tag builds FAIL without them)
10+ # OpenView-macos-arm64.zip (ad-hoc signed — see the macOS job)
1411# SHA256SUMS.txt
1512#
16- # Required secrets for a fully signed release:
17- # macOS AC_CERTIFICATE, AC_CERTIFICATE_PASSWORD, KEYCHAIN_PASSWORD,
18- # APPLE_ID, APPLE_PASSWORD (app-specific pw), APPLE_TEAM_ID
19- # Android KEYSTORE_BASE64, KEY_ALIAS, KEY_PASSWORD, STORE_PASSWORD
13+ # Desktop only. Mobile ships through the App Store and Google Play, and the
14+ # Android APK / iOS pipeline is tracked separately — do not add a mobile job
15+ # here without also sorting out release signing (see docs/mobile-deployment.md).
2016name : Release builds
2117
2218on :
4642 timeout-minutes : 5
4743 steps :
4844 - name : Checkout
49- uses : actions/checkout@v4
45+ uses : actions/checkout@v5
5046
5147 - name : Tag matches pubspec version
5248 if : startsWith(github.ref, 'refs/tags/')
6864 timeout-minutes : 60
6965 steps :
7066 - name : Checkout
71- uses : actions/checkout@v4
67+ uses : actions/checkout@v5
7268
7369 - name : Setup Flutter
7470 uses : subosito/flutter-action@v2
@@ -113,7 +109,7 @@ jobs:
113109 timeout-minutes : 60
114110 steps :
115111 - name : Checkout
116- uses : actions/checkout@v4
112+ uses : actions/checkout@v5
117113
118114 - name : Setup Flutter
119115 uses : subosito/flutter-action@v2
@@ -149,14 +145,20 @@ jobs:
149145 # Development' found"). We therefore configure with Flutter and build with
150146 # xcodebuild, overriding the signing settings on the command line (command-line
151147 # settings outrank the ones baked into project.pbxproj).
148+ #
149+ # The app is ad-hoc signed: it runs, but it is not notarized, so Gatekeeper
150+ # shows "Apple cannot check it for malicious software" on first launch and the
151+ # user must right-click → Open (or clear the quarantine bit). Developer ID
152+ # signing + notarization is a follow-up — the AC_CERTIFICATE / APPLE_* secrets
153+ # for it already exist in this repo.
152154 macos :
153155 name : macOS arm64
154156 needs : version
155157 runs-on : macos-latest
156158 timeout-minutes : 90
157159 steps :
158160 - name : Checkout
159- uses : actions/checkout@v4
161+ uses : actions/checkout@v5
160162
161163 - name : Setup Flutter
162164 uses : subosito/flutter-action@v2
@@ -168,92 +170,25 @@ jobs:
168170 - name : Install build tools (libserialport)
169171 run : brew install automake libtool
170172
171- - name : Import Developer ID certificate
172- id : cert
173- env :
174- AC_CERTIFICATE : ${{ secrets.AC_CERTIFICATE }}
175- AC_CERTIFICATE_PASSWORD : ${{ secrets.AC_CERTIFICATE_PASSWORD }}
176- KEYCHAIN_PASSWORD : ${{ secrets.KEYCHAIN_PASSWORD }}
177- run : |
178- if [ -z "$AC_CERTIFICATE" ]; then
179- echo "::warning::AC_CERTIFICATE not set — building ad-hoc signed (Gatekeeper will warn users)."
180- echo "identity=-" >> "$GITHUB_OUTPUT"
181- exit 0
182- fi
183-
184- keychain="$RUNNER_TEMP/build.keychain-db"
185- security create-keychain -p "$KEYCHAIN_PASSWORD" "$keychain"
186- security set-keychain-settings -lut 21600 "$keychain"
187- security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$keychain"
188-
189- echo "$AC_CERTIFICATE" | base64 --decode > "$RUNNER_TEMP/cert.p12"
190- security import "$RUNNER_TEMP/cert.p12" -k "$keychain" \
191- -P "$AC_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
192- security set-key-partition-list -S apple-tool:,apple:,codesign: \
193- -s -k "$KEYCHAIN_PASSWORD" "$keychain" >/dev/null
194- # Put our keychain first in the search list so xcodebuild finds the key.
195- security list-keychains -d user -s "$keychain" $(security list-keychains -d user | tr -d '"')
196- rm -f "$RUNNER_TEMP/cert.p12"
197-
198- security find-identity -v -p codesigning "$keychain"
199- identity=$(security find-identity -v -p codesigning "$keychain" \
200- | grep 'Developer ID Application' | head -1 | sed -E 's/.*"(.*)"/\1/')
201- if [ -z "$identity" ]; then
202- echo "::warning::No 'Developer ID Application' identity in AC_CERTIFICATE —" \
203- "falling back to ad-hoc signing (no notarization)."
204- identity='-'
205- fi
206- echo "identity=$identity" >> "$GITHUB_OUTPUT"
207-
208173 - name : Flutter config & deps
209174 run : |
210175 flutter config --enable-macos-desktop
211176 flutter pub get
212177
213178 - name : Build macOS release
214- env :
215- APPLE_TEAM_ID : ${{ secrets.APPLE_TEAM_ID }}
216- IDENTITY : ${{ steps.cert.outputs.identity }}
217179 run : |
218180 # Generate the ephemeral xcconfig / plugin registrant without building.
219181 flutter build macos --release --config-only
220182
221- args=(
222- -workspace macos/Runner.xcworkspace
223- -scheme Runner
224- -configuration Release
225- -derivedDataPath "$RUNNER_TEMP/dd"
226- CODE_SIGN_STYLE=Manual
227- PROVISIONING_PROFILE_SPECIFIER=
228- )
229- if [ "$IDENTITY" = "-" ]; then
230- args+=(CODE_SIGN_IDENTITY=-) # ad-hoc: runs locally, Gatekeeper warns
231- else
232- args+=(
233- CODE_SIGN_IDENTITY="$IDENTITY"
234- DEVELOPMENT_TEAM="$APPLE_TEAM_ID"
235- ENABLE_HARDENED_RUNTIME=YES # required for notarization
236- OTHER_CODE_SIGN_FLAGS=--timestamp
237- )
238- fi
239- xcodebuild "${args[@]}" build
240-
241- - name : Notarize & staple
242- if : steps.cert.outputs.identity != '-'
243- env :
244- APPLE_ID : ${{ secrets.APPLE_ID }}
245- APPLE_PASSWORD : ${{ secrets.APPLE_PASSWORD }}
246- APPLE_TEAM_ID : ${{ secrets.APPLE_TEAM_ID }}
247- run : |
248- app="$RUNNER_TEMP/dd/Build/Products/Release/OpenView.app"
249- ditto -c -k --sequesterRsrc --keepParent "$app" "$RUNNER_TEMP/notarize.zip"
250- xcrun notarytool submit "$RUNNER_TEMP/notarize.zip" \
251- --apple-id "$APPLE_ID" \
252- --password "$APPLE_PASSWORD" \
253- --team-id "$APPLE_TEAM_ID" \
254- --wait
255- xcrun stapler staple "$app"
256- spctl --assess --type execute --verbose "$app"
183+ xcodebuild \
184+ -workspace macos/Runner.xcworkspace \
185+ -scheme Runner \
186+ -configuration Release \
187+ -derivedDataPath "$RUNNER_TEMP/dd" \
188+ CODE_SIGN_STYLE=Manual \
189+ CODE_SIGN_IDENTITY=- \
190+ PROVISIONING_PROFILE_SPECIFIER= \
191+ build
257192
258193 - name : Package
259194 run : |
@@ -263,9 +198,9 @@ jobs:
263198 find "$RUNNER_TEMP/dd/Build/Products" -maxdepth 3 -name '*.app' || true
264199 exit 1
265200 fi
266- # ditto (not zip) preserves app-bundle metadata and the stapled ticket.
201+ codesign --verify --strict --verbose=2 "$app"
202+ # ditto (not zip) preserves app-bundle metadata and symlinks.
267203 ditto -c -k --sequesterRsrc --keepParent "$app" OpenView-macos-arm64.zip
268- codesign --verify --deep --strict --verbose=2 "$app" || true
269204
270205 - name : Upload artifact
271206 uses : actions/upload-artifact@v4
@@ -274,83 +209,10 @@ jobs:
274209 path : OpenView-macos-arm64.zip
275210 if-no-files-found : error
276211
277- # ── Android APK ────────────────────────────────────────────────────────
278- android :
279- name : Android APK
280- needs : version
281- runs-on : ubuntu-latest
282- timeout-minutes : 60
283- steps :
284- - name : Checkout
285- uses : actions/checkout@v4
286-
287- - name : Setup Java
288- uses : actions/setup-java@v4
289- with :
290- distribution : temurin
291- java-version : ' 17'
292- cache : gradle
293-
294- - name : Setup Flutter
295- uses : subosito/flutter-action@v2
296- with :
297- flutter-version : ${{ env.FLUTTER_VERSION }}
298- channel : stable
299- cache : true
300-
301- - name : Flutter deps
302- run : flutter pub get
303-
304- # Writes android/key.properties, which build.gradle.kts picks up. A tag
305- # build without a keystore is a hard error — shipping a debug-signed APK on
306- # a public release is worse than shipping no APK (it can never be upgraded
307- # in place by a properly signed build).
308- - name : Prepare release signing
309- env :
310- KEYSTORE_BASE64 : ${{ secrets.KEYSTORE_BASE64 }}
311- KEY_ALIAS : ${{ secrets.KEY_ALIAS }}
312- KEY_PASSWORD : ${{ secrets.KEY_PASSWORD }}
313- STORE_PASSWORD : ${{ secrets.STORE_PASSWORD }}
314- run : |
315- if [ -z "$KEYSTORE_BASE64" ]; then
316- if [ "${GITHUB_REF_TYPE}" = "tag" ]; then
317- echo "::error::KEYSTORE_BASE64 is not set. A tagged release must ship a" \
318- "release-signed APK. Add KEYSTORE_BASE64, KEY_ALIAS, KEY_PASSWORD and" \
319- "STORE_PASSWORD as repository secrets, then re-run."
320- exit 1
321- fi
322- echo "::warning::No keystore secrets — this APK will be debug-signed (dev build only)."
323- exit 0
324- fi
325- echo "$KEYSTORE_BASE64" | base64 --decode > android/release-keystore.jks
326- cat > android/key.properties <<EOF
327- storeFile=release-keystore.jks
328- storePassword=$STORE_PASSWORD
329- keyAlias=$KEY_ALIAS
330- keyPassword=$KEY_PASSWORD
331- EOF
332-
333- - name : Build APK
334- run : flutter build apk --release
335-
336- - name : Verify APK signature
337- run : |
338- cp build/app/outputs/flutter-apk/app-release.apk OpenView-android.apk
339- apksigner=$(find "$ANDROID_HOME/build-tools" -name apksigner | sort -r | head -1)
340- "$apksigner" verify --print-certs OpenView-android.apk
341- ls -la OpenView-android.apk
342-
343- - name : Upload artifact
344- uses : actions/upload-artifact@v4
345- with :
346- name : OpenView-android
347- path : OpenView-android.apk
348- if-no-files-found : error
349-
350212 # ── Publish GitHub Release (tags only) ─────────────────────────────────
351213 publish :
352214 name : Publish GitHub Release
353- needs : [linux, windows, macos, android ]
215+ needs : [linux, windows, macos]
354216 if : startsWith(github.ref, 'refs/tags/')
355217 runs-on : ubuntu-latest
356218 timeout-minutes : 15
@@ -364,7 +226,7 @@ jobs:
364226 - name : Checksums
365227 working-directory : release
366228 run : |
367- sha256sum ./*.zip ./*.apk | sed 's|\./||' | tee SHA256SUMS.txt
229+ sha256sum ./*.zip | sed 's|\./||' | tee SHA256SUMS.txt
368230
369231 - name : Create GitHub Release
370232 uses : softprops/action-gh-release@v2
@@ -375,7 +237,6 @@ jobs:
375237 release/OpenView-linux-x64.zip
376238 release/OpenView-windows-x64.zip
377239 release/OpenView-macos-arm64.zip
378- release/OpenView-android.apk
379240 release/SHA256SUMS.txt
380241 env :
381242 GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
0 commit comments