Ein macOS-DMG erstellen und die Installation prüfen

DevOps & CI/CD ·ca. 5 Min. Lesezeit

Ein macOS-DMG erstellen und die Installation prüfen

Der Build-Rechner hat Example.app erzeugt, und der Release-Job hat daraus erfolgreich ein DMG erstellt. Vor der Auslieferung sind noch drei Fragen zu klären: Enthält das gemountete Image die vollständige App und einen Link zum Ordner „Programme“? Ist die Signatur der aus dem Image kopierten App gültig? Können Nutzer die App in der grafischen Oberfläche per Drag-and-drop installieren? Die folgenden Prüfungen machen diese Schritte wiederholbar. Ersetzen Sie Example.app in den Beispielen durch den Namen Ihres tatsächlichen Builds.

Zuerst festlegen, was ins Paket gehört

Als Eingabe muss das App-Bundle in seiner endgültigen Fassung vorliegen. Legen Sie im Build-Job zunächst den Pfad zum Ergebnis fest, prüfen Sie, ob die ausführbare Datei der App vorhanden ist, und schließen Sie den vorgesehenen Signaturprozess ab. Das Erstellen des DMG ist keine Gelegenheit, Inhalte der App nachzubessern: Änderungen an Ressourcen, ausführbaren Dateien oder eingebetteten Komponenten können eine vorhandene Signatur ungültig machen.

Prüfen Sie das Verzeichnis mit test -d, statt lediglich nach einer gleichnamigen Datei zu suchen. Stellen Sie außerdem sicher, dass am Ausgabepfad noch kein altes DMG liegt. Ein eindeutiger Fehler ist leichter nachzuvollziehen als das unbemerkte Überschreiben eines früheren Release-Artefakts. Wenn die Pipeline Jobs erneut ausführen kann, sollte sie ihr eigenes Ausgabeverzeichnis vorher bereinigen. Das Packskript sollte keine unbekannten Dateien löschen.

Ein intaktes Image, eine gültige App-Signatur und das Vertrauen des Systems in die App sind drei verschiedene Befunde. Keiner davon ersetzt die beiden anderen.

Ein Image mit Installationslink erstellen

Das folgende Skript stellt den Volume-Inhalt in einem temporären Verzeichnis zusammen: Es kopiert die bereits signierte App und legt einen symbolischen Link auf /Applications an. ditto kopiert das App-Bundle; bearbeiten Sie danach keine Dateien mehr innerhalb des Bundles.

#!/bin/bash
set -euo pipefail

APP="$PWD/build/Release/Example.app"
OUT="$PWD/dist/Example.dmg"

test -d "$APP"
test -f "$APP/Contents/MacOS/Example"
mkdir -p "$(dirname "$OUT")"
test ! -e "$OUT"

work="$(mktemp -d "${TMPDIR:-/tmp}/dmg-build.XXXXXX")"
trap 'rm -rf "$work"' EXIT

stage="$work/stage"
mkdir -p "$stage"
ditto "$APP" "$stage/Example.app"
ln -s /Applications "$stage/Applications"

hdiutil create -volname "Example" \
  -srcfolder "$stage" -fs HFS+ -format UDZO "$OUT"

Falls die ausführbare Datei Ihrer App nicht Example heißt, passen Sie auch den Prüfpfad an. Der Volume-Name ist lediglich der Name, den Nutzer nach dem Mounten sehen; er bestimmt nicht den Installationspfad der App. Die Trennung zwischen temporärem Bereitstellungsverzeichnis und endgültigem Ausgabeverzeichnis erleichtert das Aufräumen beim Beenden und verhindert, dass ein altes Image versehentlich in das neue gelangt.

Was nicht auf das Volume gehört

Prüfen Sie zunächst anhand der Verzeichnisliste, ob der Bereitstellungsbereich nur das App-Bundle und den Installationslink enthält. Build-Protokolle, Signaturmaterial, Debug-Dateien und das Projekt-Repository gehören nicht in das ausgelieferte DMG. Im Skript ist stage das einzige Eingabeverzeichnis. Wenn später eine Anleitungsdatei hinzukommt, nehmen Sie sie ausdrücklich auf und prüfen Sie sie, statt hdiutil create auf das gesamte Arbeitsverzeichnis anzuwenden.

Das DMG erneut mounten und den ausgelieferten Inhalt prüfen

Prüfen Sie nicht nur das Quellverzeichnis, sondern öffnen Sie das gerade erzeugte DMG. hdiutil verify prüft das Image. Mounten Sie es anschließend schreibgeschützt, kontrollieren Sie die Pfade auf dem Volume, kopieren Sie die App in ein separates Verzeichnis und überprüfen Sie ihre Signatur:

#!/bin/bash
set -euo pipefail

OUT="$PWD/dist/Example.dmg"
work="$(mktemp -d "${TMPDIR:-/tmp}/dmg-check.XXXXXX")"
mountpoint="$work/mount"
attached=0

cleanup() {
  if [ "$attached" -eq 1 ]; then
    hdiutil detach "$mountpoint" >/dev/null || true
  fi
  rm -rf "$work"
}
trap cleanup EXIT

