mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-14 14:26:46 -04:00
macOS: build the DMG with hdiutil create so the app passes codesign --strict
hdiutil makehybrid -hfs put a com.apple.FinderInfo on every file in the image, so the signed app inside the DMG (and any ditto copy of it) failed codesign --verify --deep --strict. Build the image with hdiutil create -srcfolder (retried, since create can hit "Resource busy" on CI), clear build-time xattrs before signing, and verify the app inside the finished DMG and a ditto copy of it with --strict. Ported from storytold/pdfcraft#823 and storytold/lightcraft#959. Fixes #176 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
240aa848a0
commit
27d934e726
2 files changed
+50
-9
No files matched your search
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
What Finder shows when the DMG opens: a 660 × 400 pt background with the app icon and the
|
What Finder shows when the DMG opens: a 660 × 400 pt background with the app icon and the
|
||||||
`Applications` link side by side. `package.sh` copies these files into the image; nothing here is
|
`Applications` link side by side. `package.sh` copies these files into the image; nothing here is
|
||||||
generated at build time, so the DMG still builds with `hdiutil makehybrid` (no mounted device, no
|
generated at build time, so the DMG builds with a plain `hdiutil create -srcfolder` (no Finder
|
||||||
Finder scripting on CI, nothing extra installed in the signing job).
|
scripting on CI, nothing extra installed in the signing job).
|
||||||
|
|
||||||
| File | What |
|
| File | What |
|
||||||
|---|---|
|
|---|---|
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ sed -e "s/@VERSION@/$VERSION/g" -e "s/@SHORT_VERSION@/$SHORT_VERSION/g" \
|
|||||||
plutil -lint "$APP/Contents/Info.plist"
|
plutil -lint "$APP/Contents/Info.plist"
|
||||||
printf 'APPL????' >"$APP/Contents/PkgInfo"
|
printf 'APPL????' >"$APP/Contents/PkgInfo"
|
||||||
|
|
||||||
|
# Drop extended attributes picked up during the build (quarantine, FinderInfo) before signing:
|
||||||
|
# `codesign --verify --strict` rejects them, and nothing after signing may touch the bundle.
|
||||||
|
xattr -cr "$APP"
|
||||||
|
|
||||||
# Sign inside-out: nested code first, then the bundle itself (no --deep on the final signature).
|
# Sign inside-out: nested code first, then the bundle itself (no --deep on the final signature).
|
||||||
# Today the only nested code is the main executable; frameworks/helpers would be signed here too.
|
# Today the only nested code is the main executable; frameworks/helpers would be signed here too.
|
||||||
sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP/Contents/MacOS/SoundCraft"
|
sign --options runtime --entitlements "$HERE/entitlements.plist" "$APP/Contents/MacOS/SoundCraft"
|
||||||
@@ -133,15 +137,52 @@ ln -s /Applications "$STAGE/Applications"
|
|||||||
mkdir -p "$STAGE/.background"
|
mkdir -p "$STAGE/.background"
|
||||||
cp "$HERE/dmg/background.tiff" "$STAGE/.background/background.tiff"
|
cp "$HERE/dmg/background.tiff" "$STAGE/.background/background.tiff"
|
||||||
cp "$HERE/dmg/dmg-layout.DS_Store" "$STAGE/.DS_Store"
|
cp "$HERE/dmg/dmg-layout.DS_Store" "$STAGE/.DS_Store"
|
||||||
rm -f "$DMG" "$WORK/raw.dmg"
|
rm -f "$DMG"
|
||||||
# makehybrid + convert builds the image without attaching a device, unlike `create -srcfolder`,
|
# `hdiutil create -srcfolder` writes the files as they are. `makehybrid -hfs` gave every file a
|
||||||
# which is flaky on CI runners ("Resource busy") and hangs in sandboxed sessions.
|
# com.apple.FinderInfo, which `codesign --verify --strict` rejects as "Finder information, or
|
||||||
# The volume name has no version: .DS_Store finds the background through an alias that includes it.
|
# similar detritus" on the app in the image and on a copy installed from it (#176). `create`
|
||||||
hdiutil makehybrid -hfs -hfs-volume-name "SoundCraft" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE"
|
# attaches a device while it copies, which fails now and then on CI runners ("Resource busy"), so
|
||||||
hdiutil convert "$WORK/raw.dmg" -format UDZO -imagekey zlib-level=9 -o "$DMG"
|
# it gets a few tries. The volume name has no version: .DS_Store finds the background through an
|
||||||
rm -f "$WORK/raw.dmg"
|
# alias that includes it.
|
||||||
|
# Usage: hdiutil_retry <what> <hdiutil args…>; tries five times with growing pauses.
|
||||||
|
hdiutil_retry() {
|
||||||
|
local what="$1" attempt
|
||||||
|
shift
|
||||||
|
for attempt in 1 2 3 4 5; do
|
||||||
|
if hdiutil "$@"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
[ "$attempt" = 5 ] && { echo "hdiutil $what failed 5 times" >&2; return 1; }
|
||||||
|
warn "hdiutil $what failed (attempt $attempt of 5); retrying in $((attempt * 10))s"
|
||||||
|
sleep $((attempt * 10))
|
||||||
|
done
|
||||||
|
}
|
||||||
|
hdiutil_retry create create -srcfolder "$STAGE" -volname "SoundCraft" -fs HFS+ -format UDZO -imagekey zlib-level=9 -ov "$DMG"
|
||||||
sign "$DMG"
|
sign "$DMG"
|
||||||
codesign --verify --strict --verbose=2 "$DMG"
|
codesign --verify --strict --verbose=2 "$DMG"
|
||||||
|
# The app users get must still pass --strict: inside the finished image and after a ditto copy out
|
||||||
|
# of it, so a valid container signature can't hide a damaged app (or a makehybrid-style regression).
|
||||||
|
MOUNT="$WORK/dmg-check"
|
||||||
|
COPY="$WORK/dmg-copy"
|
||||||
|
rm -rf "$MOUNT" "$COPY"
|
||||||
|
mkdir -p "$MOUNT" "$COPY"
|
||||||
|
hdiutil_retry attach attach -nobrowse -readonly -noautoopen -mountpoint "$MOUNT" "$DMG" >/dev/null
|
||||||
|
dmg_ok=1
|
||||||
|
codesign --verify --strict --deep --verbose=2 "$MOUNT/SoundCraft.app" || dmg_ok=0
|
||||||
|
if [ "$dmg_ok" = 1 ]; then
|
||||||
|
{ ditto "$MOUNT/SoundCraft.app" "$COPY/SoundCraft.app" &&
|
||||||
|
codesign --verify --strict --deep --verbose=2 "$COPY/SoundCraft.app"; } || dmg_ok=0
|
||||||
|
fi
|
||||||
|
if [ "$dmg_ok" = 1 ] && [ "$NOTARIZE" = 1 ]; then
|
||||||
|
spctl --assess --type execute -vvv "$COPY/SoundCraft.app" || dmg_ok=0
|
||||||
|
fi
|
||||||
|
[ "$dmg_ok" = 1 ] || xattr -lr "$MOUNT/SoundCraft.app" >&2 || true
|
||||||
|
hdiutil_retry detach detach "$MOUNT" >/dev/null || dmg_ok=0
|
||||||
|
rm -rf "$COPY"
|
||||||
|
if [ "$dmg_ok" != 1 ]; then
|
||||||
|
echo "error: SoundCraft.app in $(basename "$DMG") fails strict verification" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if [ "$NOTARIZE" = 1 ]; then
|
if [ "$NOTARIZE" = 1 ]; then
|
||||||
notarize "$DMG"
|
notarize "$DMG"
|
||||||
xcrun stapler staple "$DMG"
|
xcrun stapler staple "$DMG"
|
||||||
|
|||||||
Reference in new issue
Block a user