リモート Mac で macOS DMG の作成とインストールを検証する

CI/CD ·約 9 分

リモート Mac で macOS DMG の作成とインストールを検証する

ビルドマシンで Example.app が生成され、リリースジョブでも DMG の作成が完了しました。それでも配布前には、マウントしたイメージに完全なアプリと「アプリケーション」への入口があるか、コピーしたアプリの署名は有効か、ユーザーが GUI でドラッグしてインストールできるか、という三点を確認する必要があります。以下では、それぞれを繰り返し実行できる検査に分けます。例にある Example.app は実際の成果物名に置き換えてください。

パッケージ化する範囲を先に確定する

入力には最終版のアプリバンドルを使用します。まずビルドジョブで成果物のパスを確定し、アプリの実行ファイルが存在することを確認して、予定していた署名処理を完了させてください。DMG の作成時にアプリの内容を修正してはいけません。リソース、実行ファイル、組み込みコンポーネントを変更すると、既存の署名が無効になる可能性があります。

ディレクトリの確認には test -d を使い、同名のファイルがあるかどうかだけで判断しないでください。また、出力先に古い DMG が残っていないことも確認します。前回のリリース成果物を黙って上書きするより、明示的に失敗させるほうが原因を追いやすくなります。パイプラインが再試行を行う場合は、パッケージ化スクリプトに不明なファイルを削除させず、パイプライン側で自分の出力ディレクトリを事前に整理してください。

イメージが完全であること、アプリの署名が有効であること、システムがそのアプリを信頼することは、それぞれ別の結論です。一つの検査に合格しても、ほかの二つの代わりにはなりません。

インストール先への入口を備えたイメージを作成する

次のスクリプトは、一時ディレクトリにボリュームの内容を配置します。署名済みアプリをコピーし、/Applications を指すシンボリックリンクを作成します。アプリバンドルのコピーには ditto を使い、コピー後にバンドル内のファイルを編集しないでください。

#!/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"

アプリの実行ファイル名が Example でない場合は、確認用のパスも変更してください。ボリューム名はマウント後にユーザーに表示される名前であり、アプリのインストール先を決めるものではありません。一時的な配置用ディレクトリと最終的な出力ディレクトリを分けておけば、終了時の後片付けがしやすくなり、古いイメージを誤って新しいイメージに含めることも防げます。

ボリュームに入れないもの

まずディレクトリの一覧を確認し、配置用ディレクトリにはアプリバンドルとインストール先への入口だけがあることを確かめます。ビルドログ、署名に使う素材、デバッグファイル、プロジェクトのリポジトリを DMG に含めてはいけません。スクリプトでは stage だけを入力ディレクトリにしています。後で説明ファイルを追加する場合も、ファイルを明示的に配置して確認してください。作業ディレクトリ全体を対象に hdiutil create を実行してはいけません。

再マウントして実際の配布内容を確認する

元のディレクトリを見るだけで済ませず、作成したばかりの DMG を開いてください。hdiutil verify でイメージを検査してから読み取り専用でマウントし、ボリューム内のパスを確認します。その後、アプリを別のディレクトリにコピーして署名を検証します。

#!/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"

検査に失敗するとスクリプトはゼロ以外の終了ステータスを返すため、リリースジョブに組み込めます。マウント解除に失敗した場合は、ボリュームを使用中のプロセスがないか手動で確認してください。強制的なマウント解除で使用中の状態を隠してはいけません。codesign --verify は、コピー後のバンドルが引き続き署名要件を満たすかを調べますが、システムがそのアプリを信頼したことと同義ではありません。外部配布向けの署名と公証の手順を採用している場合は、その手順に従ってシステムの評価結果も別途検証してください。

GUI セッションでユーザーのインストール操作を試す

コマンドラインではパスと署名を確認できますが、アイコンの配置が分かりやすいか、ドラッグ先が見えるか、初回起動に問題がないかまでは判断できません。ログイン済みの macOS GUI セッションで DMG を開き、一般のユーザーと同じ順序で操作します。

  1. ボリュームに想定どおりのアプリと「アプリケーション」への入口だけがあり、名前が途中で切れたり紛らわしくなったりしていないことを確認します。
  2. アプリを「アプリケーション」にドラッグし、コピーが完了したことを確認します。読み取り専用ボリュームから直接起動するだけでは、インストールのテストになりません。
  3. コピー後のアプリを起動し、最初のウィンドウと必要なファイルアクセスの操作を確認します。
  4. ボリュームをマウント解除してから、インストールしたアプリをもう一度起動します。これにより、アプリがボリューム内のリソースに依存していないことを確かめます。

この一連の検査を始める前に、テスト先に同名の古いアプリがないことを確認してください。残っていると、前回インストールした版を開いてしまう可能性があります。テスト用のコピーを削除する際もパスを確認し、普段使っているアプリを誤って削除しないようにします。GUI セッションを利用できない場合は、リリースを「コマンドライン検査は合格、GUI での受け入れ確認は未完了」と記録し、両者をまとめて成功扱いにしないでください。

失敗した箇所を切り分ける

hdiutil verify が失敗した場合は、まず元の DMG と生成ログを保存し、書き込みが完了する前に成果物がアップロードまたは読み取られていないかを調べます。ボリューム内のファイルが不足している場合は、配置用ディレクトリと ditto の入力パスに戻って確認します。署名の検証に失敗した場合は、署名後にスクリプトがアプリバンドルを変更していないかを調べ、最終版のアプリからイメージを作り直してください。既存の DMG を繰り返し部分的に修正すると、配布物の来歴を追いにくくなります。

コマンドラインの検査がすべて通るのに、ドラッグしたアプリだけが起動しない場合は、実際に起動しているパス、アプリの署名、外部配布に必要なシステムの信頼性評価を優先して確認します。最後に、アプリのビルド識別子、DMG ファイルのチェックサム、自動検査の結果、GUI での受け入れ確認の結論を記録してください。次回の配布時に、問題がビルド、パッケージ化、インストールのどの段階で起きたか判断できます。

よくある質問

hdiutil verify が成功すればアプリも起動できますか?

いいえ。確認できるのはイメージの整合性です。署名とコピー後の起動は別に検証します。

アプリの署名は DMG 作成の前に済ませるべきですか?

はい。最終状態のアプリを署名・検証してから DMG を作成し、アプリを変更したら再作成します。

専用のクラウド Mac をお探しですか?

機種、ロケーション、利用期間を選ぶだけ。専有の物理マシンを提供します。実際の利用可否は、コントロールパネルに表示される最新情報をご確認ください。

構成を確認して注文