Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af30c17a0d | ||
|
|
399e5f34b7
|
||
|
|
2bc7554a52
|
@@ -94,6 +94,10 @@ jobs:
|
||||
sed -i "s/^pkgver=.*/pkgver=${PKGVER}/" packaging/aur/kst4contest/PKGBUILD
|
||||
sed -i "s/^sha256sums=.*/sha256sums=('${SHA_SRC}')/" packaging/aur/kst4contest/PKGBUILD
|
||||
|
||||
# A new pkgver supersedes any rebuild-only pkgrel bumps made in between.
|
||||
sed -i "s/^pkgrel=.*/pkgrel=1/" packaging/aur/kst4contest-bin/PKGBUILD
|
||||
sed -i "s/^pkgrel=.*/pkgrel=1/" packaging/aur/kst4contest/PKGBUILD
|
||||
|
||||
# kst4contest-git: Basis aus pom.xml, Suffix aus git
|
||||
BASE_VER=$(grep -m1 '<version>' pom.xml \
|
||||
| sed 's/.*<version>\(.*\)<\/version>.*/\1/' | sed 's/[-.]nightly//')
|
||||
|
||||
@@ -7,6 +7,7 @@ on:
|
||||
paths:
|
||||
- "src/**"
|
||||
- "packaging/icons/**"
|
||||
- "packaging/macos/**"
|
||||
- "pom.xml"
|
||||
- "mvnw"
|
||||
- "mvnw.cmd"
|
||||
@@ -126,7 +127,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -213,7 +214,7 @@ jobs:
|
||||
jpackage \
|
||||
--type deb \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -274,7 +275,7 @@ jobs:
|
||||
jpackage \
|
||||
--type rpm \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -337,7 +338,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -457,7 +458,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -608,6 +609,7 @@ jobs:
|
||||
name: Build macOS DMG (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, macos-15-intel]
|
||||
|
||||
@@ -634,34 +636,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"
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -184,7 +184,7 @@ jobs:
|
||||
jpackage \
|
||||
--type deb \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -238,7 +238,7 @@ jobs:
|
||||
jpackage \
|
||||
--type rpm \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -292,7 +292,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -403,7 +403,7 @@ jobs:
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon src/main/resources/icons/kst4contest.png \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
@@ -506,6 +506,7 @@ jobs:
|
||||
name: Build macOS DMG (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, macos-15-intel]
|
||||
|
||||
@@ -522,35 +523,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"
|
||||
|
||||
|
||||
@@ -44,3 +44,6 @@ website/_site/
|
||||
|
||||
# Local secrets for act testing
|
||||
.secrets
|
||||
|
||||
# Apple notarization private keys - never commit these
|
||||
*.p8
|
||||
|
||||
|
After Width: | Height: | Size: 36 KiB |
@@ -32,9 +32,7 @@ Das Hauptfenster besteht aus mehreren Bereichen:
|
||||
|
||||
Die Statusleiste befindet sich am oberen Rand des Hauptfensters neben dem Menü.
|
||||
|
||||
<!-- TODO: Screenshot connection_status_indicator.png fehlt im Repository - wieder einkommentieren, sobald die Datei unter github_docs/ liegt.
|
||||

|
||||
-->
|
||||
|
||||
Der dauerhaft sichtbare `LINK`-Indikator zeigt den tatsächlichen Zustand der ON4KST-Verbindung:
|
||||
|
||||
@@ -349,9 +347,7 @@ Dabei werden:
|
||||
|
||||
Die Karte selbst bleibt im zuvor gewählten Ausschnitt. Die Funktion ist deshalb kein geografischer Reset auf den eigenen Standort.
|
||||
|
||||
<!-- TODO: Screenshot station_map_reset.png fehlt im Repository - wieder einkommentieren, sobald die Datei unter github_docs/ liegt.
|
||||

