January 19, 2020

iOS・SwiftプロジェクトのCI/CDで、bitrise.ymlをリポジトリ内で管理する

はじめに


普段は、CircleCIをメインで使っていますが、モバイルアプリのCI/CDで流行っているBitriseを少し触ってみて、CircleCIと同じようにリポジトリ内で、設定ファイルを管理したくなったので、その設定方法に関する記事です。

モチベーション


人・文化・サービスによって、bitriseの設定(bitrise.yml)をbitrise GUIで管理する or リポジトリで管理するについては議論があると思います。ちょっとワークフローの流れを試してみたいとかなら、GUIでもいいと思いますが、 基本的には、リポジトリで管理する方が自分は良いと思っています。 以下、自分なりにそれぞれのメリット・デメリットに関して整理してみました。

メリット・デメリット


◯ bitrise GUI

  • メリット
    • ワークフローが 視覚的に 確認できる
    • GitHub等のソースコード管理ツールの権限を持っていなくても、ワークフローの参照・編集ができる
    • bitrise GUIでワークフローの差分管理もできる
  • デメリット
    • bitrise GUIを見に行かないと(権限がないと)、どういうワークフローになっているのかを確認できない。
      • そもそもそのリポジトリがなんのCIが動いているのか、リポジトリからは判断できない。
    • 他のCI/CDサービス(CircleCI, TravisCI etc…)は基本的にリポジトリで管理することを前提としているものもまぁまぁ多く、同じノリではいかないので、そういったサービスを使ってた人は、ちょっと戸惑う。
    • ワークフローを修正するときに、レビュー・反映するまでのフローが仕組み化されていない。
      • Git Flow, GitHub Flowが使えない?

◯ リポジトリで管理

  • メリット
    • bitrise GUIを見に行かずに、リポジトリのbitrise.ymlを見れば、ワークフローの流れが確認できる。
    • 他のCI/CDサービス(CircleCI, TravisCI etc…)と同じノリで使える。
    • Git Flow, GitHub Flowが使える。
  • デメリット
    • GitHubの権限がないと、対象appのワークフローの流れが 視覚的に パッとわからない。
      • buildのlogを見れば、何がどの順番で実行されているかはまぁわかる。
    • GUIでは、ワークフローの変更はできない。
    • ワークフローで変更した内容を反映させて、CIを試したい場合は、都度git commitしないといけないので、少し面倒。かつ、gitが汚くなるかも。

実際にやってみた


実際にやったこととしては

  1. 事前に、bitrise管理画面からトリガーとなるワークフローを作成する
  2. リポジトリ内のbitrise.yml等の設定ファイルを作成する

の2つです。以下その詳細を記載します。

1. 事前に、bitrise管理画面からトリガーとなるワークフローを作成する


上記で、リポジトリで管理すると記載しましたが、 bitriseは全てのワークフローをリポジトリで管理するわけではありません。 構造としては以下のようになっています。その理由に関しては、 リポジトリにbitrise.ymlを保存する潜在的な問題 を参考にしてください。

1.1. 大まかな流れ


  1. まず、bitrise GUIから作成したワークフローをトリガーとしてCIが起動する。
  2. そのワークフローがリポジトリ管理されているbitrise.ymlをキックする(起動する)。

1.2. bitrise管理画面からワークフローを作成する


  1. ci
    • 名前はciではなくてもなんでも良いが、リポジトリ内のbitrise.ymlで定義するワークフローと同じ名前に合わせる必要がある。
    • やることとしては、run_from_repoを起動するだけ。
  2. run_from_repo
    • 対象のリポジトリを git clone する。
    • git cloneされたリポジトリ内で管理された bitrise.yml をみて、対象のワークフローを起動する。
      • c.f. bitrise run <workflow name>

実際のbitrise GUI上から作成するワークフロー(今回の場合は、ciというワークフロー)は、以下の通りです。

---
format_version: '8'
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: ios
trigger_map:
- push_branch: "*"
  workflow: ci
- pull_request_target_branch: "*"
  workflow: ci
workflows:
  ci:
    after_run:
    - run_from_repo
  run_from_repo:
    steps:
    # git cloneするためのkeyのsetup
    - activate-ssh-key:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    # 対象のリポジトリを `git clone` する。
    - git-clone: {}
    # git cloneされたリポジトリ内で管理された `bitrise.yml` をみて、対象のワークフローを起動する。
    - script:
        title: continue from repo
        inputs:
        - content: |-
            #!/bin/bash
            set -ex
            # この場合 `bitrise run ci` が実行される。
            # リポジトリ内のbitrise.ymlの ci というワークフローを実行する。
            bitrise run "${BITRISE_TRIGGERED_WORKFLOW_ID}"

