Files
onyx/Scripts/release.sh
Scarriffle 928ee90b5e Das Installationsfenster sieht aus wie eines
Zwei Symbole auf grauem Grund sagen nicht, was zu tun ist. Jetzt: dunkler
Verlauf in den Onyx-Farben, Titel, ein Satz darunter, eine Haarlinie und ein
Pfeil, der vom Programm zum Programme-Ordner zeigt. Die Fassung steht in der
Fußzeile — damit man später weiß, was man installiert hat.

Der Hintergrund wird gezeichnet, nicht mitgeliefert: ein Bild im Verzeichnis
wäre eine Datei, die niemand mehr anfasst und die bei jeder Farbänderung
veraltet. So stehen die Onyx-Farben genau einmal, im selben Werkzeugkasten wie
der Rest.

Der Aufwand steckt nicht im Bild, sondern in der Reihenfolge: Fenstergröße,
Symbolplätze und Hintergrund leben in der .DS_Store des Abbilds. Die schreibt
nur der Finder, und nur in ein beschreibbares Abbild. Also erst UDRW, dann
über AppleScript einrichten, warten bis der Finder geschrieben hat, dann
zusammenpressen. Schlägt die Automatisierung fehl, bleibt das Fenster schlicht
statt das Skript abzubrechen.

Als Bibliothek, weil beide Wege dasselbe Fenster zeigen sollen — der lokale
wie der notarisierte. Und als TIFF mit beiden Auflösungen: als reines PNG wäre
der Hintergrund auf einem Retina-Bildschirm doppelt so groß wie das Fenster.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 12:57:51 +02:00

