LoginSignup
9
3

More than 1 year has passed since last update.

GitHub Actions Macアプリのビルド方法+リリースの自動化方法

Last updated at Posted at 2021-09-06

Macアプリのリリース手順が煩わしかったので、GitHub Actionsを利用してリリースを自動化しました。 その際の知見(Q&A)と実際の構成を共有します。

Q&A

Q: fastlane, bundlerはデフォルトで利用できる?

利用できる。(bundle installをしなくてもfastlane利用可能。)

Q: passwordやp12ファイルなど機密情報はどのように扱う?

暗号化されたシークレット参照

この資料にパスワードやp12ファイルなどの機密情報の設定方法およびワークフローファイルからの参照方法について記載されています。(以下は抜粋)

シークレットの設定方法(リポジトリ単位)

スクリーンショット 2021-09-06 15.44.41.png

ワークフローファイルからのシークレットの参照方法

スクリーンショット 2021-09-06 10.55.58.png

Q: workflowは手動起動できる?

できる。 パラメータも設定可能。
手動起動の際にbranchの指定も可能。

設定例

on:
  # Workflowの手動起動の設定です。
  # version_numberを入力できるようにしています。
  workflow_dispatch:
    inputs: 
      version_number: 
        description: 'アプリのバージョン番号。入力例 0.3.0, 1.0.0 など。'
        required: true

# 中略

#version_numberの参照方法
bundle exec fastlane release version_number:${{ github.event.inputs.version_number }}

上の定義をすると、workflowの起動画面は下のようになります。

スクリーンショット 2021-09-06 16.44.31.png

また手動起動のほか、pullreqのタイミングやbranchがpush時などに自動起動が可能です。

ワークフローをトリガーするイベント
同資料中のworkflow_dispatch
GitHub Actionsのメタデータ構文

Q: actions/checkout@v2 でcheckoutされるブランチは?

デフォルトではworkflowを実行したブランチ

actions/checkout

Q: ワークフローファイルの環境変数とコンテキストの違いは?

以下の通り

スクリーンショット 2021-09-06 10.50.43.png

環境変数

Q: git tagの作成の仕方は?

一例

      - name: Create git tag
        run: |
          git tag v${{github.event.inputs.version_number}}
          git push origin v${{github.event.inputs.version_number}}

Q: GitHubのリリースページの作成の仕方は?

一例

※ actions/create-release@v1はarchivedされていてメンテナンスされていない。

      - name: Create release    
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
        with:
          tag_name: v${{github.event.inputs.version_number}}
          release_name: Release v${{github.event.inputs.version_number}}
          body: |
            Changes in this Release
            - First Change
            - Second Change
          draft: true
          prerelease: false

actions/create-release

Q: GitHubのリリースページにzipファイルなどの成果物をアップロードするには

下の例は、action/create-release@v1を前提としている。

      - name: Upload Release Assets
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./build/DokodemoDrag.app.zip
          asset_name: DokodemoDrag.app.zip
          asset_content_type: application/zip          

actions/upload-release-asset

Q: on: workflow_dispatchを設定しても, Actionsタブでワークフローが表示されない。

私の場合、GitHubから直接.github/workflow/aaa.yamlファイルを作成した場合に上の事象が発生しています。
(mainブランチ以外にワークフローファイルを作成すると表示されないかもしれない)
結構表示されないケースがある模様。

Q: expression中での三項演算子的なものは?

${{ val1 ? val1 : "B" }}

的なことをしたい。

ドキュメント的には見当たらない。

動作検証の限りでは、||と&&はRubyやJavaScriptと同様の動作をするので、

${{ val1 || "B" }} # val1の値が偽になるなら"B"を返す.

${{ (val1 && val2) || "B" }} # val1 && val2が偽でなければval2を返し、 偽なら"B"を返す。

といったことができる。

下記は実際の利用イメージ

- name: 'Test'
  env: 
    # github.event.inputs.version_nameは 1.0.0などを想定
    TAG_NAME: v${{ github.event.inputs.version_name }}
  run: |
         # 式の結果が偽なら""を出力する。真なら v1.0.0などを返す。
    echo ${{ (github.event.inputs.version_name && env.TAG_NAME) }} 

Q: ${{expression}}の評価がいまいち分からない

別記事を作成しました。

