【iOS/Xcode】GitHub ActionsでCIを構築する方法!テスト実行とカバレッジ計測

【iOS/Xcode】GitHub ActionsでCIを構築する方法!テスト実行とカバレッジ計測

この記事からわかること

  • iOS/XcodeGitHub Actionsを使用してCI構築する方法
  • テスト実行カバレッジ計測の実装
  • slatherを使ったカバレッジレポートアーティファクト化

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

環境

参考文献:GitHub ActionsでiOSアプリのCI環境を構築する方法

GitHub ActionsでCI環境を構築する

前提として「CI/CD」とは「Continuous Integration(継続的インテグレーション)」と「Continuous Deployment/Delivery(継続的デリバリー/デプロイメント)」の略称でソフトウェア開発のプロセスにおける自動化の手法のことです。

これはiOSアプリ開発においても活用されることが多く、今回はCI環境をGitHub Actionsを使用して構築していく方法をまとめていきたいと思います。GitHub Actions自体の詳細な使い方などは以下の記事を参考にしてください。

※ただGitHub Actionsの無料枠ではXcodeを動作させるためのmacOS環境が必要になりますが、その際は10倍の時間が消費されるので注意してください。

YAMLファイルの実装

GitHub Actionsでは.github/workflows/配下に設定されたymlファイルを読み込んで処理を実行します。そのためiOSプロジェクトの直下に.github/workflows/main.ymlを作成しておきます。中には以下のように定義します。


# ワークフロー名称
name: CI
# トリガー(条件)
on:
  push:
    branches:
      # mainブランチへのプッシュ時のみに発火
      - main 

# CI動作環境
env:
  # Xcodeの最新アプリケーションを指定
  DEVELOPER_DIR: /Applications/Xcode_26.0.1.app
  
# ジョブを定義
jobs:
  # ジョブ名を指定
  ci_build:
    # 実行環境を指定
    runs-on: macOS-latest
    # ジョブ内の各ステップを定義
    steps:
      # リポジトリのコードをチェックアウト(取得)
      - name: Checkout
        uses: actions/checkout@v4

      # あとは諸々の処理を記述していく

実際に導入しているリポジトリも記載しておきますので参考にしてください。

DEVELOPER_DIRでXcodeバージョンの指定

CI上で動作させるXcodeのバージョンは明示的に指定する必要があります。プロジェクトで使用しているバージョンに合わせたものを指定しておいてください。CI環境で設定するためのアプリ名はRun ls /Applications | grep "Xcode"

# CI動作環境
env:
  # Xcodeの最新アプリケーションを指定
  DEVELOPER_DIR: /Applications/Xcode_26.0.1.app

Jobstepの中に以下のような実装を入れておくとGitHub Actions実行に使用可能なXcodeバージョン一覧と実際に動作させているXcodeバージョンを確認できるようになります。

      # 使用可能なXcodeアプリ一覧を出力する
      - name: Show Xcode list
        run: ls /Applications | grep "Xcode"
      # 実行環境のXcodeバージョンを出力する
      - name: Show Xcode version
        run: xcodebuild -version

2025年11月時点だと以下のようになっています。

Run ls /Applications | grep "Xcode"
Xcode_16.0.0.app
Xcode_16.0.app
Xcode_16.1.0.app
Xcode_16.1.app
Xcode_16.2.0.app
Xcode_16.2.app
Xcode_16.3.0.app
Xcode_16.3.app
Xcode_16.4.0.app
Xcode_16.4.app
Xcode_16.app
Xcode_26.0.1.app
Xcode_26.0.app
Xcode_26.1_Release_Candidate.app
Xcode_26.1.0.app
Xcode_26.1.app
Xcode.app

Xcodeでビルドを行う