mkdir -p "$mountpoint" "$work/installed"
hdiutil verify "$OUT"
hdiutil attach -readonly -nobrowse \
  -mountpoint "$mountpoint" "$OUT" >/dev/null
attached=1

test -d "$mountpoint/Example.app"
test -L "$mountpoint/Applications"
test "$(readlink "$mountpoint/Applications")" = /Applications

ditto "$mountpoint/Example.app" "$work/installed/Example.app"
codesign --verify --deep --strict \
  "$work/installed/Example.app"

Bei einem Fehler liefert das Skript einen Status ungleich null zurück und lässt sich so in einen Release-Job einbinden. Schlägt das Aushängen fehl, prüfen Sie von Hand, ob noch ein Prozess auf das Volume zugreift. Verdecken Sie eine solche Belegung nicht durch erzwungenes Aushängen. codesign --verify prüft, ob das kopierte Bundle die Signaturanforderungen weiterhin erfüllt. Das bedeutet nicht, dass das System der App bereits vertraut. Wenn Sie einen Signatur- und Notarisierungsprozess für die externe Verteilung nutzen, müssen Sie die Systembewertung zusätzlich nach den Vorgaben dieses Prozesses prüfen.

Den Installationsweg in einer grafischen Sitzung testen

Die Kommandozeile kann Pfade und Signaturen prüfen. Sie kann aber nicht belegen, dass die Symbole übersichtlich angeordnet sind, das Drag-and-drop-Ziel sichtbar ist oder der erste Start ohne Auffälligkeiten verläuft. Öffnen Sie das DMG in einer angemeldeten grafischen macOS-Sitzung und gehen Sie wie ein gewöhnlicher Nutzer vor:

  1. Prüfen Sie, ob das Volume nur die erwartete App und den Link zum Ordner „Programme“ enthält und ob die Namen weder abgeschnitten noch missverständlich sind.
  2. Ziehen Sie die App in „Programme“ und vergewissern Sie sich, dass der Kopiervorgang abgeschlossen ist. Ein direkter Start vom schreibgeschützten Volume ersetzt keinen Installationstest.
  3. Starten Sie die kopierte App und prüfen Sie das erste Fenster sowie die erforderlichen Abläufe für den Dateizugriff.
  4. Hängen Sie das Volume aus und starten Sie die installierte App erneut. So schließen Sie aus, dass sie noch Ressourcen auf dem Volume benötigt.

Stellen Sie vor diesen Prüfungen sicher, dass am Testort keine ältere App mit demselben Namen liegt. Andernfalls öffnen Sie möglicherweise die Version aus einer früheren Installation. Kontrollieren Sie auch vor dem Löschen der Testkopie den Pfad, damit Sie nicht versehentlich eine regulär genutzte App entfernen. Ist keine grafische Sitzung verfügbar, kennzeichnen Sie den Release mit „Kommandozeilenprüfungen bestanden, grafische Abnahme ausstehend“. Fassen Sie beides nicht zu einem erfolgreichen Gesamtergebnis zusammen.

Fehler der richtigen Ebene zuordnen

Falls hdiutil verify fehlschlägt, bewahren Sie zunächst das ursprüngliche DMG und die Erstellungsprotokolle auf. Prüfen Sie, ob das Artefakt hochgeladen oder gelesen wurde, bevor der Schreibvorgang abgeschlossen war. Fehlen Dateien auf dem Volume, untersuchen Sie das Bereitstellungsverzeichnis und den Eingabepfad für ditto. Schlägt die Signaturprüfung fehl, prüfen Sie, ob ein Skript das App-Bundle nach dem Signieren noch verändert hat, und erstellen Sie das Image aus der endgültigen App neu. Wiederholte punktuelle Reparaturen am bestehenden DMG machen das ausgelieferte Artefakt schwer nachvollziehbar.

Wenn alle Kommandozeilenprüfungen bestehen, die App nach dem Ziehen in „Programme“ aber nicht startet, prüfen Sie zuerst den tatsächlich gestarteten Pfad, die App-Signatur und die für eine externe Verteilung erforderliche Systemvertrauensprüfung. Halten Sie abschließend die Build-Kennung der App, die Prüfsumme der DMG-Datei, die Ergebnisse der automatischen Prüfungen und das Ergebnis der grafischen Abnahme fest. So lässt sich beim nächsten Release feststellen, ob ein Problem beim Build, beim Packen oder bei der Installation entstanden ist.

Häufig gestellte Fragen

Beweist hdiutil verify, dass sich die App starten lässt?

Nein. Der Befehl prüft das Image, nicht den Start der kopierten App. Signatur und grafischer Start benötigen eigene Tests.

Wann sollte das App-Bundle signiert werden?

Vor dem Packen des DMG. Signieren und prüfen Sie die endgültige App; nach jeder Änderung am Bundle ist ein neuer Paketlauf nötig.

Sie brauchen einen exklusiven Mac in der Cloud?

Wählen Sie Modell, Standort und Abrechnungszeitraum. Sie erhalten einen exklusiven physischen Mac. Die tatsächliche Verfügbarkeit sehen Sie live in der Konsole.

Konfiguration ansehen und bestellen