DeNA Testing Blog

Make Testing Fun, Smart, and Delighting End-Users

xcode-installのリグレッションテストをGitHub Actionsで自動化した話

この記事はDeNA Advent Calendar 2019の2日目の記事です。

SWETの加瀬(@Kesin11)です。

SWETグループではいくつかの分野ごとにチームを分けて活動をしており、自分は現在CI/CDチームで主にゲーム事業部向けのJenkinsやCI/CDのサポートをしています。

今回は、xcode-installというgemにpull-reqを送る際に、動作確認のための環境としてGitHub Actionsを活用したことについての記事です。

xcode-installとは

xcode-installはその名の通り、XcodeのインストールやアンインストールをCLIから可能にするxcversionというコマンドを提供するgemです。大半の方はApp StoreやAppleのデベロッパー向けサイトからXcodeをダウンロードして手動でインストールしているでしょうから、そのようなツールがなぜ必要なのかと不思議に思われるかもしれません。

iOS開発におけるCI/CDには、CircleCIやBitriseといったマネージドサービスを利用することが一般的になってきました。ですが、ビルド時間やリポジトリ容量などの問題からそのようなサービスを使いにくいプロダクトも存在します。その場合は、Jenkins + ビルド用macOSの両方を自前で構築、管理することになります。

このビルド用macOSのマシンには、iOSアプリをビルドするための様々なツールを予めセットアップしておく必要があり、Xcodeもその1つです。マシンが1台だけであれば手動で全てのツールをセットアップ可能ですが、ビルドマシン増設を容易にするためSWETではAnsibleを採用してビルドマシンの各種ツールのセットアップを自動化しています。

Ansibleでツールをインストールする際には、homebrewのようなCLIツールが提供されていると簡単です。そこで、Xcodeをインストールするにはxcode-installが必要不可欠となります。

ここからが本題となるのですが、Xcode 11がリリースされてほどなくした今年の10月末にxcode-installで前バージョンであるXcode 10.3をインストールしようとしたところ、なぜか失敗するようになっていました。xcode-installが使えなくなるのは自分たちの業務に大変影響があるため、原因を調査して修正することにしました。

Xcode 10.x系がインストールできない問題(修正済み)

今回、自分が遭遇した問題はXcode 10系でインストールに失敗するというものでした(issue)。ちょうどXcode 11系の正式版がリリースされた時期で、Xcode 11系のインストールは問題がなかったためか、自分以外にissueで報告している人もいないようでした。

ソースコードや過去のpull-reqを追ったところ、ダウンロードしたxipを解凍後のXcode.appの証明書検証に失敗していることが分かりましたので、手元でインストールしたgemに対して後にpull-reqを出したパッチを当てて、Xcode 10.3のインストールが成功するように修正をしました。

xcode-installを修正する難しさ

自分は数年前からxcode-installを使用していますが、過去にも度々動作が不安定になったり、特定の人の環境では失敗するという話を社内で聞くことがありました。不安定な要因として、xcode-installに関係する環境の複雑さがあります

  • macOSのバージョン
  • Rubyのバージョン
  • Fastlaneのバージョン1
  • インストールしようとしているXcodeのバージョン

xcode-installの過去のissuepull-reqを見てもらうと分かるのですが、自分の環境では動いた/動かなかった、という報告が多いです。

今回の自分の修正パッチも、自分の手元のmacではXcode 10.3がインストールできることは確認したものの、 Xcode 10.0 ~ 11.1の間に含まれる他のバージョンで逆にインストールが失敗してしまうのではないか不安がありました。

本来であれば全てのバージョンで動作確認をするべきなのですが、Xcodeのインストールは自分の環境で1回あたり30-40分程度の時間がかかることと、xipをダウンロード後の解凍や検証の処理でCPUパワーが使われるためになかなか辛いものがありました。

GitHub Actionsを利用したリグレッションテスト

