[.NET MAUI] GitHub Actionsで自動ビルド(Mac Catalyst編)
GitHub Actionsを利用すると、ソースをリモートリポジトリにpushしたタイミングとかでクラウド上の仮想マシンを使って自動ビルドすることができる。いわゆるCI(継続的インテグレーション)。
Microsoft Azureでもほぼ同じことができるはず。
参考となる記事
これが一番わかりやすくて参考になった。Part ⅡのiOS編、Part ⅢのAndroid編もあり。
Apple Development証明書の準備
ストアでの公開などは抜きにして、ひとまずビルド〜発行までなら「Apple Development」の証明書があれば良い。
[.NET MAUI] iPhone実機デバッグをやっていれば、VSforMacの [ユーザー設定] > [公開処理中] > [Apple Developer のアカウント] > [詳細の表示...] と辿ると、証明書の一覧に [Apple Development: Created via API] が表示されているはず。これに対応する証明書のファイルをエクスポートする。
手順は、まず Apple Developerにログインし、[アカウント] > [プログラムのリソース] > [証明書] と辿る。すると、証明書の一覧に [Created via API] がいるので、これを選択して [Download] する。ダウンロードした [development.cer] をダブルクリックしてmacOSへインストールするとキーチェーンアクセスの [自分の証明書] に [Apple Development: Created via API (...)]が追加される。これを右クリックして [...を書き出す] して .p12ファイル形式で保管する。その際に設定したパスワードの値も大切に保管すること。
.p12ファイルの証明書はGitHub Actionsでpublishする際に必要となるが、GitHub上にそのままファイルを置くことはできないので、BASE64で文字列化してGItHubのsecretとして隠蔽する。BASE64文字列化はzshなら下記コマンドでクリップボードにコピーできる。
$ base64 -i xxx.p12 | pbcopy
GitHub sercretの追加
ここからはGitHub上での作業となる。.NET MAUIのソースを管理しているリポジトリの [Settings] > [Secrets and variables] > [Actions] と辿り、[New repository secret] で以下2つのsecretを追加する。
-
CERTIFICATES_P12
… .p12ファイルをBASE64文字列化した値 -
CERTIFICATES_P12_PASSWORD
… 証明書を書き出した際のパスワード
GitHub Actions の作成
ここからはいよいよGitHub Actions の作成に取り掛かる。
リポジトリの [Actions] より[New workflow] > [set up a workflow yourself] と辿り、[CI_mac.yml] という名前でYAMLファイルを作成する。
name: CI_mac
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:
on:
はActionsが実行されるタイミングで、mainブランチへのpushあるいはpull request、workflow_dispatch(手動実行)でのいずれかとする。
env:
DOTNET_VERSION: 8.0.100
TARGET_FRAMEWORK: net8.0-MacCatalyst
PROJECT_FILE: xxx.csproj
あとで使用する環境変数を定義しておく。
jobs:
Build_mac:
runs-on: macos-13
ジョブにBuild_mac
と名付けてGitHubのmacOS 13のジョブランナーでジョブを実行する。2024年2月時点では macos-latest
としても macOS 13 となるはず。
steps:
- name: Show Xcode version
shell: bash
run: xcodebuild -version
- name: List Xcode installations
run: sudo ls -1 /Applications | grep "Xcode"
- name: Select Xcode 15.1
run: sudo xcode-select -s /Applications/Xcode_15.1.app/Contents/Developer
ここからはジョブの個々のステップ。run:
によりシェルスクリプトを実行する。2024年2月現時点ではmacOS 13ジョブランナーのXcodeのバージョンは15.0.1であるが、念のためローカルの開発環境と合わせるためXcode 15.1に変更する。
- name: Checkout
uses: actions/checkout@v4
uses:
により既製のアクションactions/checkout
を使用し、ソースコードをリポジトリからcheckoutしてジョブランナー上に配置する。
- name: Setup .NET SDK ${{ env.DOTNET_VERSION }}
uses: actions/setup-dotnet@v2
with:
dotnet-version: '${{ env.DOTNET_VERSION }}'
- name: List .NET info
run: dotnet --info
2024年2月現時点ではmacOS 13ジョブランナーに.NET 8.0.100が入っているため無駄ではあるが actions/setup-dotnet
を使って指定バージョンの.NETをセットアップすることができる。
- name: Install .NET MAUI
shell: bash
run: |
dotnet workload install maui
macOS 13ジョブランナーには.NET MAUIワークロードが入っていないためインストールする。アクションを実行するとわかるが、これに2〜3分かかる。
- name: Restore packages
run: |
dotnet restore ./${{ env.PROJECT_FILE }}
- name: Build
run: |
dotnet build ./${{ env.PROJECT_FILE }} -c Debug -f ${{ env.TARGET_FRAMEWORK }}
- name: Test
run: |
dotnet test ./${{ env.PROJECT_FILE }} --no-build --verbosity normal
プロジェクトのリストア、デバッグビルド、テストを実行。
- name: Import certificates
uses: apple-actions/import-codesign-certs@v2
with:
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
次の公開(publish)時の署名に必要となる証明書をテンポラリなキーチェーンにインポートする。ここで事前準備しておいたsecretが使われる。証明書インポートせずにpublishしようとすると no valid code signing key
で怒られる。
- name: Publish
run: |
dotnet publish ./${{ env.PROJECT_FILE }} -c Release -f ${{ env.TARGET_FRAMEWORK }} -p:CreatePackage=false -p:EnableAssemblyILStripping=false
いよいよ発行。-p:CreatePackage=false
で.pkg形式のインストーラーは生成せずに.app形式のままとする。-p:EnableAssemblyILStripping=false
はよくわからん。
- name: Upload
uses: actions/upload-artifact@v3
with:
name: artifact-mac
path: |
./bin/Release/${{ env.TARGET_FRAMEWORK }}/maccatalyst-arm64/*.app
発行した.appファイルを成果物(artifact)としてあとで取り出せるようにジョブランナーからGitHubの公開ストレージにアップロードする。
ワークフローの実行
GitHubのWeb上でYAMLを編集して保存、またはローカルで編集してcommit〜pushするとワークフローが実行される。
Webブラウザ上でワークフロー実行状況がリアルタイムで出力されるさまは圧巻だ。無事ワークフロー実行が成功してワークフローのrun(実行結果)ページの artifact-mac
のリンクから.appファイルをダウンロードしてローカルで実行したところ、「実行できません」というエラーとなった。
Mac Catalystであれば未署名のアプリも実行可能かと思ったが違ったか?公式サイトの解説をもう一度みてみる。