Q: GitHub Actionsの完了時のメール通知を止めたい

Account Settings -> Notifications -> Actionsのセクションから設定を変更できる。

宣伝(DokodemoDragについて)

DokodemoDragは、個人的に作成中のアプリでMacのWindow移動を楽に行えるようにするツールです。よければ触ってみてください

※現時点ではnotarizationができておらず、macOSのGateKeeperに検出されます)。

image01.gif

実装の概要もこちらで公開しています。
https://zenn.dev/hmu/articles/4c17afaaf5012e

宣伝は以上で、以下は実際に自動化したGitHub Actionsの構成についてです。

実際のworkflowの構成

前提

  • GitHubのランナー上のXcode versionは12.4
  • プロジェクトの構成はworkspace下にprojectが2つ存在する
DokodemoDrag.xcworkspace/
|-DokodemoDrag.xcodeproj/
|-DokodemoDragLauncher/DokodemoDragLauncher.xcodeproj/
  • リリース形式は、GitHub上のリリースページにappname.app.zipという形式で公開(Storeへの公開ではない)
  • リリース対象のMac AppのCertificateは、Developer IdではなくDevelopmentを利用
  • 証明書のimportにmatchは利用せず手動で行う
  • プロジェクトのビルドにはfastlaneを利用する
  • 現時点ではprovisioning profileは未使用
  • 現時点ではfastlaneの設定はGitHub Actionsでの利用前提となってしまっています

ワークフローの概要

1.ワークフローは実行者が手動で起動する
スクリーンショット 2021-09-06 16.44.31.png
2.アプリのバージョンはWorkflow起動時に指定する
3.ビルド時にワークフロー起動時に指定されたバージョン番号を付与する
4.ビルドに成功したら バージョンに対応するgitのtagを生成する
5.GitHubのリリースページをドラフトで作成する
6.後始末

workflowファイル

説明は直接コメントに記載しました。

release.yml

name: Release app

on:
  # Allows you to run this workflow manually from the Actions tab
  # Workflowの手動起動の設定です。
  # version_numberを入力できるようにしています。
  workflow_dispatch:
    inputs: 
      version_number: 
        description: 'アプリのバージョン番号。入力例 0.3.0, 1.0.0 など。'
        required: true

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  release:
    # 実行環境をmacに設定。
    runs-on: macos-latest

    steps:
      - name: Show Xcode version
        run: xcodebuild -version    

      # defaultでWorkflowを実行したbranchがcheckoutされる。
      - uses: actions/checkout@v2

      - name: Show Git Branch
        run: git symbolic-ref --short HEAD

      # https://docs.github.com/ja/actions/guides/installing-an-apple-certificate-on-macos-runners-for-xcode-development
      # 上記のドキュメントにcertificateをGitHub Actionsのランナーにimport
      # する方法が記載されています。
      # 下の設定では、GitHubのsecretに設定したp12ファイルの内容を復元しています。
      # 実際のcertificateのkeychainへのimportは、fastlaneで行っています。
      - name: Generate p12 file
        env:
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
        # 以下で定義しているP12_PATHは、${{ runner.temp }}を利用することで、
        # env: 内で定義可能かもしれません。(未検証)
        run: |
          P12_PATH=$RUNNER_TEMP/build_certificate.p12
          echo $P12_PATH
          # シークレットから証明書とプロビジョニングプロファイルをインポートする
          echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $P12_PATH

      # commitに利用する情報を設定しています。     
      - name: git config
        run: |
          echo github.actor: ${{github.actor}}
          git config user.name ${{github.actor}}

      # fastlaneをbundle execで利用するためにbundlerを利用しています。
      - name: bundle install
        run: |
          bundle install

      # アプリのビルド処理です。
      - name: Build DokodemoDragLauncher & DokodemoDrag
        # ここもP12_PATHは ${{ runner.temp }} を利用した方が良いかもしれません。
        env:
          # これらの環境変数はfastlaneの処理で利用します。
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          export P12_PATH=$RUNNER_TEMP/build_certificate.p12
          echo $P12_PATH
          # certificateのimport, アプリのビルド, 成果物用のzipファイル生成を行います。
          bundle exec fastlane release version_number:${{github.event.inputs.version_number}}
          # .はかなり雑かもしれません。 
          git add .
          git commit -m "Release v${{github.event.inputs.version_number}}"
          git push origin

      # タグ付けをします。    
      - name: Create git tag
        run: |
          echo Create tag ${{github.event.inputs.version_number}}
          git tag v${{github.event.inputs.version_number}}
          git push origin v${{github.event.inputs.version_number}}

      # GitHubのリリースページを作成します。(draftで作成します)
      # actions/create-release@v1は既にメンテ終了しているので、
      # 他のアクションを利用した方が良いです。
      - name: Create release    
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
        with:
          tag_name: v${{github.event.inputs.version_number}}
          release_name: Release v${{github.event.inputs.version_number}}
          body: |
            Changes in this Release
            - First Change
            - Second Change
          draft: true
          prerelease: false

      # リリースページに成果物のzipファイルをアップロードします。          
      - name: Upload Release Assets
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./build/DokodemoDrag.app.zip
          asset_name: DokodemoDrag.app.zip
          asset_content_type: application/zip          