ちなみに余談ですが、公式ドキュメントに合わせて、after_run を使って ci -> run_from_repo と実行するように記載しましたが、試していないのですが、直接指定しても動作としては、問題ないと思います。

# e.g. after_runを使わずに、直接指定する場合
workflows:
  ci:
    steps:
    - activate-ssh-key:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone: {}
    - script:
        title: continue from repo
        inputs:
        - content: |-
            #!/bin/bash
            set -ex
            bitrise run "${BITRISE_TRIGGERED_WORKFLOW_ID}"

ただ

  • activate-ssh-key
  • git-clone
  • script

この部分を run_from_repo というワークフローで 共通化する ことで、ワークフローの管理を少なくすることができるので基本的には after_runを使った公式ドキュメントのやり方をすることが推奨されているのだと思います。

2. リポジトリ内のbitrise.yml等の設定ファイルを作成する


さて、bitrise GUI上での設定は終わりました。
あとは、いつも通りローカルで、エディタを開いて、対象のリポジトリに設定ファイルを追加するだけです。結論今回試したのは、Swiftのプロジェクトだったので、用意したのは、以下の3つのファイル。

$ tree -L 2
.
├── Dangerfile
・・・
├── bitrise.yml
├── fastlane
│   └── Fastfile
・・・

bitrise.yml

---
format_version: "8"
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
project_type: ios
workflows:
  ci:
    steps:
      # fastlaneでSwiftLintを動かしたい場合、事前にInstallしないとダメっぽい?
      - script:
          title: Install SwiftLint
          inputs:
            - content: |-
                #!/bin/bash
                set -ex
                curl -s -L -O https://github.com/realm/SwiftLint/releases/download/0.38.2/SwiftLint.pkg > /dev/null
                sudo installer -pkg SwiftLint.pkg -target / > /dev/null
                rm SwiftLint.pkg
      # fastlaneで、build laneを実行する
      - fastlane:
          inputs:
            - lane: build
      # bitriseに swiftlint の結果を artifact としてuploadする
      - deploy-to-bitrise-io:
          inputs:
            - deploy_path: "swiftlint-output.html"
      # 結果をSlack通知
      - slack:
          inputs:
            - title: ""
            - emoji: ""
            - emoji_on_error: ""
            - webhook_url: https://hooks.slack.com/services/xxxxxx/xxxxxx/xxxxxx # Slack の incoming webhook url
            - channel: "#bitrise-ci"
            - message: ""
            - message_on_error: ""
            - icon_url: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-icon-128.png
            - icon_url_on_error: https://bitrise-public-content-production.s3.amazonaws.com/slack/bitrise-slack-error-icon-128.png
            - fields: |
                App|${BITRISE_APP_TITLE}
                Branch|${BITRISE_GIT_BRANCH}
                Message|${BITRISE_GIT_MESSAGE}
                Workflow|${BITRISE_TRIGGERED_WORKFLOW_ID}

Fastlane

  • Swiftlint
  • danger

を実行するだけ。

fastlane_version "2.140.0"
default_platform :ios

lane :build do |options|
  danger(use_bundle_exec: true) # use_bundle_execをtrueにする必要あったか不明。。すいません。

  swiftlint(
    mode: :lint,
    reporter:    "html",
    output_file: "swiftlint-output.html",
    config_file: ".swiftlint.yml",
  )
end

Dangerfle

とりあえず、wipだったらwarnするだけ。

has_label_wip = github.pr_title.match(/WIP/i) || github.pr_labels.include?('wip') || github.pr_labels.include?('Wip') || github.pr_labels.include?('WIP')
warn("PR is Work in Progress") if has_label_wip

実行する

あとは、これらのファイルを対象リポジトリに追加、commitして、pushするだけ。

bitriseのlogを管理画面から確認してみると

bitrise-from-repo bitrise-artifact

こんな感じで成功です! 今後これをベースにbitrise.ymlを改善していこうと思っています。

さいごに

今までbitrise触ったことなかったですが、いい感じにベースは設定できたのかなという感じでした。 fastlaneも初めて触ったのですが、色々便利だなーと思いました。 iOSで構築しているCIのWorkflow紹介の記事の中で紹介しているように、bitriseのワークフローではなく、Fastlaneでメイン部分のワークフローを管理すれば、実質今回やりたかった「ワークフローをgitで管理すること」は満たせる感じはあるので、まずそちらをやってみて、それでもワークフローの管理に課題感を感じたら、本記事のようにbitrise.ymlもgitで管理することも検討してみるといいのかなと思いました。

参考

(C) Jun Kitamura 2020

Powered by Hugo & Kiss.