開発中のXcodeプロジェクトは、署名がAutomatic(自動署名)で、Apple Developmentの証明書を使うのが一般的である。配布用のアプリは、Developer ID Applicationの証明書で署名する。ローカルの設定は変えずに、CIでだけDeveloper IDの署名に切り替えたい。
切り替えの方法には、project.pbxprojをsedで書き換える方法と、xcodebuildの引数で上書きする方法がある。引数で上書きする方法であれば、ファイルを書き換えずに済む。
- name: Archive
env:
TEAM_ID: ${{ secrets.TEAM_ID }}
run: |
xcodebuild -project [プロジェクト名].xcodeproj -scheme [スキーム名] -configuration Release \
-archivePath build/[アプリ名].xcarchive \
CODE_SIGN_STYLE=Manual CODE_SIGN_IDENTITY="Developer ID Application" DEVELOPMENT_TEAM="$TEAM_ID" archive
実行例は、Xcode 27.0のランナー(runs-on: xcode-27)のもの。証明書は、事前にキーチェーンへインポートしておく。
- 前の記事: 【GitHub Actions】一時keychainに証明書をインポートして署名する
- 親記事: GitHubを使い、macOSアプリを署名・公証・自動アップデート付きで公開する
- 次の記事: 【GitHub Actions】タグpushで公証からRelease作成まで自動化する
ビルド設定を上書きする方法
xcodebuildは、コマンドラインの末尾に[ビルド設定]=[値]と書くと、ビルド設定を上書きする。project.pbxprojの内容よりも、コマンドラインの指定が優先される。
| ビルド設定 | 値 | 意味 |
|---|---|---|
CODE_SIGN_STYLE | Manual | 署名の方法を手動にする |
CODE_SIGN_IDENTITY | Developer ID Application | 署名に使う証明書 |
DEVELOPMENT_TEAM | Team ID | 署名するTeam |
この方法でアーカイブを作ると、アーカイブの中のアプリが、Developer IDの証明書で署名される。ワークフローのログには、実行されたxcodebuildのコマンドが表示される。Secretsの値は、***に置き換えられる。
/Applications/Xcode_27.app/Contents/Developer/usr/bin/xcodebuild -project [プロジェクト名].xcodeproj -scheme [スキーム名] -configuration Release -archivePath build/[アプリ名].xcarchive CODE_SIGN_STYLE=Manual "CODE_SIGN_IDENTITY=Developer ID Application" DEVELOPMENT_TEAM=*** archive
アーカイブの署名を確認する。
- name: Show signature
run: codesign -dv --verbose=2 build/[アプリ名].xcarchive/Products/Applications/[アプリ名].app 2>&1 | grep -E 'Authority|flags|Timestamp'
CodeDirectory v=20500 size=488 flags=0x10000(runtime) hashes=4+7 location=embedded
Authority=Developer ID Application: [名前] (***)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=[署名した日時]
flags=0x10000(runtime)は、Hardened Runtimeが有効であることを表す。Hardened Runtimeは、Xcodeのプロジェクトで有効にしておく。
引数で上書きしても、ワーキングツリーは変更されない。git status --shortの結果は、空である。
$ git status --short
$
ローカルでは、Automatic署名のまま、通常どおりビルドできる。
pbxprojをsedで書き換える方法
project.pbxprojを、sedとperlで書き換える方法もある。署名の方法をManualに変え、CODE_SIGN_IDENTITYを追加する。
- name: Rewrite project.pbxproj
run: |
sed -i '' 's/CODE_SIGN_STYLE = Automatic;/CODE_SIGN_STYLE = Manual;/' [プロジェクト名].xcodeproj/project.pbxproj
perl -i -pe 's/(CODE_SIGN_STYLE = Manual;)/$1\n\t\t\t\tCODE_SIGN_IDENTITY = "Developer ID Application";/' [プロジェクト名].xcodeproj/project.pbxproj
git diff --stat
macOSのsedは、BSD版である。-iには、バックアップの拡張子を渡す必要があり、バックアップを作らないときは''を渡す。GNU版のsedとは、書き方が異なる。
参考: 【Mac】GNUのsedを使う
この方法でも、アーカイブはDeveloper IDの署名になる。署名の結果は、引数で上書きした場合と同じである。
CodeDirectory v=20500 size=488 flags=0x10000(runtime) hashes=4+7 location=embedded
Authority=Developer ID Application: [名前] ([Team ID])
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=[署名した日時]
sedは意図しない箇所も書き換える
git diff --statで、書き換えの範囲を確認すると、project.pbxprojが12行追加、6行削除になる。
[プロジェクト名].xcodeproj/project.pbxproj | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
CODE_SIGN_STYLE = Automatic;は、アプリのターゲットだけでなく、テストのターゲットを含む6か所に存在する。sedは、すべての箇所を書き換える。アプリのターゲットだけに絞りたい場合は、sedの指定が複雑になる。
sedは一致しなくても成功する
sedは、置換する文字列が見つからなくても、終了コードが0である。プロジェクトの設定が変わり、置換のパターンに一致しなくなっても、ワークフローは成功する。
$ sed -i '' 's/DOES_NOT_EXIST/x/' file
$ echo $?
0
署名の設定が書き換わらないまま、ビルドが進む。署名の失敗は、後の段階で見つかる。引数で上書きする方法であれば、置換のパターンに依存しない。
ExportOptions.plistのTeam IDを埋め込む
エクスポートに使うExportOptions.plistも、Team IDなどをSecretsから渡す。リポジトリには、プレースホルダー(YOUR_TEAM_ID)で保存しておく。
<key>teamID</key>
<string>YOUR_TEAM_ID</string>
ワークフローで、プレースホルダーを置き換える。
- name: Export archive
env:
TEAM_ID: ${{ secrets.TEAM_ID }}
run: |
sed -i '' "s/YOUR_TEAM_ID/$TEAM_ID/" ExportOptions.plist
xcodebuild -exportArchive -archivePath build/[アプリ名].xcarchive -exportPath build -exportOptionsPlist ExportOptions.plist
plistの値は、PlistBuddyでも書き換えられる。PlistBuddyは、キーが存在しない場合に、終了コード1で失敗する。
$ /usr/libexec/PlistBuddy -c "Set :teamID $TEAM_ID" ExportOptions.plist
$ /usr/libexec/PlistBuddy -c "Print :teamID" ExportOptions.plist
[Team ID]
$ /usr/libexec/PlistBuddy -c "Set :noSuchKey x" ExportOptions.plist
Set: Entry, ":noSuchKey", Does Not Exist
$ echo $?
1
置換の失敗を検出したい場合は、sedよりもPlistBuddyが適している。
どちらの方法を選ぶか
引数で上書きする方法は、ファイルを書き換えないため、ローカルの設定と、CIの設定が分離される。sedによる書き換えと違い、置換のパターンの変更や、意図しない箇所の書き換えを心配しなくてよい。
xcodebuildの引数が長くなるときは、ビルド設定を.xcconfigのファイルにまとめて、-xcconfigで渡す方法もある。
