「Azure PipelinesのYAMLでiOSアプリのCI/CD環境を構築する」は3部構成です。
記事を順番に読み進めると、Azure PipelinesでiOSアプリのCI/CD環境が構築できるようになります。
- 第一部:CI環境の構築
- 第二部:App Center配布パイプラインの構築 ←イマココ
- 第三部:TestFlight配布パイプラインの構築
はじめに
Azure Pipelinesを使い、iOSアプリをApp Centerへ配布するCDを構築します。
本記事で説明しないこと
- Azure Pipelinesの概要や基本的な操作方法
私が以前書いた記事が参考になると思います - Visual Studio App Centerの概要や基本的な操作方法
-
CI環境の構築で説明した内容
以前説明した内容を説明するのは冗長なのでしません
App Centerのコネクションを追加
Azure DevOpsのプロジェクトに、App Centerを接続します。
Azure DevOps > Project Settings > Pipelines - Service connections > 「New service connection」をクリック
以下のURLからでもアクセスできる
https://dev.azure.com/{Organization}/{Project}/_settings/adminservices
「Visual Studio App Center」を選択し、「Next」をクリック
API TokenにApp CenterのAPIトークン、Service connection nameに「App Center」など適当な名前を入力し、「save」をクリック
スクリーンショットを撮るのが手間だったので、API Tokenの発行方法とサービスの追加方法は記載できていません。
以下の記事が参考になるので、こちらに沿って行ってください。
https://qiita.com/gremito/items/08d44b5e18afe05910a5
これでApp Centerの接続は完了です。
証明書とProvisioning Profileのアップロード
証明書とProvisioning ProfileをAzure Pipelines内の安全な場所へアップロードします。
Azure DevOps > Pipelines > Library > [Secure files]タブ > 「+ Secure file」をクリック
これをファイル数分繰り返せば、証明書とProvisioning Profileのアップロードは完了です。
P12ファイルのパスワードの追加
P12ファイルのパスワードをAzure Pipelinesの安全な場所で保持します。
まず変数のグループを作成し、その中に変数を追加します。
Azure DevOps > Pipelines > Library > [Variable group]タブ > 「+ Variable group」をクリック
Variable group nameに適当な名前を入力し、VariablesにP12ファイルのパスワードを追加し、「Save」をクリック
パスワードの変数名は適当な名前でOKです。
Standardのみ契約している場合、単純に P12Password
でいいと思います。
これでP12ファイルのパスワードの追加は完了です。
Makefileの作成
アーカイブやIPAファイルの作成などの実行コマンドをまとめたMakefileを作成します。
CI環境の構築で紹介したコマンドは省略します。
Makefile
例はAd Hocなので、In-Houseの場合は変数名などを適当に修正してください。
DEVELOPMENT_TEAM
、 PRODUCT_BUNDLE_IDENTIFIER
、 ADHOC_PROVISIONING_PROFILE_SPECIFIER
は自分のプロジェクトの値に置き換えてください。
ADHOC_EXPORT_OPTIONS_PATH := ./ExportOptions/ExportOptionsAdHoc.plist
としているので、このパスに.plistファイルを配置してください。
Xcode上からアーカイブ→エクスポートすると.plistが生成されるので、それをそのまま使うのがオススメです。
SDK := iphoneos
CONFIGURATION := Release
ARCHIVE_PATH := ./build/${PRODUCT_NAME}.xcarchive
EXPORT_PATH := ./output/${SDK}/${CONFIGURATION}
XCODEBUILD_ARCHIVE_LOG_NAME := xcodebuild_archive.log
XCODEBUILD_EXPORT_ARCHIVE_LOG_NAME := xcodebuild_exportArchive.log
DEVELOPMENT_TEAM := XXXXXXXXXX
PRODUCT_BUNDLE_IDENTIFIER := com.example.Foo
ADHOC_PROVISIONING_PROFILE_SPECIFIER := Foo_AdHoc
ADHOC_EXPORT_OPTIONS_PATH := ./ExportOptions/ExportOptionsAdHoc.plist
.PHONY: generate-ipa-adhoc
generate-ipa-adhoc: # Generate IPA file for Ad Hoc
$(MAKE) archive-adhoc
$(MAKE) export-archive-adhoc
.PHONY: archive-adhoc
archive-adhoc:
$(MAKE) archive PROVISIONING_PROFILE_SPECIFIER=${ADHOC_PROVISIONING_PROFILE_SPECIFIER}
.PHONY: export-archive-adhoc
export-archive-adhoc:
$(MAKE) export-archive EXPORT_OPTIONS_PATH=${ADHOC_EXPORT_OPTIONS_PATH}
.PHONY: archive
archive:
set -o pipefail && \
xcodebuild \
-sdk ${SDK} \
-configuration ${CONFIGURATION} \
-project ${PROJECT_NAME} \
-scheme ${SCHEME_NAME} \
-archivePath ${ARCHIVE_PATH} \
CODE_SIGN_STYLE=Manual \
CODE_SIGN_IDENTITY="iPhone Distribution" \
PROVISIONING_PROFILE_SPECIFIER=${PROVISIONING_PROFILE_SPECIFIER} \
DEVELOPMENT_TEAM=${DEVELOPMENT_TEAM} \
PRODUCT_BUNDLE_IDENTIFIER=${PRODUCT_BUNDLE_IDENTIFIER} \
clean archive \
| tee ./${XCODEBUILD_ARCHIVE_LOG_NAME} \
| bundle exec xcpretty --color
.PHONY: export-archive
export-archive:
set -o pipefail && \
xcodebuild \
-exportArchive \
-archivePath ${ARCHIVE_PATH} \
-exportPath ${EXPORT_PATH} \
-exportOptionsPlist ${EXPORT_OPTIONS_PATH} \
| tee ./${XCODEBUILD_EXPORT_ARCHIVE_LOG_NAME} \
| bundle exec xcpretty --color
アーカイブ時に CODE_SIGN_STYLE=Manual
を指定し、手動で署名しているのがポイントです。
これにより、開発時に自動署名していても確実に署名できます。
今回のMakefileは、本記事で使うコマンドのみを抜粋および編集して紹介しています。
私が普段使っているMakefileの全容はこちらにあるので、よかったら参考にしてください。
設定ファイルの構成
CI環境の構築で紹介したので省略します。
各項目の紹介
各項目を上から順に紹介します。
name
CI環境の構築と同様なので省略します。
trigger
私は手動でApp Centerへ配布したいため、トリガーをOFFにしています。
trigger: none
pool
CI環境の構築と同様なので省略します。
variables
先ほど追加した変数を使うには、変数グループを明記する必要があります。
変数グループと変数を同時に指定する場合、変数は name
・ value
で定義しなければいけません。
variables:
- group: Foo-iOS
- name: DEVELOPER_DIR
value: '/Applications/Xcode_12.4.app/Contents/Developer'
- name: MINT_PATH
value: 'mint/lib'
- name: MINT_LINK_PATH
value: 'mint/bin'
variables:
DEVELOPER_DIR: '/Applications/Xcode_12.4.app/Contents/Developer'
MINT_PATH: 'mint/lib'
MINT_LINK_PATH: 'mint/bin'
- group: Foo-iOS
steps
パイプライン内のステップを1つずつ紹介します。
ライブラリのインストールなど、CI環境の構築と同様のステップは省略します。
証明書のインストール
証明書をインストールします。
標準で用意されているタスクを使います。
certSecureFile
にP12ファイルの名前、 certPwd
に先ほど追加したP12ファイルのパスワードの変数を指定します。
- task: InstallAppleCertificate@2
inputs:
certSecureFile: 'Certificate.p12'
certPwd: $(P12Password)
keychain: 'temp'
Provisioning Profileのインストール
Provisioning Profileをインストールします。
証明書のインストールと同様、標準で用意されているタスクを使います。
provProfileSecureFile
にProvisioning Profileの名前を指定します。
- task: InstallAppleProvisioningProfile@1
inputs:
provisioningProfileLocation: 'secureFiles'
provProfileSecureFile: 'Foo_AdHoc.mobileprovision'
IPAファイルの作成
IPAファイルを作成します。
- script: make generate-ipa-adhoc
displayName: Generate IPA file for Ad Hoc
アーティファクトのステージングへコピー
配布に問題があった場合に調査するため、生ログとアーカイブ、IPAファイルをダウンロードできるようにします。
そのためには「ステージングへコピー→アップロード」と2つのタスクを実行します。
- task: CopyFiles@2
inputs:
Contents: |
**/xcodebuild_*.log
**/*.xcarchive/**/*
**/output/iphoneos/Release/*
TargetFolder: '$(Build.ArtifactStagingDirectory)'
Contents
では、Makefileで定義した生ログと ARCHIVE_PATH
、 EXPORT_PATH
をワイルドカードで指定しています。
.xcarchiveファイルはフォルダ扱いのため、末尾を **/*
としています。
アーティファクトへアップロード
直前のタスクでステージングへコピーしたので、本タスクでアップロードします。
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
これにより、パイプラインの実行結果からアーカイブとIPAファイルがダウンロードできるようになります。
App Centerへ配布
作成したIPAファイルをApp Centerへ配布します。
serverEndpoint
は先ほど追加したコネクションの名前を指定します。
appSlug
は自分のApp Centerの値に置き換えてください。
releaseNotesInput
はテストアプリの配布なのでいろいろな情報を表示しています。必要に応じて変更してください。
最後の $(ReleaseNote)
はパイプラインの手動実行時に値を入れることで、リリースノートを書けるようにしています。
- task: AppCenterDistribute@3
inputs:
serverEndpoint: 'App Center'
appSlug: '{Organization}/{App}'
appFile: '**/*.ipa'
releaseNotesOption: 'input'
releaseNotesInput: |
- Environment: 'Ad Hoc'
- Configuration: Release
- Certificate: $(APPLE_CERTIFICATE_SIGNING_IDENTITY)
- Provisioning Profile: $(APPLE_PROV_PROFILE_UUID)
- Build ID: $(Build.BuildId)
- Build Number: $(Build.BuildNumber)
- Reason: $(Build.Reason)
- Requested For: $(Build.RequestedFor)
- Source Branch: $(Build.SourceBranch)
- Last Commit ID: $(Build.SourceVersion)
- Last Commit Comment: $(Build.SourceVersionMessage)
- Release Note: $(ReleaseNote)
destinationType: 'groups'
設定ファイルの全体図
最後に設定ファイルの全体図を載せます。
name: $(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
trigger: none
pool:
vmImage: 'macos-latest'
variables:
- group: Foo-iOS
- name: DEVELOPER_DIR
value: '/Applications/Xcode_12.4.app/Contents/Developer'
- name: MINT_PATH
value: 'mint/lib'
- name: MINT_LINK_PATH
value: 'mint/bin'
steps:
# Xcodeのバージョン出力
- script: xcodebuild -version
displayName: Show Xcode version
# Makeのバージョン出力
- script: make --version
displayName: Show Make version
# Bundlerで管理しているライブラリのインストール
- script: make install-bundler
displayName: Bundle install
# Mintのインストール
- script: brew install mint
displayName: Install Mint
# ライセンス情報の生成
- script: make generate-licenses
displayName: Generate licenses
# プロジェクトファイルの生成
- script: make generate-xcodeproj
displayName: Generate Xcode project
# 証明書のインストール
- task: InstallAppleCertificate@2
inputs:
certSecureFile: 'Certificate.p12'
certPwd: $(P12Password)
keychain: 'temp'
# Provisioning Profileのインストール
- task: InstallAppleProvisioningProfile@1
inputs:
provisioningProfileLocation: 'secureFiles'
provProfileSecureFile: 'Foo_AdHoc.mobileprovision'
# IPAファイルの生成
- script: make generate-ipa-adhoc
displayName: Generate IPA file for Ad Hoc
# アーティファクトのステージングへコピー
- task: CopyFiles@2
inputs:
Contents: |
**/xcodebuild_*.log
**/*.xcarchive/**/*
**/output/iphoneos/Release/*
TargetFolder: '$(Build.ArtifactStagingDirectory)'
# アーティファクトへアップロード
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
# App Centerへ配布
- task: AppCenterDistribute@3
inputs:
serverEndpoint: 'App Center'
appSlug: '{Organization}/{App}'
appFile: '**/*.ipa'
releaseNotesOption: 'input'
releaseNotesInput: |
- Environment: 'Ad Hoc'
- Configuration: Release
- Certificate: $(APPLE_CERTIFICATE_SIGNING_IDENTITY)
- Provisioning Profile: $(APPLE_PROV_PROFILE_UUID)
- Build ID: $(Build.BuildId)
- Build Number: $(Build.BuildNumber)
- Reason: $(Build.Reason)
- Requested For: $(Build.RequestedFor)
- Source Branch: $(Build.SourceBranch)
- Last Commit ID: $(Build.SourceVersion)
- Last Commit Comment: $(Build.SourceVersionMessage)
- Release Note: $(ReleaseNote)
destinationType: 'groups'
おわりに
Azure PipelinesのYAMLでiOSアプリをApp Centerへ配布することができました!
fastlaneを使えばもう少しかんたんに実現できそうですが、知識不足なのでできませんでした…。