Macos signing (#80)

* 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>

* Sign bundle contents serially

Signing the app image's Mach-O files with "xargs -P 8" passed locally but
failed on a runner: codesign reported "replacing existing signature" and then
"No such file or directory" for that same path. The two libjli.dylib copies are
separate inodes, so this is not hard links being signed twice -- concurrent
codesign runs over one bundle are simply not reliable. Serially costs about a
minute, since each call waits on Apple's timestamp server.

Also stop the matrix from cancelling the other architecture on a failure; that
throws away half the diagnostic information from a failed run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Document macOS signing from 1.42

The installation guides described the right-click workaround as the normal
first launch. That stays, but as the path for 1.41.1 and older; from 1.42 a
double-click works. Both guides also show how to verify a download with spctl,
so the claim is checkable rather than something to take on faith.

The per-channel download notes distinguish where the channels actually stand:
Nightly is built from main and is signed as of now, while Stable still points
at 1.41.1, so those notes name the version instead of claiming it outright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 16:48:31 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent 399e5f34b7
commit af30c17a0d
14 changed files with 462 additions and 57 deletions
+4
View File
@@ -123,6 +123,10 @@ v1.42 führt mehrere bisher getrennte Auswertungen zusammen. Bandinformationen,
- Nightly-Pakete werden automatisiert aus dem aktuellen `main`-Branch gebaut. Stable- und Beta-Releases verwenden reproduzierbare Paketnamen für die unterstützten Plattformen.
- **Signierte und notarisierte macOS-Pakete:** Die DMG-Dateien für Apple Silicon und Intel sind mit einer Apple Developer ID signiert und von Apple notarisiert; das Notarisierungsticket ist in der DMG hinterlegt. Der erste Start funktioniert damit per Doppelklick, ohne den bisherigen Umweg über **Öffnen** im Kontextmenü, und die Prüfung gelingt auch ohne Internetverbindung. Betroffen sind Nightly-, Beta- und Stable-Pakete gleichermaßen. Die Windows-Pakete sind weiterhin nicht signiert.
- **Korrekte Bundle-Kennung und Version unter macOS:** Die Anwendung meldet sich jetzt als `de.x08.KST4Contest` statt als `kst4contest.view` und trägt die tatsächliche Versionsnummer im Bundle. Bisher wies jedes Release im Finder unter **Informationen** die Version `1.0` aus. Bestehende Einstellungen sind davon nicht betroffen, da KST4Contest seine Daten in `~/.praktiKST/` ablegt und nicht an der Bundle-Kennung festmacht.
### Bekannte Grenzen
- Die aktive Geländedatenquelle verwendet Open-Meteo mit Copernicus-GLO-90-Daten und höchstens 100 Höhenpunkten pro Strecke.
+16 -2
View File
@@ -267,7 +267,19 @@ Für Apple-Silicon-Macs wird das Paket mit `arm64` benötigt. Für Intel-Macs is
3. Ziehe `KST4Contest.app` in den Ordner **Programme**.
4. Starte KST4Contest aus dem Programme-Ordner oder über das Launchpad.
Die Anwendung ist derzeit nicht von Apple notarisiert. macOS kann den ersten Start deshalb blockieren.
Ab Version 1.42 sind die macOS-Pakete mit einer Apple Developer ID signiert und von Apple notarisiert. Der erste Start funktioniert damit per Doppelklick, ohne Umweg über das Kontextmenü und ohne Sicherheitsabfrage. Das Notarisierungsticket liegt in der DMG-Datei selbst, sodass die Prüfung auch ohne Internetverbindung gelingt.
Wer nachsehen möchte, ob ein heruntergeladenes Paket wirklich signiert ist, kann das im Terminal prüfen:
```bash
spctl --assess --type open --context context:primary-signature -v KST4Contest-v<Version>-macos-arm64.dmg
```
Erwartet wird `accepted` zusammen mit `source=Notarized Developer ID`.
### Versionen bis einschließlich 1.41.1
Ältere Pakete sind nicht notarisiert. macOS blockiert den ersten Start deshalb.
Falls die Anwendung aus dem offiziellen GitHub Release stammt:
@@ -408,7 +420,9 @@ Starte die Datei anschließend aus einem Terminal. Fehlermeldungen sind dort mei
### macOS blockiert die Anwendung
Verwende die unter [Installation unter macOS](#installation-unter-macos) beschriebene Funktion **Öffnen** im Kontextmenü. Prüfe vorher, ob die DMG-Datei aus dem offiziellen GitHub Release stammt.
Ab Version 1.42 sollte das nicht mehr vorkommen, da die Pakete signiert und notarisiert sind. Tritt die Blockade trotzdem auf, ist die DMG-Datei meist unvollständig heruntergeladen oder nachträglich verändert worden. Lade sie in dem Fall erneut aus dem offiziellen GitHub Release.
Bei älteren Versionen ist die Blockade zu erwarten. Verwende dort die unter [Installation unter macOS](#installation-unter-macos) beschriebene Funktion **Öffnen** im Kontextmenü.
### Das Problem bleibt bestehen
+4
View File
@@ -121,6 +121,10 @@ v1.42 brings several previously separate calculations together. Band information
- Nightly packages are built automatically from the current `main` branch. Stable and Beta releases use predictable asset names for the supported platforms.
- **Signed and notarized macOS packages:** The DMG files for Apple Silicon and Intel are signed with an Apple Developer ID and notarized by Apple, with the notarization ticket stapled into the DMG. The first launch now works by double-clicking, without the previous detour through **Open** in the context menu, and the check also succeeds without an internet connection. This applies to Nightly, Beta and Stable packages alike. The Windows packages remain unsigned.
- **Correct bundle identifier and version on macOS:** The application now identifies itself as `de.x08.KST4Contest` rather than `kst4contest.view`, and carries its actual version number in the bundle. Previously every release reported version `1.0` in Finder's **Get Info** panel. Existing settings are unaffected, because KST4Contest stores its data in `~/.praktiKST/` rather than keying it to the bundle identifier.
### Known limitations
- The active terrain provider uses Open-Meteo with Copernicus GLO-90 data and no more than 100 elevation samples per path.
+16 -2
View File
@@ -267,7 +267,19 @@ Apple Silicon Macs require the package marked `arm64`. Intel Macs require the pa
3. Drag `KST4Contest.app` into the **Applications** folder.
4. Start KST4Contest from the Applications folder or Launchpad.
The application is not currently notarized by Apple. macOS may therefore block the first launch.
From version 1.42 onwards the macOS packages are signed with an Apple Developer ID and notarized by Apple. The first launch therefore works by double-clicking, without going through the context menu and without a security prompt. The notarization ticket is stapled into the DMG file itself, so the check also succeeds without an internet connection.
To confirm that a downloaded package really is signed, check it in a terminal:
```bash
spctl --assess --type open --context context:primary-signature -v KST4Contest-v<version>-macos-arm64.dmg
```
The expected result is `accepted` together with `source=Notarized Developer ID`.
### Versions up to and including 1.41.1
Older packages are not notarized, so macOS blocks the first launch.
If the application came from the official GitHub Release:
@@ -408,7 +420,9 @@ Then start the file from a terminal. Error messages shown there are usually more
### macOS blocks the application
Use the **Open** function described under [Installing on macOS](#installing-on-macos). Before doing so, verify that the DMG file came from the official GitHub Release.
From version 1.42 onwards this should no longer happen, because the packages are signed and notarized. If it does occur, the DMG file was most likely downloaded incompletely or modified afterwards; download it again from the official GitHub Release.
On older versions the block is expected. Use the **Open** function described under [Installing on macOS](#installing-on-macos).
### The problem remains