149 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
# Baut Onyx als notarisiertes DMG.
#
# Voraussetzungen — beide einmalig einzurichten:
#
# 1. Ein Zertifikat „Developer ID Application: … (PP34X97WS3)" im Schlüsselbund.
# Xcode → Einstellungen → Konten → Manage Certificates → + →
# Developer ID Application. Das Entwicklerzertifikat („Apple Development")
# genügt NICHT: damit signierte Apps lassen sich nicht notarisieren und
# laufen auf keinem fremden Mac.
#
# 2. Ein Zugangsprofil für notarytool:
# xcrun notarytool store-credentials "Onyx" \
# --apple-id "<Apple-ID>" --team-id PP34X97WS3 \
# --password "<app-spezifisches Passwort>"
# Das app-spezifische Passwort kommt von appleid.apple.com, nicht das
# normale Kennwort.
#
# Danach genügt: Scripts/release.sh
set -euo pipefail
export DEVELOPER_DIR=${DEVELOPER_DIR:-/Applications/Xcode.app/Contents/Developer}
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BUILD="$ROOT/build/release"
PROFILE="${NOTARY_PROFILE:-Onyx}"
TEAM="PP34X97WS3"
APP_NAME="Onyx"
cd "$ROOT"
VERSION=$(awk -F'"' '/MARKETING_VERSION/ {print $2; exit}' project.yml)
DMG="$BUILD/${APP_NAME}-${VERSION}.dmg"
fail() { echo "$*" >&2; exit 1; }
step() { echo; echo "── $* ──"; }
# ---------------------------------------------------------------- Vorprüfung
#
# Beide Prüfungen vorweg statt unterwegs: ein Fehlschlag nach dem Archivieren
# kostet Minuten, und die Notarisierung scheitert sonst erst nach dem Hochladen.
step "Vorprüfung"
security find-identity -v -p codesigning | grep -q "Developer ID Application" \
|| fail "Kein „Developer ID Application“-Zertifikat im Schlüsselbund. Siehe Kopf dieses Skripts."
xcrun notarytool history --keychain-profile "$PROFILE" >/dev/null 2>&1 \
|| fail "Kein notarytool-Profil „$PROFILE“. Siehe Kopf dieses Skripts."
command -v xcodegen >/dev/null || fail "xcodegen fehlt (brew install xcodegen)"
echo "✓ Zertifikat, Notarisierungsprofil und xcodegen vorhanden"
step "Projekt erzeugen"
xcodegen generate
step "Tests"
(cd Packages/OnyxKit && swift test 2>&1 | tail -3)
# ------------------------------------------------------------------ Bauen
#
# Über ein Archiv und nicht über `build`: nur exportArchive signiert das
# fertige Bundle vollständig mit der Verteilungsidentität, samt aller
# eingebetteten Programme.
step "Archivieren"
rm -rf "$BUILD"
mkdir -p "$BUILD"
xcodebuild archive \
-project Onyx.xcodeproj -scheme Onyx -configuration Release \
-archivePath "$BUILD/$APP_NAME.xcarchive" \
-allowProvisioningUpdates \
CODE_SIGN_STYLE=Automatic \
CODE_SIGN_IDENTITY="Developer ID Application" \
DEVELOPMENT_TEAM="$TEAM" \
| grep -E "error:|warning: .*deprecated|ARCHIVE SUCCEEDED" || true
[ -d "$BUILD/$APP_NAME.xcarchive" ] || fail "Archivieren fehlgeschlagen"
cat > "$BUILD/export.plist" <<PLIST
<?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>
<key>method</key><string>developer-id</string>
<key>teamID</key><string>$TEAM</string>
<key>signingStyle</key><string>automatic</string>
<key>destination</key><string>export</string>
</dict></plist>
PLIST
step "Exportieren"
xcodebuild -exportArchive \
-archivePath "$BUILD/$APP_NAME.xcarchive" \
-exportPath "$BUILD/export" \
-exportOptionsPlist "$BUILD/export.plist" \
-allowProvisioningUpdates | tail -3
APP="$BUILD/export/$APP_NAME.app"
[ -d "$APP" ] || fail "Export fehlgeschlagen"
# --------------------------------------------------------------- Nachprüfen
#
# Was hier durchrutscht, lehnt Apple nach dem Hochladen ab. Die drei Punkte
# sind genau die, an denen dieses Projekt eine Sonderbehandlung hat.
step "Signatur prüfen"
codesign --verify --deep --strict --verbose=2 "$APP" 2>&1 | tail -3
codesign -d --entitlements - "$APP" 2>/dev/null | grep -q "application-groups" \
|| fail "App-Group fehlt in den Entitlements — Calendarr wäre unerreichbar"
# Der Helfer trägt seine Kennung in der Binary, nicht in einer Info.plist.
# Stimmt sie nicht, lehnt die App ihren eigenen Helfer ab.
HELPER_ID=$(codesign -d --verbose=2 "$APP/Contents/MacOS/OnyxHelper" 2>&1 \
| awk -F= '/^Identifier=/ {print $2}')
[ "$HELPER_ID" = "com.scarriffleservices.onyx.helper" ] \
|| fail "Helfer trägt die Kennung „$HELPER_ID“ statt com.scarriffleservices.onyx.helper"
# Ad-hoc signierte Bibliotheken sind der häufigste Ablehnungsgrund.
if codesign -dv "$APP/Contents/Resources/Vendor/MediaRemoteAdapter.framework" 2>&1 \
| grep -q "adhoc"; then
fail "MediaRemoteAdapter.framework ist ad-hoc signiert — die Notarisierung lehnt das ab"
fi
echo "✓ Signaturen, Entitlements, Helfer-Kennung und Adapter in Ordnung"
# ------------------------------------------------------------------- DMG
step "DMG bauen"
source "$ROOT/Scripts/lib-dmg.sh"
make_pretty_dmg "$APP" "$DMG" "$APP_NAME" "$BUILD" "$VERSION"
# Das DMG selbst wird mitsigniert — sonst meldet Gatekeeper beim Öffnen einen
# unbekannten Entwickler, obwohl die App darin einwandfrei ist.
codesign --force --sign "Developer ID Application" --timestamp "$DMG"
# ---------------------------------------------------------- Notarisierung
step "Notarisieren (das dauert)"
xcrun notarytool submit "$DMG" --keychain-profile "$PROFILE" --wait \
|| fail "Notarisierung abgelehnt. Ursache: xcrun notarytool log <id> --keychain-profile $PROFILE"
step "Ticket anheften"
# Ohne Stapeln braucht der erste Start des Nutzers eine Netzverbindung.
xcrun stapler staple "$DMG"
xcrun stapler validate "$DMG"
step "Abschließende Prüfung"
spctl -a -t open --context context:primary-signature -v "$DMG" 2>&1 | tail -2
echo
echo "✓ Fertig: $DMG"