fastfile

こちらも説明は直接コメントに記載しました。

fastfile

default_platform(:mac)

XCODE_PROJ_PATH = %w(./DokodemoDragLauncher/DokodemoDragLauncher.xcodeproj ./DokodemoDrag.xcodeproj)
BUILD_PATH="build"
APP_NAME="DokodemoDrag.app"
KEYCHAIN_NAME="map_app_keychain" # macのtypo...
OUTPUT_PATH="build"

platform :mac do

  after_all do |lane|
    # GitHubホストランナーの場合は不要です。
    # create_keychainが呼ばれずにdelete_keychainを呼ぶと
    # エラーになってしまいます。
    delete_keychain(name: KEYCHAIN_NAME)
  end

  error do |lane|
    # GitHubホストランナーの場合は不要です。
    # create_keychainが呼ばれずにdelete_keychainを呼ぶと
    # エラーになってしまいます。
    delete_keychain(name: KEYCHAIN_NAME)
  end

  desc "release. option version: 0.3.0 ..."
  lane :release do |options|
      # プロジェクトにversion_numberを設定します。
      set_version_number(
        version_number: options[:version_number]
      )

      increment_all_app_build_numbers

      build
  end


  desc "set version number"
  lane :set_version_number do |options|
    # increment_version_numberだと主のschemeに対してのみ
    # 実行されるようなので、プロジェクト毎に設定しています。
    XCODE_PROJ_PATH.each do |path|
      increment_version_number(
        xcodeproj: "#{path}",
        version_number: options[:version_number]
      )
    end
  end

  desc "increment all app's build_numbers"
  lane :increment_all_app_build_numbers do
    # increment_xxx_numberだと主のschemeに対してのみ
    # 実行されるようなので、プロジェクト毎に設定しています。
    XCODE_PROJ_PATH.each do |path|
      increment_build_number(
        xcodeproj: "#{path}"
      )
    end
  end

  desc "build and zip app-file"
  lane :build do
    # certificateをimportしています。
    # ここはciの時のみ実行するなど分岐があったほうが良さそうです。
    import_my_certificate

    build_mac_app(
      workspace: "DokodemoDrag.xcworkspace",
      configuration: "Release",
      scheme: "DokodemoDrag",
      export_method: "development",
      clean: true,
      output_directory: BUILD_PATH,
      skip_package_pkg: true,
      output_name: APP_NAME
    )

    zip(
      path: "#{BUILD_PATH}/#{APP_NAME}",
      output_path: "#{OUTPUT_PATH}/#{APP_NAME}.zip"
    )

  end

  # ワークフローファイル側で設定しても問題ないと思いますが、fastlaneで設定しています。 
  # 参考: https://note.com/hayabusabusa/n/nbf4a1a095bf5
  private_lane :import_my_certificate do
    create_keychain(
      name: KEYCHAIN_NAME,
      password: ENV["KEYCHAIN_PASSWORD"],
      timeout: 1800
    )
    import_certificate(
      certificate_path: ENV["P12_PATH"],
      certificate_password: ENV["P12_PASSWORD"],
      keychain_name: KEYCHAIN_NAME,
      keychain_password: ENV["KEYCHAIN_PASSWORD"]
    )
  end  
end

参考資料

fastfileとワークフローファイルを作成時に参考したページです。
上の内容と一部重複しています。

GitHub Actions

