nashcft's blog

時々何か書く。

Bitrise: Repository で bitrise.yml を管理している場合の Bitrise Start Build による workflow の並列実行を行う

Bitrise は基本的に1つのトリガーに対して1つの workflow しか実行させられないが、 Bitrise Start Build という step を用いることで、複数の workflow を並列に実行できるようになっている。以下では主に GitHub などの repository で bitrise.yml を管理・運用しながら Bitrise を利用している場合の Bitrise Start Build の導入方法や、実際に私が導入した際の雑感などを書いていく。

事前準備

Bitrise Start Build を実行するには access token が必要で、これは各個人のアカウントで生成する personal access token のことである。なので、適当なアカウントで Account setting -> Security から token を生成し、Workflow Editor の Secrets 適当な名前で登録しておく。

(寄り道) GUI でのセットアップ

今回の主題は repository で管理している bitrise.yml で運用している場合の導入方法についてだが、yaml を書く際のドキュメントは存在しない*1ので、その場合でも先にGUI側でお試し workflow を作ってどのような設定があるか見てみるのが良い。Bitrise Start Build についてもGUI側での設定方法ならば上記の access token についても含めて公式のドキュメントにおおむね書かれている。大雑把に要点を挙げると

  • Bitrise Start Build step を追加
  • 並列実行したい workflow を羅列
  • 用意した access token を登録

という感じ。

また、ドキュメントには記述がないが、実行元の workflow で定義した環境変数を引き継ぐ為の設定 Environments to share というものがあり、これによって1つの workflow に対して実行元 (設定した環境変数の値) に応じて振る舞いを変更する、といったことにも対応可能になっている。

ついでに、 Bitrise Start Build の step の後に他の step を追加して、並列実行した workflow の実行後にそれを動かすようにしたい場合以下の2種類の方法がある。

  • Bitrise Start Build の設定にある Wait for buildstrue にする
  • Bitrise Wait for Build という step を Bitrise Start Build の後に追加する

これらの振る舞いは完全に一緒っぽいのでそのうちどちらかがなくなるのではないか。

Repository でbitrise.yml を管理している場合のセットアップ

bitrise.yml での記述

yaml における Bitrise Start Build の step 名は build-router-start であり、設定など含めると以下のようになる:

  steps:
  # ssh activation, cloning repository, etc...
  - build-router-start:
      inputs:
      - access_token: "$ACCESS_TOKEN"  # 事前準備で用意した access token
      - workflows: |- # 実行する workflow のリスト
          foo
          bar
          baz
      - wait_for_build: false # optional: default false
      - environment_key_list: "$KEY1\n$KEY2" # optional

これでめでたく workflow の並列化が完了... ではない。単に上記の step を追加しただけで実行すると以下のようなエラーで終了してしまう:

Failed to start build, error: failed to get response, statuscode: 400, body: {"status":"error","message":"workflow (foo) did not match any workflows defined in app config","slug":"[REDACTED]","service":"bitrise"}

これはなぜかというと、現在の Bitrise Start Build で実行可能な workflow はGUI側で定義されているもののみだからである。
ここで諦めて大人しくGUI側に workflow の定義を移すこともできるが、折角変更の管理ができるように repository 側で持たせているのだから、その状態を維持したままで並列実行を動かせるようにしたい。とはいえ repository 側の bitrise.yml だけではどうにもできないので、GUI側への最小限の変更で動かせるようにする方法を紹介する。

GUI 側での設定

今の所参考になる解決策は以下の discussion で挙げられている手法かと思われる。

discuss.bitrise.io

要点は以下の3つ:

  • GUI側で、Bitrise Start Build で実行する対象と同名の workflow を定義する
  • 環境変数を用いて、実行するべき workflow を保存しておく
  • bitrise run環境変数で保存していた名前の workflow を実行する

ちなみに上のリンク先の定義は改善の余地があって、自前で WORKFLOW_TO_RUN のような環境変数を用意しなくても、$BITRISE_TRIGGERED_WORKFLOW_ID というデフォルト環境変数があり、同名の workflow を定義しているならこれが使えるので、こちらを使うことで定義をスッキリさせることができる。

  run_from_repo:
    steps:
    - activate-ssh-key: {}
    - git-clone: {}
    - bitrise-run:
        title: continue from repo
        inputs:
        - workflow_id: "$BITRISE_TRIGGERED_WORKFLOW_ID"
  foo:
    after_run:
    - run_from_repo
  bar:
    after_run:
    - run_from_repo
  baz:
    after_run:
    - run_from_repo

この方法を用いる場合の注意点として、bitrise-run で実行した workflow 内の script step で set -e をつけておかないとタスクが失敗したにも関わらずその後の処理も続いて workflow が成功扱いになってしまうみたいなことがあったので共有しておく。

雑感

  • 現時点では Bitrise Start Build はGUI側のみでの workflow 構築しか想定されておらず、repository で bitrise.yml を管理している場合には定義が repository 側とGUI側に散ってしまい嬉しくない。Bitrise 的にはGUI側で全てを完結してほしそうにしているが、 workflow の変更管理がそれだけではできないのでGUIで完結させたいなら早く運用でカバーする以外の管理方法と提供してくれという気持ち。
  • wait: true にしている場合、実行したコンテナの結果を待っている間そのコンテナは占有されたままとなるので、CircleCI と比べるとコンテナが枯渇しやすい。
  • Bitrise では現在 branch 単位でしかキャッシュを持てず、他にコンテナやCIパイプライン間でファイルを共有するすべがないので、たとえ wait: true にしたとしてもそれぞれの workflow の成果物を収集してまとめて何かをするというのはできなさそう。
    • 基本的には build_router_start を実行する workflow はそれのみを step として持ち、自己完結した workflow を並列実行して自身は wait しない、という構成にするのが一番無駄が無い気がする。
    • Danger に色々な仕事をさせていて、成果物の収集は互いに独立しているので並列化したかったのだけど残念...

まあ CircleCI の workflow とかと比べても洗練されてないというか色々足りてないなーという印象だけど、まだリリースされてそれほど時間が経っていないことだし、今後に期待という感じだろうか。

References

*1:Bitrise は基本的にGUI側での設定の仕方しかドキュメントにまとめてくれない