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>
149 lines
5.7 KiB
Bash
Executable File
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"
|