GitHub Actions中でビルドを行いたい場合はxcodebuildコマンドを使用します。オプションでそれぞれ対象のプロジェクトファイルやスキーム、実行先にシミュレーターなどを細かく指定することが可能です。Swift UIのPreviewがある場合はENABLE_PREVIEWS=NOをつけておくと安定します。またパイプで失敗したコマンドを正しく検知するためにset -o pipefailも付与しておきます。

- name: Xcode build
  run: |
    set -o pipefail
    xcodebuild \
      -project プロジェクト名.xcodeproj \
      -scheme スキーム名 \
      -sdk iphonesimulator \
      -destination "platform=iOS Simulator,name=iPhone 17" \
      -configuration Debug \
      build \
      ENABLE_PREVIEWS=NO

単純なプロジェクトであれば上記だけでビルドまで完了します。ただ実際はCocoa Podsを使用していたり、Firebaseと連携させていたりすると思うのでそこら辺の連携処理の実装も必要になってきます。

Ruby製ライブラリのセットアップ

Cocoa Podsやxcprettyを使用する場合は最初にRubyのセットアップも必要になります。

      # Rubyのセットアップ
      - name: Set Ruby version
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2
              
      # Gemsのキャッシュ
      - name: Cache Gems
        uses: actions/cache@v4
        with:
          path: vendor/bundle
          key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-gems-

      # GemFileに定義したライブラリ群のインストール
      - name: Install Bundled Gems
        run: |
          bundle config path vendor/bundle
          bundle install --jobs 4 --retry 3

GemFileの中には以下あたりを入れておきます。ここら辺はプロジェクトによって変わる部分かなと思いますがxcprettyはログを最適化してくれ、slatherはカバレッジレポートをCIツール(Codecovなど)と連携しやすくするために入れておくと便利です。


# frozen_string_literal: true

source "https://rubygems.org"

# ===== GitHub Actions CI用 ===== 
# xcodebuild の出力ログを整形して見やすくするツール
gem "xcpretty"
# iOS/Swift の コードカバレッジレポート生成ツール(CIツール連携用)
gem "slather"
# ライブラリ管理ツール
gem "cocoapods"

xcprettyでログを最適化する

CI上で出力されるログは何もしないと膨大な量出力されて可読性が悪いのでxcprettyを使用することで最適化させることが可能です。bundle exec xcprettyをビルド時の最後に一緒に実行するようにすればOKです。

      # Xcodeビルド
      - name: Xcode build
        run: |
          set -o pipefail
          xcodebuild \
            -project プロジェクト名.xcodeproj \
            -scheme スキーム名 \
            -sdk iphonesimulator \
            -destination "platform=iOS Simulator,name=iPhone 17" \
            -configuration Debug \
            build \
            ENABLE_PREVIEWS=NO \
            | bundle exec xcpretty

Cocoa Podsを使用する

プロジェクトがCocoa Podsを使用してライブラリを管理している場合はGitHub Actions上でもCocoa Pods自体のインストールやライブラリのインストールが必要になってきます。先ほどGemFileでインストールは完了しているのでキャッシュ処理とライブラリ群のインストール処理を定義しておきます。

      # CocoaPodsで管理しているライブラリのキャッシュ
      - name: Cache Pods
        uses: actions/cache@v4
        with:
          path: Pods
          key: ${{ runner.os }}-pods-$#123;{ hashFiles('**/Podfile.lock') }}
          restore-keys: |
            ${{ runner.os }}-pods-

      # Cocoa Podsのセットアップ
      - name: Install Pods
        run: bundle exec pod install

またCocoa Podsの場合は.xcworkspaceに変わるのでxcodebuildで指定する際も以下のように修正しておいてください。

// -project プロジェクト名.xcodeproj \
-workspace プロジェクト名.xcworkspace \

Swift Package Manager

