Skip to content

build.gradle: re-sign Mac bundle ad-hoc after patchMacJpackage#7629

Open
Vest wants to merge 1 commit into
PCGen:masterfrom
Vest:mac-jpackage-resign
Open

build.gradle: re-sign Mac bundle ad-hoc after patchMacJpackage#7629
Vest wants to merge 1 commit into
PCGen:masterfrom
Vest:mac-jpackage-resign

Conversation

@Vest

@Vest Vest commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Problem

Every release of PcGen.app ships with a broken signature on macOS. Running spctl -a -vv on a freshly downloaded bundle reports:

PcGen.app: invalid resource directory (directory or signature have been modified)

This happens before quarantine is even considered. Users see "PcGen.app is damaged and can't be opened" on first launch and have to recover with codesign --force --deep --sign - or a ditto round-trip. The fix doesn't stick because the next download has the same problem.

Root cause

jpackage seals the bundle with an ad-hoc signature. The existing patchMacJpackage task then:

  1. Rewrites Contents/Info.plist to point CFBundleExecutable at MacDirLauncher.
  2. Copies MacDirLauncher into Contents/MacOS/.

Both modifications happen after the seal, invalidating it (Sealed Resources rules=13 no longer matches the on-disk contents). Re-running jpackage doesn't help — the patch runs after every build.

Fix

Re-sign the bundle ad-hoc at the end of patchMacJpackage so the seal matches the final on-disk layout. One codesign --force --deep --sign - in a doLast block.

Scope / what this does not do

  • This does not make Gatekeeper happy on first launch — that needs a real Developer ID + notarization, which requires a paid Apple Developer account and CI secrets, and is out of scope here.
  • It does mean a user can recover the bundle with just xattr -dr com.apple.quarantine PcGen.app (one command, no sudo, no codesign --force --deep on the user side). That's the minimum a non-notarized app can offer.

Verification

  • ./gradlew help --task patchMacJpackage parses cleanly.
  • Manual spctl -a -vv against a local build was not run (build is ~5-10 min); CI on macos-latest will exercise it.

After the change, on a fresh build:

spctl -a -vv build/jpackage/PcGen.app
# build/jpackage/PcGen.app: accepted    (when xattr is clean)

jpackage seals PcGen.app with an ad-hoc signature, but patchMacJpackage
then rewrites Info.plist and drops MacDirLauncher into Contents/MacOS,
invalidating the seal. The downloaded bundle ships with a broken
signature, so 'spctl -a -vv PcGen.app' reports 'invalid resource
directory (directory or signature have been modified)' even before
quarantine enters the picture.

Re-sealing ad-hoc at the end of patchMacJpackage makes the bundle
internally consistent. Users still hit Gatekeeper on first launch
because PCGen has no Developer ID, but stripping quarantine with
'xattr -dr com.apple.quarantine PcGen.app' is then sufficient — no
'codesign --force --deep' round-trip required on the user side.

Proper notarization needs an Apple Developer ID + notarytool secrets in
CI and is out of scope here.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant