🪄

【日本語訳+Tips】Codemagic.yaml チートシート

2023/11/04に公開

この記事は、Codemagicの公式ドキュメントである Codemagic.yaml cheatsheet の日本語訳です。正確な情報は Using codemagic.yaml - Codemagic を参照ください。

Codemagicとは

Codemagicとは、Flutterのビルドとテスト、デプロイを自動化するためのCI/CDツールです。
Flutterだけでなく、React Native、iOS、およびAndroidのプロジェクトをサポートしています。
類似サービスに Bitrise があります。

価格はフリープランからチーム、エンタープライズが用意されています。(2023年11月時点)
フリープラン: 月に500分まで、ビルドは1つまで同時実行可能。
チームプラン: 従量課金(macOS M1 $0.095/min)、ビルドは3つまで同時実行可能。

基本的にはWeb上からビルドプロセスの要素 (たとえば、使用するFlutterのバージョン、ビルドするターゲット、環境変数など) をポチポチと設定することで、コードを書かずにビルド設定を作成できます。

しかし、高度な設定や細かいカスタマイズが必要となるケースでは、そのような要件を満たすために codemagic.yaml ファイルに設定を記述し、コードと共にバージョン管理することができます。

Codemagic.yaml チートシート

以下、日本語訳と筆者の補足を含めています。
記述例にはわかりやすくするため若干の変更がある場合があります。

はじめに

このドキュメントは、codemagic.yaml の記述方法に関する早見表です。
全体を知りたい場合は Using codemagic.yaml - Codemagic を参照ください。

構文

ワークフローの最低限の記述は次の通りです。

workflows:
  hello-world-workflow:
    name: Hello world workflow
    scripts:
        - echo "Hello World!"

再利用

異なるワークフロー間で設定を再利用したいことがあると思います。
yamlのトップレベルに definitions というセクションを追加すると、この中で定義した設定は後から登場するセクションから呼び出すことができます。

definitions:
  instance_mac_pro: &instance_mac_pro
    instance_type: mac_pro
    max_build_duration: 120
  env_versions: &env_versions
    flutter: stable
    xcode: latest
    cocoapods: default
  scripts:
    - &add_certs_to_keychain  # 定義側には & をつける
      name: Add certs to keychain
      script: |
         keychain add-certificates

再利用するために、定義されたセクションの前に * を追加します。

workflows:
  ios-release:
    name: iOS release
    <<: *instance_mac_pro
    environment:
      <<: *env_versions
    scripts:
      - *add_certs_to_keychain  # * つけると参照できる

エンコード

base64エンコードを用いて、ファイルの内容をクリップボードにコピーする方法を説明します。

macOS

cat your_file | base64 | pbcopy

Windows

[Convert]::ToBase64String([IO.File]::ReadAllBytes("file.ext")) | \
Set-Clipboard

Linux

sudo apt-get install xclip
cat your_file | \
base64 | \
xclip -selection clipboard

デコード

次のコマンドを使用してbase64をデコードし、その結果をビルド時の環境変数の値として使用できます。

echo $ENV_VAR | base64 --decode > /path/afile

ワークフローの環境変数

グローバルな環境変数

environment:
  groups: # Define your environment variables groups here          
    - keystore_credentials
    - app_store_credentials
    - firebase_credentials

ワークフローのみの変数

ワークフローのみの変数を定義することもできます。

workflows:
  example-workflow:
    environment:
      vars: # ここでこのワークフローしか参照できない環境変数を定義
        PUBLIC_ENV_VAR: "value here"

ソフトウェアのバージョン

ワークフローで使用するソフトウェアのバージョンを指定できます。

environment:
  flutter: stable  # 指定可能な値 [Channel name, version (例: v1.13.4)]
  xcode: latest    # 指定可能な値 [latest, edge, version (例: 11.2)]
  cocoapods: 1.9.1 # 指定可能な値 [default, version]
  node: 12.14.0    # 指定可能な値 [default, latest, current, version]
  npm: 6.13.7      # 指定可能な値 [default, latest, next, lts, version]
  ndk: r21d        # 指定可能な値 [default, ver, build.gradle]
  java: 1.8        # 指定可能な値 [default, platform version (        例: 11)]
  ruby: 2.7.2      # 指定可能な値 [default, version]
environment:
  flutter: fvm

トリガー

自動ビルドのトリガー設定とブランチ監視について説明します。
イベントが設定されていなければ、ビルドは手動でしか開始できません。

任意のブランチにプッシュしたときにトリガーしたい

triggering:
  events:  
    - push
  branch_patterns:
    - pattern: '*'

特定のコミットによってビルドをスキップしたい

特定のコミットをビルドしないためには、コミットメッセージに skip ci または ci skip を含めてください。

dev* ブランチを除外したい

triggering:
  events:  
    - push
  branch_patterns:
    - pattern: '*'  # デフォルトでは include: true
    - pattern: 'dev*'
    - include: false

PRが作成されたときにトリガーしたい

triggering:
  events:  
    - pull_request
  branch_patterns:
    - pattern: '*'

devブランチから任意のブランチへのPR作成時にトリガーしたい

triggering:
  events:  
    - pull_request
  branch_patterns:
    - pattern: 'dev*'
    - source: true  # デフォルトでtrue

devブランチからPRが作成されたときにトリガーしたい(ただしmain以外のブランチ)

triggering:
  events:  
    - pull_request
  Branch_patterns:
    - pattern: 'dev*'
    - source: false
    - pattern: 'master'
    - include: false

