@@ -152,7 +152,7 @@ jobs:
152152 exit 1
153153 fi
154154
155- - name : Sign macOS app and DMG (Developer ID)
155+ - name : Sign macOS app (Developer ID)
156156 if : runner.os == 'macOS'
157157 shell : bash
158158 env :
@@ -172,8 +172,84 @@ jobs:
172172 codesign --verify --deep --strict --verbose=2 "$app"
173173 done
174174 fi
175- if [ -d "$BUNDLE_ROOT/dmg" ]; then
176- for dmg in "$BUNDLE_ROOT/dmg"/*.dmg; do
175+
176+ - name : Ad-hoc codesign macOS bundle
177+ if : runner.os == 'macOS'
178+ shell : bash
179+ env :
180+ APPLE_SIGNING_CERT_B64 : ${{ secrets.APPLE_SIGNING_CERT_B64 }}
181+ APPLE_SIGNING_CERT_PASSWORD : ${{ secrets.APPLE_SIGNING_CERT_PASSWORD }}
182+ APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
183+ run : |
184+ if [ -n "${APPLE_SIGNING_CERT_B64:-}" ] && [ -n "${APPLE_SIGNING_CERT_PASSWORD:-}" ] && [ -n "${APPLE_SIGNING_IDENTITY:-}" ]; then
185+ echo "Developer ID signing is configured; skipping ad-hoc codesign fallback."
186+ exit 0
187+ fi
188+ # Apple Silicon and modern Intel macOS refuse to launch unsigned
189+ # apps with the cryptic "DevOpster.app is damaged" alert. An ad-hoc
190+ # signature (sign identity "-") satisfies the loader so the app
191+ # runs without users having to run `xattr -cr DevOpster.app`.
192+ BUNDLE_ROOT="src-tauri/target/${{ matrix.target }}/release/bundle"
193+ if [ -d "$BUNDLE_ROOT/macos" ]; then
194+ for app in "$BUNDLE_ROOT/macos"/*.app; do
195+ [ -d "$app" ] || continue
196+ echo "codesign $app"
197+ codesign --force --deep --options runtime --sign - "$app"
198+ codesign --verify --deep --strict --verbose=2 "$app" || true
199+ done
200+ fi
201+
202+ - name : Repack DMG with signed app
203+ if : runner.os == 'macOS'
204+ shell : bash
205+ run : |
206+ set -euo pipefail
207+ BUNDLE_ROOT="src-tauri/target/${{ matrix.target }}/release/bundle"
208+ APP_DIR="$BUNDLE_ROOT/macos"
209+ DMG_DIR="$BUNDLE_ROOT/dmg"
210+ if [ ! -d "$APP_DIR" ] || [ ! -d "$DMG_DIR" ]; then
211+ echo "No macOS app bundle or DMG directory to repack."
212+ exit 0
213+ fi
214+ APP_PATH=$(ls "$APP_DIR"/*.app 2>/dev/null | head -n 1 || true)
215+ if [ -z "$APP_PATH" ]; then
216+ echo "No .app bundle found to repack."
217+ exit 0
218+ fi
219+ APP_NAME=$(basename "$APP_PATH")
220+ for dmg in "$DMG_DIR"/*.dmg; do
221+ [ -f "$dmg" ] || continue
222+ echo "Repacking DMG with signed app: $dmg"
223+ RW_DMG="$(mktemp /tmp/devopster-dmg-rw-XXXXXX.dmg)"
224+ hdiutil convert "$dmg" -format UDWR -o "$RW_DMG"
225+ MOUNT=$(hdiutil attach -nobrowse "$RW_DMG" | awk '/Volumes/ {print $3; exit}')
226+ if [ -z "$MOUNT" ]; then
227+ echo "Failed to mount writable DMG."
228+ rm -f "$RW_DMG"
229+ exit 1
230+ fi
231+ rm -rf "$MOUNT/$APP_NAME"
232+ ditto "$APP_PATH" "$MOUNT/$APP_NAME"
233+ sync
234+ hdiutil detach "$MOUNT"
235+ hdiutil convert "$RW_DMG" -format UDZO -o "$dmg" -ov
236+ rm -f "$RW_DMG"
237+ done
238+
239+ - name : Sign macOS DMG (Developer ID)
240+ if : runner.os == 'macOS'
241+ shell : bash
242+ env :
243+ APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
244+ run : |
245+ set -euo pipefail
246+ if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
247+ echo "APPLE_SIGNING_IDENTITY is not set; skipping DMG signing."
248+ exit 0
249+ fi
250+ DMG_DIR="src-tauri/target/${{ matrix.target }}/release/bundle/dmg"
251+ if [ -d "$DMG_DIR" ]; then
252+ for dmg in "$DMG_DIR"/*.dmg; do
177253 [ -f "$dmg" ] || continue
178254 echo "codesign dmg: $dmg"
179255 codesign --force --timestamp --sign "$APPLE_SIGNING_IDENTITY" "$dmg"
@@ -208,39 +284,6 @@ jobs:
208284 done
209285 fi
210286
211- - name : Ad-hoc codesign macOS bundle
212- if : runner.os == 'macOS'
213- shell : bash
214- env :
215- APPLE_SIGNING_CERT_B64 : ${{ secrets.APPLE_SIGNING_CERT_B64 }}
216- APPLE_SIGNING_CERT_PASSWORD : ${{ secrets.APPLE_SIGNING_CERT_PASSWORD }}
217- APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
218- run : |
219- if [ -n "${APPLE_SIGNING_CERT_B64:-}" ] && [ -n "${APPLE_SIGNING_CERT_PASSWORD:-}" ] && [ -n "${APPLE_SIGNING_IDENTITY:-}" ]; then
220- echo "Developer ID signing is configured; skipping ad-hoc codesign fallback."
221- exit 0
222- fi
223- # Apple Silicon and modern Intel macOS refuse to launch unsigned
224- # apps with the cryptic "DevOpster.app is damaged" alert. An ad-hoc
225- # signature (sign identity "-") satisfies the loader so the app
226- # runs without users having to run `xattr -cr DevOpster.app`.
227- BUNDLE_ROOT="src-tauri/target/${{ matrix.target }}/release/bundle"
228- if [ -d "$BUNDLE_ROOT/macos" ]; then
229- for app in "$BUNDLE_ROOT/macos"/*.app; do
230- [ -d "$app" ] || continue
231- echo "codesign $app"
232- codesign --force --deep --options runtime --sign - "$app"
233- codesign --verify --deep --strict --verbose=2 "$app" || true
234- done
235- fi
236- if [ -d "$BUNDLE_ROOT/dmg" ]; then
237- for dmg in "$BUNDLE_ROOT/dmg"/*.dmg; do
238- [ -f "$dmg" ] || continue
239- echo "codesign $dmg"
240- codesign --force --sign - "$dmg" || true
241- done
242- fi
243-
244287 - name : Collect bundles
245288 if : always()
246289 shell : bash
@@ -360,7 +403,7 @@ jobs:
360403 exit 1
361404 fi
362405
363- - name : Sign macOS app and DMG (Developer ID)
406+ - name : Sign macOS app (Developer ID)
364407 shell : bash
365408 env :
366409 APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
@@ -378,8 +421,76 @@ jobs:
378421 codesign --verify --deep --strict --verbose=2 "$app"
379422 done
380423 fi
381- if [ -d "$BUNDLE_ROOT/dmg" ]; then
382- for dmg in "$BUNDLE_ROOT/dmg"/*.dmg; do
424+
425+ - name : Ad-hoc codesign macOS bundle
426+ shell : bash
427+ env :
428+ APPLE_SIGNING_CERT_B64 : ${{ secrets.APPLE_SIGNING_CERT_B64 }}
429+ APPLE_SIGNING_CERT_PASSWORD : ${{ secrets.APPLE_SIGNING_CERT_PASSWORD }}
430+ APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
431+ run : |
432+ if [ -n "${APPLE_SIGNING_CERT_B64:-}" ] && [ -n "${APPLE_SIGNING_CERT_PASSWORD:-}" ] && [ -n "${APPLE_SIGNING_IDENTITY:-}" ]; then
433+ echo "Developer ID signing is configured; skipping ad-hoc codesign fallback."
434+ exit 0
435+ fi
436+ BUNDLE_ROOT="src-tauri/target/x86_64-apple-darwin/release/bundle"
437+ if [ -d "$BUNDLE_ROOT/macos" ]; then
438+ for app in "$BUNDLE_ROOT/macos"/*.app; do
439+ [ -d "$app" ] || continue
440+ codesign --force --deep --options runtime --sign - "$app"
441+ codesign --verify --deep --strict --verbose=2 "$app" || true
442+ done
443+ fi
444+
445+ - name : Repack DMG with signed app
446+ shell : bash
447+ run : |
448+ set -euo pipefail
449+ BUNDLE_ROOT="src-tauri/target/x86_64-apple-darwin/release/bundle"
450+ APP_DIR="$BUNDLE_ROOT/macos"
451+ DMG_DIR="$BUNDLE_ROOT/dmg"
452+ if [ ! -d "$APP_DIR" ] || [ ! -d "$DMG_DIR" ]; then
453+ echo "No macOS app bundle or DMG directory to repack."
454+ exit 0
455+ fi
456+ APP_PATH=$(ls "$APP_DIR"/*.app 2>/dev/null | head -n 1 || true)
457+ if [ -z "$APP_PATH" ]; then
458+ echo "No .app bundle found to repack."
459+ exit 0
460+ fi
461+ APP_NAME=$(basename "$APP_PATH")
462+ for dmg in "$DMG_DIR"/*.dmg; do
463+ [ -f "$dmg" ] || continue
464+ echo "Repacking DMG with signed app: $dmg"
465+ RW_DMG="$(mktemp /tmp/devopster-dmg-rw-XXXXXX.dmg)"
466+ hdiutil convert "$dmg" -format UDWR -o "$RW_DMG"
467+ MOUNT=$(hdiutil attach -nobrowse "$RW_DMG" | awk '/Volumes/ {print $3; exit}')
468+ if [ -z "$MOUNT" ]; then
469+ echo "Failed to mount writable DMG."
470+ rm -f "$RW_DMG"
471+ exit 1
472+ fi
473+ rm -rf "$MOUNT/$APP_NAME"
474+ ditto "$APP_PATH" "$MOUNT/$APP_NAME"
475+ sync
476+ hdiutil detach "$MOUNT"
477+ hdiutil convert "$RW_DMG" -format UDZO -o "$dmg" -ov
478+ rm -f "$RW_DMG"
479+ done
480+
481+ - name : Sign macOS DMG (Developer ID)
482+ shell : bash
483+ env :
484+ APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
485+ run : |
486+ set -euo pipefail
487+ if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
488+ echo "APPLE_SIGNING_IDENTITY is not set; skipping DMG signing."
489+ exit 0
490+ fi
491+ DMG_DIR="src-tauri/target/x86_64-apple-darwin/release/bundle/dmg"
492+ if [ -d "$DMG_DIR" ]; then
493+ for dmg in "$DMG_DIR"/*.dmg; do
383494 [ -f "$dmg" ] || continue
384495 codesign --force --timestamp --sign "$APPLE_SIGNING_IDENTITY" "$dmg"
385496 done
@@ -411,32 +522,6 @@ jobs:
411522 done
412523 fi
413524
414- - name : Ad-hoc codesign macOS bundle
415- shell : bash
416- env :
417- APPLE_SIGNING_CERT_B64 : ${{ secrets.APPLE_SIGNING_CERT_B64 }}
418- APPLE_SIGNING_CERT_PASSWORD : ${{ secrets.APPLE_SIGNING_CERT_PASSWORD }}
419- APPLE_SIGNING_IDENTITY : ${{ secrets.APPLE_SIGNING_IDENTITY }}
420- run : |
421- if [ -n "${APPLE_SIGNING_CERT_B64:-}" ] && [ -n "${APPLE_SIGNING_CERT_PASSWORD:-}" ] && [ -n "${APPLE_SIGNING_IDENTITY:-}" ]; then
422- echo "Developer ID signing is configured; skipping ad-hoc codesign fallback."
423- exit 0
424- fi
425- BUNDLE_ROOT="src-tauri/target/x86_64-apple-darwin/release/bundle"
426- if [ -d "$BUNDLE_ROOT/macos" ]; then
427- for app in "$BUNDLE_ROOT/macos"/*.app; do
428- [ -d "$app" ] || continue
429- codesign --force --deep --options runtime --sign - "$app"
430- codesign --verify --deep --strict --verbose=2 "$app" || true
431- done
432- fi
433- if [ -d "$BUNDLE_ROOT/dmg" ]; then
434- for dmg in "$BUNDLE_ROOT/dmg"/*.dmg; do
435- [ -f "$dmg" ] || continue
436- codesign --force --sign - "$dmg" || true
437- done
438- fi
439-
440525 - name : Collect bundles
441526 if : always()
442527 shell : bash
0 commit comments