#1085: the DMG's app passes codesign --strict

`hdiutil makehybrid -hfs` gave every file in the image a
com.apple.FinderInfo, which `codesign --verify --strict` rejects as
"Finder information, or similar detritus" on the app in the DMG and on
copies installed from it, so compliance and MDM checks reported the
notarized app as damaged. As PdfCraft did (storytold/pdfcraft#823,
shipped in PdfCraft 0.6.0), the DMG is now made with
`hdiutil create -srcfolder -fs HFS+ -format UDZO`, retried when a CI
runner's device is busy, and the app mounted from the finished DMG must
pass `codesign --verify --strict --deep` before the release goes on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bflatastic
2026-10-11 11:24:36 +07:00
co-authored by Claude Opus 5.5
parent 61c333b8ed
commit 83ad194819
4 changed files with 37 additions and 12 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -2
View File
@@ -85,8 +85,9 @@ The rules are in craftrules `standards/fonts.md`, the build option in
(`entitlements.plist`) are deliberately empty.
- **Notarization:** the app is zipped and sent with `xcrun notarytool submit --wait`, then the
ticket is stapled and checked with `stapler validate` and `spctl`. The app goes on a DMG
(`hdiutil makehybrid` and `convert`, with an `Applications` link to drag onto), which is signed,
notarized and stapled too. Its Finder window (background, icon size and positions) comes from
(`hdiutil create -srcfolder`, retried when a CI runner's device is busy, with an `Applications` link
to drag onto), which is signed, notarized and stapled too; the app mounted from it must pass
`codesign --verify --strict --deep` (#1085). Its Finder window (background, icon size and positions) comes from
[`packaging/macos/dmg/`](../packaging/macos/dmg/README.md), and its volume is named `VectorCraft`
without the version, which the window's background needs; the DMG file name keeps the version.
- **CLI:** the universal `vectorcraft-cli` is signed the same way, zipped, and the zip is
+2 -2
View File
@@ -2,8 +2,8 @@
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
generated at build time, so the DMG still builds with `hdiutil makehybrid` (no mounted device, no
Finder scripting on CI).
generated at build time, so the DMG builds with a plain `hdiutil create -srcfolder` (no Finder
scripting on CI, nothing extra installed in the signing job).
| File | What |
|---|---|
+31 -7
View File
@@ -135,15 +135,39 @@ ln -s /Applications "$STAGE/Applications"
mkdir -p "$STAGE/.background"
cp "$HERE/dmg/background.tiff" "$STAGE/.background/background.tiff"
cp "$HERE/dmg/DS_Store" "$STAGE/.DS_Store"
rm -f "$DMG" "$WORK/raw.dmg"
# makehybrid + convert builds the image without attaching a device, unlike `create -srcfolder`,
# which is flaky on CI runners ("Resource busy") and hangs in sandboxed sessions.
# The volume name has no version: .DS_Store finds the background through an alias that includes it.
hdiutil makehybrid -hfs -hfs-volume-name "VectorCraft" -hfs-openfolder "$STAGE" -o "$WORK/raw.dmg" "$STAGE"
hdiutil convert "$WORK/raw.dmg" -format UDZO -imagekey zlib-level=9 -o "$DMG"
rm -f "$WORK/raw.dmg"
rm -f "$DMG"
# `hdiutil create -srcfolder` writes the files as they are. `makehybrid -hfs` gave every file a
# com.apple.FinderInfo, which `codesign --verify --strict` rejects as "Finder information, or
# similar detritus" on the app in the image and on a copy installed from it (#1085, as PdfCraft's
# storytold/pdfcraft#823). `create` attaches a device while it copies, which fails now and then on
# CI runners ("Resource busy"), so it gets a few tries. The volume name has no version: .DS_Store
# finds the background through an 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; }
echo "hdiutil $what failed (attempt $attempt of 5); retrying in $((attempt * 10))s" >&2
sleep $((attempt * 10))
done
}
hdiutil_retry create create -srcfolder "$STAGE" -volname "VectorCraft" -fs HFS+ -format UDZO -imagekey zlib-level=9 -ov "$DMG"
sign "$DMG"
codesign --verify --strict --verbose=2 "$DMG"
# The app inside the image must still pass --strict, so a makehybrid-style regression can't ship.
MOUNT="$WORK/dmg-check"
rm -rf "$MOUNT"
mkdir -p "$MOUNT"
hdiutil_retry attach attach -nobrowse -readonly -mountpoint "$MOUNT" "$DMG" >/dev/null
if ! codesign --verify --strict --deep --verbose=2 "$MOUNT/VectorCraft.app"; then
hdiutil_retry detach detach "$MOUNT" >/dev/null || true
exit 1
fi
hdiutil_retry detach detach "$MOUNT" >/dev/null
if [ "$NOTARIZE" = 1 ]; then
notarize "$DMG"
xcrun stapler staple "$DMG"