
Xcode Cloudで任意のバージョンのRubyを使う
はじめに
Xcode Cloudは便利なCI/CDサービスだが、ビルド環境にプリインストールされているRubyのバージョンが古いという課題がある。具体的には Ruby 2.6系 であり、現在一般的に利用されているRuby 3系とは互換性に差がある。
先日、iOSアプリの機密情報の取り扱いには Arkana を採用した。Arkanaは .env
ファイルや環境変数から難読化されたSwiftコードを生成するgemで、アプリのシークレット情報をコードと分離して扱える。この記事では、Xcode CloudがRuby 2.6であるためArkana v1.4.0を使った経緯を紹介した。
Arkanaの最新版を使うにはRubyのバージョンを2.7.0以上に上げる必要がある。
Appleが将来的にランナー環境のRubyを更新する可能性もあるが、執筆時点では開発者側で対処するしかない。本記事では ci_post_clone.sh
スクリプトを使い、Xcode Cloudで任意のバージョンのRubyを使う方法を紹介する。
Xcode Cloudに任意のRubyをインストールする
Xcode Cloudにはリポジトリ取得後に任意のスクリプトを実行できる ci_post_clone.sh
という仕組みがある。この仕組みを利用して新しいRubyをインストール・設定する。
- プロジェクトのルートに
ci_scripts
ディレクトリを作成 - その中へ
ci_post_clone.sh
を配置 chmod +x ci_scripts/ci_post_clone.sh
で、実行権限を付与してGitにコミット
Xcode Cloudは、リポジトリをクローンした直後にこのスクリプトを実行する。
Rubyを3系(例:3.2.1)に上げておけば、今後gemを追加しても対応しやすい。以下は、Ruby 3.2.1を導入するスクリプト例だ。ci_post_clone.sh
に記述する。
#!/bin/zsh
set -euo pipefail
cd "$CI_PRIMARY_REPOSITORY_PATH"
# 書き込み権限がないためエラーが発生する。Bundlerはユーザ領域にインストールさせる
export GEM_HOME="$HOME/.gem"
# rbenvのインストール
brew install rbenv ruby-build
eval "$(rbenv init -)"
# 必要なRubyバージョンのインストール(例:3.2.1)
rbenv install 3.2.1
rbenv global 3.2.1
# どのRubyを使用しているか確認する
echo "🔎 Ruby executable: $(which ruby)"
echo "🔎 Ruby: $(ruby -v)"
echo "🔎 RubyGems: $(gem --version)"
# Bundler をインストールする (Gemfile.lock の BUNDLED WITH と合わせる)
BUNDLER_VERSION="2.4.22"
gem install bundler -v "$BUNDLER_VERSION" --no-document --quiet
bundle install --quiet
# ArkanaKeys パッケージを生成する
bundle exec ruby -e "puts '🔎 Arkana version: ' + Gem.loaded_specs['arkana'].version.to_s"
bundle exec arkana
ci_post_clone.sh
実行後のログは次のとおりで、Ruby 3.2.1が使用されていると確認できた。
ビルド時間への影響
カスタムRubyをインストールする最大のデメリットはビルド時間の増加だ。Xcode Cloudランナーは一時的な環境のため、キャッシュされないインストール処理が毎回発生する。
プロジェクトの依存関係にもよるが、ビルド時間はおおよそ4〜6分ほどの増加する。筆者のプロジェクトでは通常15分のビルドが、この処理により約20分30秒に延びた。Xcode Cloud無料プランは月25時間までと制限があるため、このオーバーヘッドを考慮する必要があるだろう(ビルド回数は月100回から70回へ減少)。
まとめ
- Xcode Cloudに任意のRubyをインストールすることは可能
- 時間課金型CI/CDサービスでは、ビルド時間の増加がコストに直結する
ビルド時間の増加はネックのため、当面はArkana 1.4.0で運用することにした。ArkanaがHomebrew Formulaとして配布されればCIでの時間ロスは解消される。すでにIssue #44が起票されているが、依存関係の問題で対応が進んでいないのが残念だ。今後もウォッチを続ける。
関連記事
既存のiOSアプリをXcode Cloudでビルドする方法は以下の記事で紹介した。