mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-09-11 11:45:27 +02:00
Sign and notarize macOS builds
jpackage cannot produce a distributable macOS bundle on its own. It ad-hoc signs the embedded runtime and then re-runs codesign on the same files without --force, which codesign rejects; and "--type dmg --app-image" re-signs the app it is handed, replacing a Developer ID signature with an ad-hoc one. So the build now creates an unsigned app-image, signs it from the inside out, and wraps it with hdiutil. Apple's notary service also unpacks JARs and checks the native libraries inside them, which sqlite-jdbc ships for both architectures. Those are signed before the bundle is sealed, since rewriting a JAR afterwards would invalidate the seal. A preflight check verifies Apple's two criteria locally, so a missed binary costs seconds rather than a round trip to the notary service. Two long-standing defects surfaced while testing and are fixed here: the bundle identifier defaulted to the main class's package name (kst4contest.view instead of de.x08.KST4Contest), and every release reported version 1.0 in Finder because --app-version was never passed. Neither affects existing users: the app keeps its settings in ~/.praktiKST, independent of the bundle ID. Both workflows call the same script the local Mac uses, so the two cannot drift apart. Signing needs a keychain that can answer a UI prompt, which a runner cannot, so ci-import-cert.sh creates a throwaway keychain whose password is generated per job and discarded with it. Notarization goes through an App Store Connect API key and needs no keychain at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WYcmHra3YndA1ahkHeNdJ2
This commit is contained in:
@@ -7,6 +7,7 @@ on:
|
||||
paths:
|
||||
- "src/**"
|
||||
- "packaging/icons/**"
|
||||
- "packaging/macos/**"
|
||||
- "pom.xml"
|
||||
- "mvnw"
|
||||
- "mvnw.cmd"
|
||||
@@ -634,34 +635,38 @@ jobs:
|
||||
- name: Ensure mvnw is executable
|
||||
run: chmod +x mvnw
|
||||
|
||||
- name: Build JAR and copy runtime dependencies
|
||||
run: |
|
||||
./mvnw -B -DskipTests package dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dist-libs
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
|
||||
- name: Build macOS DMG with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type dmg \
|
||||
--name KST4Contest \
|
||||
--icon packaging/icons/kst4contest.icns \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--dest dist
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: "13.0"
|
||||
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
|
||||
MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
|
||||
run: ./packaging/macos/ci-import-cert.sh
|
||||
|
||||
# Builds the jar, signs the app bundle and every native library inside it,
|
||||
# wraps it into a DMG and has Apple notarize the result. Same script the
|
||||
# local Mac uses, so the two cannot drift apart.
|
||||
- name: Build signed and notarized DMG
|
||||
env:
|
||||
MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }}
|
||||
NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
|
||||
NOTARY_ISSUER: ${{ secrets.MACOS_NOTARY_ISSUER }}
|
||||
run: |
|
||||
printf '%s' "$MACOS_NOTARY_KEY" | base64 --decode > "$RUNNER_TEMP/notary.p8"
|
||||
export NOTARY_KEY="$RUNNER_TEMP/notary.p8"
|
||||
./packaging/macos/build-signed-dmg.sh
|
||||
|
||||
- name: Remove signing credentials
|
||||
if: always()
|
||||
run: |
|
||||
rm -f "$RUNNER_TEMP/notary.p8"
|
||||
if [ -n "${SIGNING_KEYCHAIN:-}" ]; then
|
||||
security delete-keychain "$SIGNING_KEYCHAIN" || true
|
||||
fi
|
||||
|
||||
- name: Rename DMG artifact
|
||||
run: |
|
||||
DMG=$(ls dist/*.dmg | head -n 1)
|
||||
if [ -z "$DMG" ]; then
|
||||
echo "No DMG produced by jpackage" && exit 1
|
||||
echo "No DMG produced by the build" && exit 1
|
||||
fi
|
||||
mv "$DMG" "dist/${ASSET_BASENAME}-macos-${ARCH}.dmg"
|
||||
|
||||
|
||||
@@ -522,35 +522,39 @@ jobs:
|
||||
- name: Ensure mvnw is executable
|
||||
run: chmod +x mvnw
|
||||
|
||||
- name: Build JAR and copy runtime dependencies
|
||||
run: |
|
||||
./mvnw -B -DskipTests package dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dist-libs
|
||||
cp "$(ls -t target/praktiKST-*.jar | head -n 1)" target/dist-libs/app.jar
|
||||
|
||||
- name: Build macOS DMG with jpackage
|
||||
run: |
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
jpackage \
|
||||
--type dmg \
|
||||
--name KST4Contest \
|
||||
--icon packaging/icons/kst4contest.icns \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
--module-path target/dist-libs \
|
||||
--add-modules "$ADD_MODULES" \
|
||||
--dest dist
|
||||
|
||||
- name: Import signing certificate
|
||||
env:
|
||||
MACOSX_DEPLOYMENT_TARGET: "13.0"
|
||||
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
|
||||
MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
|
||||
run: ./packaging/macos/ci-import-cert.sh
|
||||
|
||||
# Builds the jar, signs the app bundle and every native library inside it,
|
||||
# wraps it into a DMG and has Apple notarize the result. Same script the
|
||||
# local Mac uses, so the two cannot drift apart.
|
||||
- name: Build signed and notarized DMG
|
||||
env:
|
||||
MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }}
|
||||
NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
|
||||
NOTARY_ISSUER: ${{ secrets.MACOS_NOTARY_ISSUER }}
|
||||
run: |
|
||||
printf '%s' "$MACOS_NOTARY_KEY" | base64 --decode > "$RUNNER_TEMP/notary.p8"
|
||||
export NOTARY_KEY="$RUNNER_TEMP/notary.p8"
|
||||
./packaging/macos/build-signed-dmg.sh
|
||||
|
||||
- name: Remove signing credentials
|
||||
if: always()
|
||||
run: |
|
||||
rm -f "$RUNNER_TEMP/notary.p8"
|
||||
if [ -n "${SIGNING_KEYCHAIN:-}" ]; then
|
||||
security delete-keychain "$SIGNING_KEYCHAIN" || true
|
||||
fi
|
||||
|
||||
- name: Rename DMG artifact
|
||||
run: |
|
||||
ARCH=$(uname -m)
|
||||
DMG=$(ls dist/*.dmg | head -n 1)
|
||||
if [ -z "$DMG" ]; then
|
||||
echo "No DMG produced by jpackage" && exit 1
|
||||
echo "No DMG produced by the build" && exit 1
|
||||
fi
|
||||
mv "$DMG" "dist/KST4Contest-${{ github.ref_name }}-macos-${ARCH}.dmg"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user