Files
wordcraft/packaging/macos/dmg/README.md
T
Valentin KleinandClaude Opus 5.5 f822dcb23c macOS packaging: strip extended attributes before signing and verify the DMG's app strictly (#525) (#527)
hdiutil makehybrid -hfs gave every file and folder in the image a
com.apple.FinderInfo, so WordCraft.app failed codesign --verify --deep
--strict inside the released DMG and after copying it out with ditto.

- Build the DMG with hdiutil create -srcfolder -fs HFS+ -format UDZO
  (retried: attaching a device is flaky on CI runners).
- Clear extended attributes on the bundle before signing.
- After signing the DMG, mount it read-only and strictly verify the app
  inside it and a ditto copy of it (plus spctl when notarizing), so the
  release job fails if this regresses.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 16:56:10 -04:00

3.2 KiB
Raw Blame History

macOS DMG window

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 builds with a plain hdiutil create -srcfolder (no Finder scripting on CI, nothing extra installed in the signing job).

Nothing in this step may touch WordCraft.app: codesign --verify --deep --strict rejects any com.apple.FinderInfo or resource fork on the bundle. hdiutil makehybrid -hfs, which built the image before, put a FinderInfo on every file in it, so the released app failed that check (#525). package.sh clears extended attributes before signing and, after building the DMG, mounts it read-only and checks the app inside it, and a ditto copy of it, with --strict.

File What
background.svg Source of the background: the app icon (assets/app-icon/wordcraft.svg, linked, not copied) cropped as a cover on the WordCraft colour field (#3b5bdb), Ink and Paper. Its text (Inter, JetBrains Mono) is outlined, so rendering it needs no fonts. No paper grain: noise doesn't compress, and this keeps background.tiff small.
background.tiff The background at 1x (660 × 400 px, 72 dpi) and 2x (1320 × 800 px, 144 dpi) in one HiDPI TIFF (16-colour palette, Deflate, sRGB). Goes to .background/background.tiff.
dmg-layout.DS_Store Finder's view settings for the volume: window size, icon size 128, WordCraft.app at (326, 205), Applications at (574, 205), and the background. Goes to .DS_Store in the image; named so it isn't mistaken for (or ignored like) a Finder-generated .DS_Store.
generate.py Writes background.tiff and dmg-layout.DS_Store from the SVG and the layout above.

The volume name has no version

The mounted volume is called WordCraft, not WordCraft <version>. The layout points at the background through an alias that includes the volume name, and Finder resolves it by that name: with a versioned name the window keeps its size and icon positions but shows no background (tested). The DMG file name (wordcraft-<version>-macos-<arch>.dmg) still carries the version.

Rules

  • Finder draws the icon labels in black in light and dark mode when a window has a background, so the area under both icons stays light (Paper).
  • Nothing goes inside the icon boxes: artwork keeps 10 pt clear of each 128 pt icon box and of the label strip under it.

Regenerate

Edit background.svg (or the layout constants in generate.py), then run, on any OS:

pip install 'pillow>=12' ds_store==1.3.3 mac_alias==2.2.3
python3 packaging/macos/dmg/generate.py   # needs resvg on PATH

Both outputs are byte-for-byte reproducible and carry nothing from the machine that ran it: the SVG renders without any fonts, and dmg-layout.DS_Store is written from scratch, its background alias holding only the volume name and /.background/background.tiff. If you add text to the SVG, outline it (usvg from resvg converts text to paths). The window is 660 × 432 with Finder's 32 pt title bar; the content area is 660 × 400.

This follows VectorCraft's packaging/macos/dmg/ (storytold/vectorcraft#493).