|
||||
-->
|
||||
|
||||
Wird anschließend wieder ein einzelner Marker gewählt, erscheinen Stationsauswahl und Analysebereich erneut.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 36 KiB |
@@ -37,6 +37,7 @@ build() {
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--icon packaging/icons/kst4contest.png \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pkgbase = kst4contest
|
||||
pkgdesc = ON4KST Chat Client for VHF/UHF contest operation
|
||||
pkgver = 1.41.1
|
||||
pkgrel = 1
|
||||
pkgrel = 2
|
||||
url = https://github.com/praktimarc/kst4contest
|
||||
arch = x86_64
|
||||
license = GPL-3.0-only
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Maintainer: Philipp Wagner <philipp@wagnersnetz.de>
|
||||
pkgname=kst4contest
|
||||
pkgver=1.41.1
|
||||
pkgrel=1
|
||||
pkgrel=2
|
||||
pkgdesc="ON4KST Chat Client for VHF/UHF contest operation"
|
||||
arch=('x86_64')
|
||||
url="https://github.com/praktimarc/kst4contest"
|
||||
@@ -34,9 +34,17 @@ build() {
|
||||
else
|
||||
ADD_MODULES="$(sed -n 's:.*<addmodule>\(.*\)</addmodule>.*:\1:p' pom.xml | paste -sd,)"
|
||||
fi
|
||||
# Same story for the packaging icon: without --icon jpackage silently ships
|
||||
# its own Duke placeholder, but tarballs older than v1.42.0 have no icon to
|
||||
# point at, so only pass the flag when the file is actually there.
|
||||
ICON_ARGS=()
|
||||
if [ -f packaging/icons/kst4contest.png ]; then
|
||||
ICON_ARGS=(--icon packaging/icons/kst4contest.png)
|
||||
fi
|
||||
jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
"${ICON_ARGS[@]}" \
|
||||
--input target/dist-libs \
|
||||
--main-jar app.jar \
|
||||
--main-class kst4contest.view.Kst4ContestApplication \
|
||||
|
||||
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180" width="180" height="180"><rect x="0" y="0" width="180" height="180" rx="40" fill="#5fd63a"></rect><g transform="translate(40,40) scale(1)">
|
||||
<path d="M20 34 h60 a12 12 0 0 1 12 12 v20 a12 12 0 0 1 -12 12 h-30 l-16 12 v-12 h-14 a12 12 0 0 1 -12 -12 v-20 a12 12 0 0 1 12 -12 z" fill="#0a110a"></path>
|
||||
<text x="50" y="65" text-anchor="middle" font-family="'Space Grotesk','Helvetica Neue',Arial,sans-serif" font-weight="700" font-size="24" letter-spacing="0.5" fill="#5fd63a">KST</text>
|
||||
<line x1="50" y1="34" x2="50" y2="17" stroke="#0a110a" stroke-width="6" stroke-linecap="round"></line>
|
||||
<circle cx="50" cy="13" r="4.5" fill="#0a110a"></circle>
|
||||
<path d="M58 6 a9 9 0 0 1 0 14" fill="none" stroke="#0a110a" stroke-width="4" stroke-linecap="round"></path>
|
||||
<path d="M64 1 a15 15 0 0 1 0 24" fill="none" stroke="#0a110a" stroke-width="4" stroke-linecap="round"></path>
|
||||
<path d="M42 6 a9 9 0 0 0 0 14" fill="none" stroke="#0a110a" stroke-width="4" stroke-linecap="round"></path>
|
||||
<path d="M36 1 a15 15 0 0 0 0 24" fill="none" stroke="#0a110a" stroke-width="4" stroke-linecap="round"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,268 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Local signed (and optionally notarized) macOS build.
|
||||
#
|
||||
# jpackage cannot sign the app itself: it ad-hoc signs the embedded runtime and
|
||||
# then re-runs codesign on the same files without --force, which codesign
|
||||
# rejects with "is already signed". So this builds an unsigned app-image, signs
|
||||
# it from the inside out ourselves, and only then wraps it into a DMG.
|
||||
#
|
||||
# Required:
|
||||
# SIGNING_IDENTITY The name part of the Developer ID Application certificate,
|
||||
# without the "Developer ID Application: " prefix. Example:
|
||||
# SIGNING_IDENTITY="Philipp Wagner (ABCDE12345)"
|
||||
# List available ones with:
|
||||
# security find-identity -v -p codesigning
|
||||
#
|
||||
# Optional:
|
||||
# Notarization, either as three separate values (what CI uses)...
|
||||
# NOTARY_KEY Path to the App Store Connect .p8 private key
|
||||
# NOTARY_KEY_ID The key's ID, also part of the .p8 filename
|
||||
# NOTARY_ISSUER The issuer UUID, shown above the key list in the portal
|
||||
# ...or as a keychain profile previously created with
|
||||
# NOTARY_PROFILE xcrun notarytool store-credentials <name>
|
||||
#
|
||||
# With neither, the build is signed but not notarized -- enough to test
|
||||
# locally, not enough to distribute.
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/../.."
|
||||
REPO_ROOT="$PWD"
|
||||
|
||||
BUNDLE_ID="de.x08.KST4Contest"
|
||||
ENTITLEMENTS="packaging/macos/kst4contest.entitlements"
|
||||
|
||||
if [ -z "${SIGNING_IDENTITY:-}" ]; then
|
||||
echo "SIGNING_IDENTITY is not set. Available signing identities:" >&2
|
||||
security find-identity -v -p codesigning >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
FULL_IDENTITY="Developer ID Application: $SIGNING_IDENTITY"
|
||||
|
||||
# notarytool takes either an API key triple or a stored keychain profile. The
|
||||
# triple needs no keychain at all, which is why CI uses it.
|
||||
NOTARY_ARGS=()
|
||||
if [ -n "${NOTARY_KEY:-}" ] && [ -n "${NOTARY_KEY_ID:-}" ] && [ -n "${NOTARY_ISSUER:-}" ]; then
|
||||
NOTARY_ARGS=(--key "$NOTARY_KEY" --key-id "$NOTARY_KEY_ID" --issuer "$NOTARY_ISSUER")
|
||||
elif [ -n "${NOTARY_PROFILE:-}" ]; then
|
||||
NOTARY_ARGS=(--keychain-profile "$NOTARY_PROFILE")
|
||||
fi
|
||||
|
||||
echo "==> Building JAR and collecting runtime dependencies"
|
||||
chmod +x mvnw
|
||||
./mvnw -B -DskipTests package \
|
||||
dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target/dist-libs
|
||||
JAR="$(ls -t target/praktiKST-*.jar | head -n 1)"
|
||||
cp "$JAR" target/dist-libs/app.jar
|
||||
|
||||
# jpackage only accepts a numeric major[.minor[.patch]] as the macOS bundle
|
||||
# version, so a Maven qualifier like "-nightly" has to be trimmed off.
|
||||
POM_VERSION="${JAR##*/praktiKST-}"
|
||||
POM_VERSION="${POM_VERSION%.jar}"
|
||||
APP_VERSION="$(printf '%s' "$POM_VERSION" | sed -e 's/[^0-9.].*$//' -e 's/\.*$//')"
|
||||
[ -n "$APP_VERSION" ] || { echo "Could not derive app version from $JAR" >&2; exit 1; }
|
||||
echo "==> Version: $POM_VERSION -> bundle version $APP_VERSION"
|
||||
|
||||
echo "==> Step 1/4: jpackage app-image (unsigned)"
|
||||
rm -rf dist
|
||||
mkdir -p dist
|
||||
ADD_MODULES="$(java packaging/AddModules.java)"
|
||||
|
||||
MACOSX_DEPLOYMENT_TARGET="13.0" jpackage \
|
||||
--type app-image \
|
||||
--name KST4Contest \
|
||||
--app-version "$APP_VERSION" \
|
||||
--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" \
|
||||
--mac-package-identifier "$BUNDLE_ID" \
|
||||
--mac-package-name KST4Contest \
|
||||
--dest dist/appimage
|
||||
|
||||
APP="dist/appimage/KST4Contest.app"
|
||||
[ -d "$APP" ] || { echo "jpackage produced no app image" >&2; exit 1; }
|
||||
|
||||
echo "==> Step 2/4: signing bundle contents (this takes a few minutes)"
|
||||
|
||||
# Apple's notary service unpacks JARs and checks the native libraries inside
|
||||
# them. sqlite-jdbc ships libsqlitejdbc.dylib for both architectures that way,
|
||||
# and an unsigned binary in there fails the whole submission. So sign those
|
||||
# first: the app bundle's seal covers Contents/app, and rewriting a JAR
|
||||
# afterwards would invalidate it.
|
||||
echo " scanning jars for native libraries"
|
||||
find "$APP/Contents/app" -name '*.jar' -type f | while read -r JARPATH; do
|
||||
# Only unpack jars that can plausibly hold a native library. Note the
|
||||
# plain grep: "grep -q" exits at the first match, which hands unzip a
|
||||
# SIGPIPE, and under "set -o pipefail" that failure becomes the pipeline's
|
||||
# status -- inverting this very test.
|
||||
if ! unzip -l "$JARPATH" | grep -E '\.(dylib|jnilib|so)$' >/dev/null; then
|
||||
continue
|
||||
fi
|
||||
|
||||
JARABS="$(cd "$(dirname "$JARPATH")" && pwd)/$(basename "$JARPATH")"
|
||||
JARTMP="$(mktemp -d)"
|
||||
unzip -q "$JARABS" -d "$JARTMP"
|
||||
|
||||
NATIVES="$(mktemp)"
|
||||
( cd "$JARTMP" && find . -type f \( -name '*.dylib' -o -name '*.jnilib' -o -name '*.so' \) \
|
||||
| while read -r n; do
|
||||
if [ "$(file --mime-type -b "$n")" = "application/x-mach-binary" ]; then
|
||||
printf '%s\n' "${n#./}"
|
||||
fi
|
||||
done ) > "$NATIVES"
|
||||
|
||||
if [ -s "$NATIVES" ]; then
|
||||
echo " $(basename "$JARPATH"): $(wc -l < "$NATIVES" | tr -d ' ') native lib(s)"
|
||||
( cd "$JARTMP" && xargs -I {} codesign --force --timestamp --options runtime \
|
||||
--sign "$FULL_IDENTITY" {} < "$NATIVES" )
|
||||
# Update in place rather than repacking, so the rest of the jar --
|
||||
# manifest, module descriptor, entry order -- stays byte for byte.
|
||||
( cd "$JARTMP" && xargs jar --update --file "$JARABS" < "$NATIVES" )
|
||||
fi
|
||||
|
||||
rm -rf "$JARTMP" "$NATIVES"
|
||||
done
|
||||
|
||||
# Every Mach-O file has to carry its own signature before the enclosing bundle
|
||||
# can be sealed, so collect them first. jpackage leaves them ad-hoc signed,
|
||||
# hence --force on every call.
|
||||
# file(1) pads its output into columns when given several arguments at once,
|
||||
# so ask it one file at a time with -b and get an unambiguous answer.
|
||||
MACHO_LIST="$(mktemp)"
|
||||
find "$APP" -type f -print0 | while IFS= read -r -d '' f; do
|
||||
case "$(file --mime-type -b "$f")" in
|
||||
application/x-mach-binary) printf '%s\n' "$f" ;;
|
||||
esac
|
||||
done > "$MACHO_LIST"
|
||||
|
||||
COUNT="$(wc -l < "$MACHO_LIST" | tr -d ' ')"
|
||||
echo " $COUNT Mach-O files to sign"
|
||||
|
||||
# Serially, deliberately. Running codesign concurrently over several files of
|
||||
# the same bundle fails intermittently -- a CI run died with "replacing existing
|
||||
# signature" immediately followed by "No such file or directory" for that same
|
||||
# path, while the identical script passed locally. Each call contacts Apple's
|
||||
# timestamp server, so this costs about a minute for a runtime this size.
|
||||
xargs -I {} codesign --force --timestamp --options runtime \
|
||||
--sign "$FULL_IDENTITY" {} < "$MACHO_LIST"
|
||||
rm -f "$MACHO_LIST"
|
||||
|
||||
# The embedded JDK is a bundle in its own right and must be sealed before the
|
||||
# app that contains it.
|
||||
echo " sealing embedded runtime"
|
||||
codesign --force --timestamp --options runtime \
|
||||
--sign "$FULL_IDENTITY" "$APP/Contents/runtime"
|
||||
|
||||
# Entitlements go on the outermost bundle: the hardened runtime derives the
|
||||
# process's entitlements from the main executable's signature.
|
||||
echo " sealing app bundle"
|
||||
codesign --force --timestamp --options runtime \
|
||||
--entitlements "$ENTITLEMENTS" \
|
||||
--sign "$FULL_IDENTITY" "$APP"
|
||||
|
||||
# Apple rejects the whole submission over a single unsigned native library, and
|
||||
# a round trip to the notary service costs minutes. Check its two criteria --
|
||||
# a Developer ID authority and a secure timestamp -- locally first.
|
||||
echo " preflight: verifying native libraries inside jars"
|
||||
PREFLIGHT_ERRORS="$(mktemp)"
|
||||
find "$APP/Contents/app" -name '*.jar' -type f | while read -r JARPATH; do
|
||||
if ! unzip -l "$JARPATH" | grep -E '\.(dylib|jnilib|so)$' >/dev/null; then
|
||||
continue
|
||||
fi
|
||||
CHECKTMP="$(mktemp -d)"
|
||||
unzip -q "$JARPATH" -d "$CHECKTMP"
|
||||
find "$CHECKTMP" -type f \( -name '*.dylib' -o -name '*.jnilib' -o -name '*.so' \) \
|
||||
| while read -r NATIVE; do
|
||||
[ "$(file --mime-type -b "$NATIVE")" = "application/x-mach-binary" ] || continue
|
||||
INFO="$(codesign -dv --verbose=2 "$NATIVE" 2>&1 || true)"
|
||||
LABEL="$(basename "$JARPATH")/${NATIVE#"$CHECKTMP"/}"
|
||||
printf '%s' "$INFO" | grep -q "Authority=Developer ID Application" \
|
||||
|| echo "$LABEL: not signed with a Developer ID certificate" >> "$PREFLIGHT_ERRORS"
|
||||
printf '%s' "$INFO" | grep -q "Timestamp=" \
|
||||
|| echo "$LABEL: signature has no secure timestamp" >> "$PREFLIGHT_ERRORS"
|
||||
done
|
||||
rm -rf "$CHECKTMP"
|
||||
done
|
||||
if [ -s "$PREFLIGHT_ERRORS" ]; then
|
||||
echo "ERROR: these would fail notarization:" >&2
|
||||
sed 's/^/ /' "$PREFLIGHT_ERRORS" >&2
|
||||
rm -f "$PREFLIGHT_ERRORS"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$PREFLIGHT_ERRORS"
|
||||
echo " preflight ok"
|
||||
|
||||
echo "==> Step 3/4: building the dmg"
|
||||
|
||||
# Not with jpackage: "jpackage --type dmg --app-image" re-signs the app it is
|
||||
# handed, replacing our Developer ID signature with an ad-hoc one and dropping
|
||||
# the hardened runtime flag. hdiutil copies the bundle verbatim instead.
|
||||
DMG="dist/KST4Contest-${APP_VERSION}.dmg"
|
||||
STAGE="$(mktemp -d)"
|
||||
# ditto rather than cp -R: it preserves the extended attributes the code
|
||||
# signature depends on.
|
||||
ditto "$APP" "$STAGE/KST4Contest.app"
|
||||
ln -s /Applications "$STAGE/Applications"
|
||||
|
||||
hdiutil create -volname "KST4Contest" -srcfolder "$STAGE" \
|
||||
-ov -format UDZO -quiet "$DMG"
|
||||
rm -rf "$STAGE"
|
||||
[ -f "$DMG" ] || { echo "hdiutil produced no DMG" >&2; exit 1; }
|
||||
|
||||
# Signing the DMG itself is not what Gatekeeper judges -- that is the .app
|
||||
# inside -- but Apple expects the container to be signed too.
|
||||
codesign --force --timestamp --sign "$FULL_IDENTITY" "$DMG"
|
||||
echo "==> Built $DMG"
|
||||
|
||||
echo "==> Step 4/4: verification"
|
||||
|
||||
if [ ${#NOTARY_ARGS[@]} -gt 0 ]; then
|
||||
echo " submitting for notarization (waits for Apple's verdict)"
|
||||
# Without a timeout a stalled submission would hang a CI job forever.
|
||||
xcrun notarytool submit "$DMG" "${NOTARY_ARGS[@]}" --wait --timeout 30m
|
||||
echo " stapling ticket"
|
||||
xcrun stapler staple "$DMG"
|
||||
else
|
||||
echo " no notarization credentials set, skipping notarization"
|
||||
fi
|
||||
|
||||
# Everything below inspects the app as it actually ships, mounted from the DMG,
|
||||
# rather than the staging copy on disk.
|
||||
MOUNT_POINT="$(mktemp -d)"
|
||||
hdiutil attach "$DMG" -nobrowse -quiet -mountpoint "$MOUNT_POINT"
|
||||
trap 'hdiutil detach "$MOUNT_POINT" -quiet 2>/dev/null || hdiutil detach "$MOUNT_POINT" -force -quiet 2>/dev/null || true' EXIT
|
||||
SHIPPED_APP="$MOUNT_POINT/KST4Contest.app"
|
||||
|
||||
echo "--- codesign --verify on the app inside the DMG ---"
|
||||
codesign --verify --deep --strict --verbose=2 "$SHIPPED_APP"
|
||||
|
||||
echo "--- app identity ---"
|
||||
codesign -dv --verbose=2 "$SHIPPED_APP" 2>&1 | grep -iE "identifier|authority|teamidentifier|flags"
|
||||
|
||||
# An ad-hoc signature here means something along the way re-signed the bundle.
|
||||
if codesign -dv "$SHIPPED_APP" 2>&1 | grep -q "adhoc"; then
|
||||
echo "ERROR: the app inside the DMG is ad-hoc signed, not Developer ID signed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "--- entitlements as signed ---"
|
||||
codesign -d --entitlements - --xml "$SHIPPED_APP" 2>/dev/null | plutil -convert xml1 -o - - | grep -E "key|true|false"
|
||||
|
||||
echo "--- dmg identity ---"
|
||||
codesign -dv --verbose=2 "$DMG" 2>&1 | grep -iE "authority|teamidentifier" | head -2
|
||||
|
||||
echo "--- spctl assessment ---"
|
||||
# Without notarization this reports "rejected"; that is expected.
|
||||
spctl --assess --type execute --verbose=4 "$SHIPPED_APP" || true
|
||||
|
||||
if [ ${#NOTARY_ARGS[@]} -gt 0 ]; then
|
||||
echo "--- stapler validate ---"
|
||||
xcrun stapler validate "$DMG"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Done: $REPO_ROOT/$DMG"
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Import the Developer ID certificate into a throwaway keychain on a CI runner.
|
||||
#
|
||||
# A runner cannot answer the keychain's authorization dialog, so the login
|
||||
# keychain is unusable there. This creates a dedicated keychain instead, whose
|
||||
# password is generated here and needed nowhere else -- it is discarded with the
|
||||
# keychain at the end of the job.
|
||||
#
|
||||
# Reads from the environment:
|
||||
# MACOS_CERT_P12 base64 of the exported .p12
|
||||
# MACOS_CERT_PASSWORD the password that .p12 was exported with
|
||||
#
|
||||
# Exports to $GITHUB_ENV:
|
||||
# SIGNING_IDENTITY for packaging/macos/build-signed-dmg.sh
|
||||
# SIGNING_KEYCHAIN so the cleanup step knows what to delete
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
: "${MACOS_CERT_P12:?MACOS_CERT_P12 is not set}"
|
||||
: "${MACOS_CERT_PASSWORD:?MACOS_CERT_PASSWORD is not set}"
|
||||
: "${RUNNER_TEMP:?RUNNER_TEMP is not set}"
|
||||
: "${GITHUB_ENV:?GITHUB_ENV is not set}"
|
||||
|
||||
KEYCHAIN="$RUNNER_TEMP/kst4contest-signing.keychain-db"
|
||||
KEYCHAIN_PASSWORD="$(uuidgen)"
|
||||
CERT="$RUNNER_TEMP/cert.p12"
|
||||
|
||||
printf '%s' "$MACOS_CERT_P12" | base64 --decode > "$CERT"
|
||||
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
|
||||
# Keychains re-lock after five minutes by default, which would strand a build
|
||||
# halfway through signing.
|
||||
security set-keychain-settings -lut 21600 "$KEYCHAIN"
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
|
||||
|
||||
security import "$CERT" -k "$KEYCHAIN" -P "$MACOS_CERT_PASSWORD" \
|
||||
-T /usr/bin/codesign -T /usr/bin/security
|
||||
rm -f "$CERT"
|
||||
|
||||
# Lets codesign reach the private key without the UI prompt a runner has no way
|
||||
# of answering.
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: \
|
||||
-s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN" >/dev/null
|
||||
|
||||
# codesign searches the keychain list, so the new keychain has to be on it --
|
||||
# added to whatever the runner already had, not in place of it.
|
||||
EXISTING_KEYCHAINS="$(security list-keychains -d user | sed -e 's/^[[:space:]]*"//' -e 's/"$//')"
|
||||
# shellcheck disable=SC2086
|
||||
security list-keychains -d user -s "$KEYCHAIN" $EXISTING_KEYCHAINS
|
||||
|
||||
IDENTITY="$(security find-identity -v -p codesigning "$KEYCHAIN" \
|
||||
| sed -n 's/.*"Developer ID Application: \(.*\)".*/\1/p' | head -n 1)"
|
||||
|
||||
if [ -z "$IDENTITY" ]; then
|
||||
echo "No 'Developer ID Application' identity found in the imported certificate." >&2
|
||||
echo "What the keychain does contain:" >&2
|
||||
security find-identity -v -p codesigning "$KEYCHAIN" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Imported identity: Developer ID Application: $IDENTITY"
|
||||
echo "SIGNING_IDENTITY=$IDENTITY" >> "$GITHUB_ENV"
|
||||
echo "SIGNING_KEYCHAIN=$KEYCHAIN" >> "$GITHUB_ENV"
|
||||
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- The JVM compiles bytecode to machine code at runtime and executes it
|
||||
from memory it allocated itself. Under the hardened runtime all three
|
||||
of these are required or the app is killed on launch. -->
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<!-- jpackage bundles JavaFX native libraries that are signed with our own
|
||||
identity rather than Apple's, and the JVM dlopen()s them at runtime. -->
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
|
||||
<!-- KST4Contest talks to the ON4KST chat servers. -->
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
Before Width: | Height: | Size: 264 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.6 KiB |
@@ -129,14 +129,14 @@ module.exports = async function () {
|
||||
os: "macOS Apple Silicon",
|
||||
format: "DMG arm64",
|
||||
icon: "🍎",
|
||||
note: "Best-effort build for Apple Silicon Macs. Not currently notarized by Apple.",
|
||||
note: "Best-effort build for Apple Silicon Macs. Signed and notarized by Apple from version 1.42 onwards.",
|
||||
url: assetUrl("KST4Contest-{tag}-macos-arm64.dmg")
|
||||
},
|
||||
{
|
||||
os: "macOS Intel",
|
||||
format: "DMG x86_64",
|
||||
icon: "🍎",
|
||||
note: "Best-effort build for Intel Macs. Not currently notarized by Apple.",
|
||||
note: "Best-effort build for Intel Macs. Signed and notarized by Apple from version 1.42 onwards.",
|
||||
url: assetUrl("KST4Contest-{tag}-macos-x86_64.dmg")
|
||||
}
|
||||
];
|
||||
|
||||
@@ -121,7 +121,7 @@ module.exports = async function () {
|
||||
format: "DMG arm64",
|
||||
icon: "🍎",
|
||||
recommended: false,
|
||||
note: "Best-effort build for Apple Silicon Macs. The application is not currently notarized by Apple.",
|
||||
note: "Best-effort build for Apple Silicon Macs. Signed and notarized by Apple from version 1.42 onwards.",
|
||||
url: assetUrl("KST4Contest-{tag}-macos-arm64.dmg")
|
||||
},
|
||||
{
|
||||
@@ -129,7 +129,7 @@ module.exports = async function () {
|
||||
format: "DMG x86_64",
|
||||
icon: "🍎",
|
||||
recommended: false,
|
||||
note: "Best-effort build for Intel Macs. The application is not currently notarized by Apple.",
|
||||
note: "Best-effort build for Intel Macs. Signed and notarized by Apple from version 1.42 onwards.",
|
||||
url: assetUrl("KST4Contest-{tag}-macos-x86_64.dmg")
|
||||
},
|
||||
{
|
||||
|
||||
@@ -67,14 +67,14 @@ const ARTIFACT_INFO = {
|
||||
os: "macOS Apple Silicon",
|
||||
format: "DMG arm64",
|
||||
icon: "🍎",
|
||||
note: "Best-effort build for Apple Silicon Macs. Not notarized by Apple.",
|
||||
note: "Best-effort build for Apple Silicon Macs. Signed and notarized by Apple.",
|
||||
order: 7
|
||||
},
|
||||
"macos-dmg-macos-15-intel": {
|
||||
os: "macOS Intel",
|
||||
format: "DMG x86_64",
|
||||
icon: "🍎",
|
||||
note: "Best-effort build for Intel Macs. Not notarized by Apple.",
|
||||
note: "Best-effort build for Intel Macs. Signed and notarized by Apple.",
|
||||
order: 8
|
||||
}
|
||||
};
|
||||
|
||||
@@ -223,9 +223,11 @@ description: Download the latest stable KST4Contest packages for Windows, Linux
|
||||
with their respective package managers.
|
||||
</p>
|
||||
<p>
|
||||
macOS packages are provided for Apple Silicon and Intel systems on a best-effort basis. They are
|
||||
not currently notarized by Apple. The installation guide covers the first launch, updates, the
|
||||
Stable, Beta and Nightly channels, and the location of the settings directory.
|
||||
macOS packages are provided for Apple Silicon and Intel systems on a best-effort basis. From
|
||||
version 1.42 onwards they are signed with an Apple Developer ID and notarized by Apple, so they
|
||||
start by double-clicking without a security prompt. The installation guide covers the first
|
||||
launch, updates, the Stable, Beta and Nightly channels, and the location of the settings
|
||||
directory.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<a class="button" href="/manual/en/installation/">Read the installation guide</a>
|
||||
|
||||