Swift Package Managerのライブラリは基本的にビルド時に自動で導入されるので明示的に処理を記述する必要はありません。ただキャッシュだけ行うようにしておくとパフォーマンスが向上するので入れておきます。

      # SPMのライブラリのキャッシュ
      - name: Cache Swift Packages
        uses: actions/cache@v4
        with:
          path: SourcePackages
          key: ${{ runner.os }}-spm-${{ hashFiles('*.xcodeproj/project.xcworkspace/ xcshareddata/swiftpm/Package.resolved') }}
          restore-keys: ${{ runner.os }}-spm-

テストの実行 & カバレッジの取得

テストを実行したい場合はbuildではなくtestに変更するだけです。-enableCodeCoverage YESを付与することでカバレッジデータ(.xccovreport / .xccovarchive)を生成してくるようになります。ただこれはカバレッジレポートではなく、あくまでバイナリファイルなので人間の目では読むことができません。そのため最初に紹介したslatherを使用します。またxcpretty --test --colorとすることでGitHub上のログも詳細に出せます。

      # Xcodeビルド
      - name: Run Xcode Test
        run: |
          set -o pipefail
          xcodebuild \
            -sdk iphonesimulator \
            -destination "platform=iOS Simulator,name=iPhone 17" \
            -configuration Debug \
            -workspace プロジェクト名.xcworkspace \
            -scheme スキーム名 \
            -enableCodeCoverage YES \
            test \
            ENABLE_PREVIEWS=NO \
            | bundle exec xcpretty --test --color

テストが実行されるブランチは当たり前ですがGitHub Actionsのトリガーに指定しているブランチになります。またデフォルトではテストに失敗するとフロー自体がエラーになりGitHub Actions上では以下のように表示されます。テストを追加しなければマージをブロックさせたい場合を想定してデフォルトではエラーになるので、失敗でも通過させたい場合は|| trueで終了コードを無視するようにすればOKです。

** TEST FAILED ** Error: Process completed with exit code 65.

テストに失敗した部分が現状のままだとログとして出ておらず、気づけなかったので失敗した場合はbundle exec xcpretty --test --colorを一時的にコメントアウトするとちゃんと以下のようにエラーが確認できました。

// 失敗していた
Test case 'DateFormatUtilityTests/getTimeString()' failed on 'Clone 1 of iPhone 16 Pro Max - プロジェクト名 (23634)' (0.000 seconds) 

Test case 'JsonConvertUtilityTests/decodeFromJsonString()' passed on 'Clone 1 of iPhone 16 Pro Max - プロジェクト名 (23634)' (0.000 seconds)

slatherでカバレッジレポートを生成する

slatherを使用することで人間の読めるHTMLベースや別のCI統合用のカバレッジレポートを生成することができます。

      # カバレッジレポートの作成
      - name: Generate Coverage Report
        run: |
          slather coverage \
            --html \
            --output-directory slather-report \
            --scheme スキーム名 \
            プロジェクト名.xcodeproj \ # ここはCocoa Podsありでも.xcodeprojでOKぽい

      # カバレッジレポートのアーティファクト化
      - name: Upload coverage report
        uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: slather-report

アーティファクト化は「ソフトウェア開発における、成果物(=アーティファクト)として扱えるように明確な形にまとめること」を指しています。要は成果物としてまとまったドキュメントとして吐き出してくれるようになるということです。実際に動作させてみるとGitHub Actionsの結果のArtifactsに「coverage-report」が表示されるようになります。

【iOS/Xcode】GitHub ActionsでCIを構築する方法!テスト実行とカバレッジ計測

これをダウンロードして中身を見るとSwiftファイルごとのカバレッジレポートファイルがHTML形式で作成されています。

【iOS/Xcode】GitHub ActionsでCIを構築する方法!テスト実行とカバレッジ計測

中身はこんな感じです。

【iOS/Xcode】GitHub ActionsでCIを構築する方法!テスト実行とカバレッジ計測

詳細は以下の記事を参考にしてください。

Firebase連携アプリでpublicリポジトリの場合は以下もチェック

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

Search Box

Sponsor

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index