devブランチへPRが作成されたときにトリガーしたい

triggering:
  events:  
    - pull_request
  branch_patterns:
    - pattern: 'dev*'
    - source: false # デフォルトはtrue

プッシュまたは任意のブランチから作成されたPRでトリガーし、古いビルドをキャンセルしたい

もし2つのビルドが走るときに、この設定を追加すると古い方のビルドをキャンセルします。

triggering:
  events:  
    - push
    - pull_request
  branch_patterns:
    - pattern: '*'
  cancel_previous_builds: true  # これを追加

同じブランチに対して新しいビルドが開始された場合、それに伴いWebhookからトリガーされた進行中またはキューに入ったビルドを止めることができます。
これにより、古いコミットに基づいて無駄にビルドが走るのを避けることができます。

条件付きビルドトリガー

ファイルが変更されたらトリガーしたい

when 以下の changesetincludesexcludes で、変更で監視するファイルを指定します。
次の例は、すべてのマークダウンファイルのビルドをスキップします。

workflows:
  build-app:
    name: Build App
    triggering:
      events:
        - push
    when:
      changeset:
        includes:
          - '.' # デフォルトは '.'
        excludes:
          - '**/*.md'

特定のパス配下のファイルに変更があったときにトリガーしたい

次の例は iOS/ 配下のファイルが変更されたらトリガーされます。

workflows:
  build-ios:
    name: Build iOS
    triggering:
      events:
        - push
    when:
      changeset:
        includes:
          - 'iOS/'

whenを使って細かく条件を制御する

workflows:
  build:
    name: Build on PR update
    triggering:
      events:
        - pull_request
    when:
      condition: not event.pull_request.draft

スクリプト

複数行のスクリプトを記述したい

scripts:
  - echo "single line script"
  - name: Flutter test
    script: flutter test
    ignore_failure: true
  - | # パイプを使うことで複数行のスクリプトを記述できる
    #!/usr/bin/env python3

    print('Multiline python script')

[筆者追記] スクリプトを再利用したい

ワークフロー間でスクリプトを再利用したいときは次のように記述します。

definitions: 
  scripts:  # definitionsに共通のスクリプトを記述
    - &setup-melos
      name: Setup melos
      script: |
        dart pub global activate melos
        melos bootstrap

workflows:
  workflow-a:
    name: Workflow - A
    scripts:
      - *setup-melos  # このように参照する

...

  workflow-b:
    name: Workflow - B
    scripts:
      - *setup-melos  # このように参照する

ビルドのバージョニング

Flutter

--build-name=1.0.$PROJECT_BUILD_NUMBER \
--build-number=$PROJECT_BUILD_NUMBER

Native iOS

set -e
set -x
cd $CM_BUILD_DIR/ios
agvtool new-version -all $(($BUILD_NUMBER + 1))

App Store から最新のビルド番号を取得する

LATEST_BUILD=$(get-latest-app-store-build-number "$APP_STORE_APPLE_ID")
agvtool new-version -all $(($LATEST_BUILD + 1))

TestFlight から最新のビルド番号を取得する

LATEST_BUILD=$(app-store-connect get-latest-testflight-build-number "$APP_STORE_APPLE_ID")
agvtool new-version -all $(($LATEST_BUILD + 1))

App Store または TestFlight から最新のビルド番号を取得する

LATEST_BUILD=$(app-store-connect get-latest-build-number "$APP_STORE_APPLE_ID")
agvtool new-version -all $(($LATEST_BUILD + 1))

成果物と公開

成果物

成果物としたいファイルは次のように指定できます。相対パスはもちろん、絶対パス指定や環境変数も利用可能です。

artifacts:
  - build/**/outputs/apk/**/*.apk # ルートからの相対パス 
  - subfolder_name/build/**/outputs/apk/**/*.apk
  - build/**/outputs/**/*.aab
  - build/**/outputs/**/mapping.txt
  - build/ios/ipa/*.ipa
  - build/macos/**/*.pkg
  - /tmp/xcodebuild_logs/*.log # 絶対パス
  - flutter_drive.log
  - $HOME/Library/Developer/Xcode/DerivedData/**/Build/**/*.dSYM # 環境変数も利用可能

公開

Codemagicは公開のための多くの方法を持っていますが、カスタムスクリプトを使用してメールでも公開することができます。
公開スクリプトは、ビルド状態に関係なくデフォルトで実行されることに注意してください。if文を使用して追加の条件を指定することができます。

publishing:
  email:
    recipients:
      - name@example.com
  scripts:
    name: Check for apk
    script: |
      apkPath=$(find build -name "*.apk" | head -1)
      if [[ -z ${apkPath} ]]
      then
        echo "No .apk were found"
      else
        echo "Publishing .apk artifacts"
      fi      
publishing:
  slack:
    channel: '#ios_artifacts'

ビルド状態を報告する

scripts:
  - name: Report build start
    script: # build started

    . . .

  - name: Build finished successfully
    script: touch ~/SUCCESS
publishing:
  scripts:
    - name: Report build status
      script: |
        if [ -a "~/SUCCESS" ] ; then
           # build successful
        else
           # build failed
        fi

終わりに

ご覧いただきありがとうございます!以上がCodemagic.yamlのチートシートになります。
次の記事では codemagic.yaml でビルドと公開までの一連の設定を解説したいと思います。

間違い等がありましたらお気軽にお知らせください。

Discussion