Skip to content

Commit 83e9518

Browse files
Timna BrownTimna Brown
authored andcommitted
fix(macos): repack dmg after signing app
1 parent d3ceb5e commit 83e9518

1 file changed

Lines changed: 150 additions & 65 deletions

File tree

.github/workflows/desktop-app.yml

Lines changed: 150 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)