GitHub Actionsについて学ぶ
GitHub Actionsの概要を把握するために一読をお勧めします。


Xcode 開発用の macOS ランナーに Apple 証明書をインストールする

Github Actions上でCertificateのインストールする手順が記載されています。

今回はp12ファイルをGithub Actions上で生成するところを参考にし、keychainへの証明書のimportは、fastlaneを利用しています。


GitHub Actionsのメタデータ構文

アクションの入力パラメータの設定方法等が記載されています。
今回はworkflowを手動実行する際入力パラメータの設定の参考にしています。


GitHub Actionsのワークフロー構文

GitHub Actionsのworkflowのyamlファイルのリファレンスです。


ワークフローをトリガーするイベント

pullreqのタイミングやbranchがpushされた時などをtriggerとしてworkflowを起動できます。

手動でworkflowを実行する設定(on: workflow_dispatch)も記載されています。


環境変数

GitHub Actionsで利用可能な環境変数についての説明。
ワークフローの定義ファイル中には環境変数とコンテキストの2種類の変数がありますが、その違いについても
記載されています。

スクリーンショット 2021-09-06 10.50.43.png


暗号化されたシークレット

パスワードやp12ファイルなどの機密情報の設定方法およびワークフローファイルからの参照方法について記載されています。

シークレットの設定方法(リポジトリ単位)

スクリーンショット 2021-09-06 15.44.41.png

ワークフローファイいるからのシークレットの参照方法

スクリーンショット 2021-09-06 10.55.58.png


セルフホストランナーについて

通常ワークフローは、GitHub管理下で実行されますが、独自のワークフローのランナー環境が構築できるようです。

ドキュメント内では、GitHub管理下のランナーをGitHubホストランナー、独自のランナーをセルフホストランナーと表記されています。

スクリーンショット 2021-09-06 11.09.15.png


Action

actions/checkout

Gitのリポジトリをcheckoutするアクション。
デフォルトでは、workflowを実行したbranchを参照するようです。


actions/create-release

GitHubのreleaseページを作成するために利用したのですが、
このリポジトリはarchivedされていてメンテナンスされていない模様。


actions/upload-release-asset

GitHubのリリースページに成果物をアップロードするアクションです。


Fastlane

increment_build_number

increment_build_numberは、デフォルトだと1projectにしか適用されないので

increment_build_number(
  build_number: 75, # specify specific build number (optional, omitting it increments by one)
  xcodeproj: "./path/to/MyApp.xcodeproj" # (optional, you must specify the path to your main Xcode project if it is not in the project root directory)
)

のようにxcodeprojを明示しています。


increment_version_number

workflow実行時に入力したバージョンを設定しています。
increment_version_numberは、デフォルトだと1projectのみ適用なので、全プロジェクトに
適用するようにしています。


create_keychain


delete_keychain

今回の設定では、お行儀よくfastlaneの最後にkeychainを削除しました。
GitHubホストランナー上で実行する場合、この設定は不要です。

参考:Xcode 開発用の macOS ランナーに Apple 証明書をインストールする

スクリーンショット 2021-09-06 11.11.51.png


Technical Q&A QA1827
Automating Version and Build Numbers Using agvtool

Github Actionsとは直接関係ありませんが、fastlaneのincrement_build_no, increment_version_numberは、Appleが提供しているagvtoolに依存しています。
またそのための設定をXcode のプロジェクトに行う必要があるため、その手順が記載されています。

注意点として、同一ディレクトリにxcodeprojが複数あるとagvtoolは動作しません。

(私の場合、過去にproject名をリネームしていてその残骸のxcodeprojが残っていたため、知らぬ間に同一ディレクトリに複数のxcodeprojが存在していて、agvtoolが実行できないというポカをしていました)

先人の知見

GitHub ActionsでReleaseを自動化する方法としたときに得た学び

Github Actions と fastlane で iOS アプリをアーカイブしてビルドを提出する

Github ActionsでiOSアプリのデプロイを自動化する


以上です。分かってしまえば1つ1つの設定は単純ですが、Actionsのデバッグに想像以上の時間がかかりました。 デバッグ時にはワークフロー中のcommitを省略するなどの仕組みが必要だったなぁとか、キャッシュは先に有効にしておくべきだったとか...改善の余地は多々あります。

9
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
3