手元のmacで実行するのが難しいのであれば、外部のマシンパワーをお借りしたいところです。ちょうどGitHub Actionsがオープンβで個人的にも色々試していた時期で、macOSのVMも使えることが分かっていました。このmacOSのVMを利用してxcode-installの過去のXcodeバージョンのインストール動作確認、すなわちリグレッションテスト(回帰テスト)を行うことを思いつきました。

自分が修正パッチを当てる前は、10系のXcodeのインストールが失敗するという状態でしたので、実際に全てのXcodeのバージョンについて問題なくインストールできることを確認することにしました。確認の手順としては以下になります。

  1. xcversion install {XCODE_VERSION} が終了コード0で完了すること
  2. xcversion installed の結果にインストールしたXcodeのバージョンが表示されること

実際にGitHub Actionsのyamlに書き下したのがこちらです

name: "E2E test"
on: [pull_request]

jobs:
check_install:
  strategy:
    fail-fast: false
    matrix:
      os: [macos-latest]
      xcode: ["10.0", "10.1", "10.2.1", "10.3", "11.0", "11.1", "11.2.1"]

  runs-on: ${{ matrix.os }}
  env:
    # It needs AppleID that has disabled 2FA.
    XCODE_INSTALL_USER: ${{ secrets.XCODE_INSTALL_USER }}
    XCODE_INSTALL_PASSWORD: ${{ secrets.XCODE_INSTALL_PASSWORD }}
  steps:
  # Prepare env
  - uses: actions/checkout@master
  - uses: actions/setup-ruby@master
    with:
      ruby-version: '2.6'

  # Show env
  - name: Show macOS version
    run: sw_vers
  - name: Show ruby version
    run: |
      ruby --version
      bundler --version
  
  # Prepare
  - run: bundle install -j4 --clean --path=vendor
  - run: bundle exec xcversion update
  - name: Show installed versions before install
    run: bundle exec xcversion installed
  - name: Uninstall installed target Xcode version
    run: bundle exec xcversion uninstall ${{ matrix.xcode }} || true

  # Exec
  - run: bundle exec xcversion install ${{ matrix.xcode }}

  # Check
  - name: Show installed versions after install
    run: bundle exec xcversion installed
  - name: Check Xcode installation was successful
    run: bundle exec xcversion installed | grep "${{ matrix.xcode }}"

xcode-installをforkした自分のリポジトリでこのGitHub Actionsを動かし、全てのバージョンで問題なくインストールできることを確認できましたので、自信を持って本家にpull-reqを送ることができました。

GitHub Actionsは他のCIサービス同様に、publicなリポジトリであればオーナー以外のユーザーも実行ログを確認できます。自分は今回pull-reqを出した側でしたが、レビュワーも実際に動いたログからデグレしていないことを確認できたため、安心できたのではないでしょうか。

その後、自分が作成したGitHub Actionsのコードはメンテナの方に興味を持ってもらえたようで、別のpull-reqで本家にマージされました🎉
xcode-installの動作確認が簡単になることで他の方もコントリビュートしやすくなり、今後は安定性も向上するでしょう。

まとめ

今回はxcode-installという特殊なツールの修正事例を通してGitHub Actionsの少し変わった活用方法をご紹介しました。GitHub Actionsでは他のCIサービスと同様にLint、ユニットテスト、デプロイというフローを組み立てるのが一般的だと思いますが、応用次第で今回のように色々と面白いことができるはずです。

最後に、CI/CDチームでは社内におけるCI/CD環境の開発・提供を通じて、開発者が開発に専念できるプロセスを支援しています。
興味を持たれた方は下記の職種で採用をしておりますので、ぜひご応募ください。


  1. Developer Portalにアクセスする処理などにFastlane内部のライブラリが使用されていたりします。ですが、xcode-installのgemspecでFastlaneのバージョンは厳格に管理されていないため、環境によってはとても古いFastlaneが使われてしまうことで問題となることがあります