CircleCI などの CI / CDサービスを利用した自動テストやデプロイはとても便利です。しかし時には、以下のようなクラウド上でジョブを実行できない場面も存在します。
- 社内ネットワーク内のリソースに直接アクセスしたい
- クラウドで提供されていない macOS / Xcode バージョンを使いたい
- macOS ジョブのコストを抑えたい
- 物理マシンとの接続が必要なプロダクトである
このようなケースで使えるのが、self-hosted runnerです。 これを使えば、手元の PC で CI ジョブを動かせます。
この記事では、machine runner 3 を macOS にインストールし、実際にジョブを実行するまでの手順を紹介します。
クラウド上でジョブを実行することが難しいケース
まずはどのようなケースでself-hosted runnerを使う必要があるかを整理しましょう。
社内ネットワーク内のリソースに直接アクセスするタイプのデプロイを行いたい
プロジェクトによってはプライベートレジストリやテスト用データベースへの接続を必要とするジョブを実行する必要があります。金融系やヘルスケア業界・公共機関などでは、特にこの傾向があります。
もしこれらのリソースと接続してジョブを実行する必要がある場合は、self-hosted runnerを使う必要があります。
物理マシンとの接続が必要なプロダクトである
IoTデバイスやRTOSなど、物理デバイスに組み込むことを想定したソフトウェアの場合は、実際のデバイスへのアクセスがデプロイやE2Eテストなどで必要です。この場合も対象のデバイスか、そのデバイスに接続するPC上へself-hosted runnerを構築してジョブを実行する設計となります。
そのほかのユースケース
これ以外にも利用しているCIサービスがサポートしていないベータ版または古いバージョンのmacOSやXCodeを利用したい場合や、社内に余っているマシンの有効活用、コードベースを社外ネットワークへ共有できない要件があるケースなどでは、self-hosted runnerを利用してCI / CDパイプラインを実行することになります。
macOS上にself-hosted runnerを構築する
macOS上でジョブを実行する環境を整備する方法は非常に簡単です。ここからはセットアップ手順を6つのステップに分けて紹介します。
前提条件
今回紹介する手順は、以下の環境を前提としています。
- macOS(この記事では macOS 15.7.2、Apple Silicon で検証)
- Homebrew がインストール済み
- CircleCI アカウント
- 組織の管理者権限(Runner 作成時のみ必要)
sha256sum がインストールされていない場合は、事前に coreutils をインストールしてください。
brew install coreutils
ステップ1: Runner 利用規約への同意
self-hosted runner を使うには、まず組織の管理者が利用規約に同意する必要があります。
CircleCI Web App にログインし、Organization Settings から Self-Hosted Runners を開いてください。
利用規約が表示されるので、内容を確認して同意しましょう。
ステップ2: namespace と resource class の作成
続いて、Runner を識別するための namespace と resource class を作成します。
CircleCI Web App で Self-Hosted Runners を開きます。画面右上にあるCreate Resource Class をクリックしましょう。
namespace は組織全体で1つしか作成できません。すでに Orbs を使っている場合は、同じ namespace を使用する必要があります。新規に作成する場合は、組織名の小文字表記がおすすめです。
resource class 名には、用途がわかる名前を付けましょう。例えば my-macos-runner のような名前が適しています。
作成が完了すると、resource class token が表示されます。
このトークンは後から再取得できないため、安全な場所に保存してください。
macOSなどローカルマシンを利用する場合は、Machine タブを選択して対象のOSごとのセットアップ方法が記載されたドキュメントのリンクを開きましょう。
ステップ3: Runner のインストール
ここからはローカルのmacOS PCにて、self-hosted runnerを実行する環境を構築します。
macOS の場合、 Homebrew を使って Runner をインストールします。
まず、CircleCI のリポジトリを追加してください。
brew tap circleci-public/circleci
次に、circleci-runner パッケージをインストールします。
brew install circleci-runner
インストールが完了したら、設定ファイルを編集しましょう。サンプルコマンドはvimですが、codeやcursorなどのエディタにてYAMLファイルを開いて編集してもOKです。
vim $HOME/Library/Preferences/com.circleci.runner/config.yaml
config.yamlは以下のように編集します。まずauth_token には、ステップ2で取得したトークンを設定します。name には任意の識別名を指定しておきましょう。
runner:
name: "my-macos-runner"
working_directory: "/Users/$USER/Library/com.circleci.runner/workdir"
cleanup_working_directory: true
api:
auth_token: "ステップ2で取得したトークン"
cleanup_working_directory を true に設定すると、ジョブ実行後に作業ディレクトリがクリーンアップされます。
ファイルを保存したら、インストールと初期設定は完了です。
設定ファイルには resource class token(auth_token)が含まれます。記事やスクリーンショット、ログを公開する際は、トークンを含めないよう注意してください。
ステップ4: Apple 署名の承認
続いてmacOSの場合、署名認証を行います。これはself-hosted runner がバイナリとして配布されている関係上、macOS のセキュリティ機構による承認が必要となるためです。
まず、署名と notarization を検証しましょう。
spctl -a -vvv -t install "$(brew --prefix)/bin/circleci-runner"
以下のような出力が表示されれば、正しく署名されています。
/opt/homebrew/bin/circleci-runner: accepted
source=Notarized Developer ID
origin=Developer ID Application: Circle Internet Services Inc.
次に、quarantine 属性を解除します。このコマンドは sudo が必要なため、macOS のシステムパスワードを入力してください。
sudo xattr -r -d com.apple.quarantine "$(brew --prefix)/bin/circleci-runner"
これで承認が完了しました。
ステップ5: Runner の起動
最後にセットアップした Runner 起動しましょう。
起動には launchctl コマンドを使います。以下のコマンドを順番に実行してください。
launchctl bootstrap gui/$(id -u) $HOME/Library/LaunchAgents/com.circleci.runner.plist
launchctl enable gui/$(id -u)/com.circleci.runner
launchctl kickstart -k gui/$(id -u)/com.circleci.runner
起動状態の確認には、以下のコマンドを実行します。
launchctl print gui/$(id -u)/com.circleci.runner
state = running と表示されれば、Runner は正常に起動しています。
これであとは CircleCI からパイプラインを実行すればOKです。
ステップ6: 動作確認
最後にセットアップした Runner が正しく動作するか確認しましょう。テスト用のプロジェクトに .circleci/config.yml を作成します。
version: 2.1
workflows:
test-workflow:
jobs:
- runner-test
jobs:
runner-test:
machine: true
resource_class: your-namespace/my-macos-runner
steps:
- run:
name: Hello from self-hosted runner
command: echo "Hi, I'm running on my Mac!"
resource_class には、ステップ2で作成した namespace と resource class 名を namespace/resource-class の形式で指定してください。
この設定ファイルをコミットして push しましょう。すると、手元の macOS 上に構築された Runner でジョブが実行されます。CircleCI のダッシュボードでパイプラインを確認すると、ジョブが self-hosted runner 上で実行されたことがわかります。
Runner のログを確認したい場合は、以下のコマンドを実行してください。
tail -f $HOME/Library/Logs/com.circleci.runner/runner.log
Runner の停止
Runner を停止するには、disable と bootout の両方を実行する必要があります。disable だけではプロセスが残り続けるため、必ず両方のコマンドを実行してください。
launchctl disable gui/$(id -u)/com.circleci.runner
launchctl bootout gui/$(id -u)/com.circleci.runner
停止を確認するには、以下のコマンドを実行します。
launchctl list | grep circleci
何も表示されなければ、Runner は完全に停止しています。
なお、Runnerが停止した状態でパイプラインが実行された場合、ジョブが待機状態のまま停止します。もしいつまで経ってもジョブが実行されないパイプラインを見つけた場合は、self-hosted runnerのランナーが停止していないか確認しましょう。
self-hosted runnerで任意のコマンドが実行できない場合
バージョン管理ツール(fnm、rbenvなど)を使用している場合、
ジョブ内でPATHを明示的に設定する必要があります。
- run:
name: 環境変数を設定
command: |
echo 'export PATH="$HOME/.fnm:$PATH"' >> "$BASH_ENV"
source "$BASH_ENV"
まとめ
この記事では、macOS に CircleCI machine runner 3 をインストールし、ジョブを実行するまでの手順を説明しました。
セットアップにはCircleCIダッシュボード上での操作やトークン取得と、RunnerにするmacOSマシン側での作業が必要です。とはいえ一度セットアップしてしまえば、あとはlaunchctlコマンドで起動・停止などを操作するのみです。ただし利用するコマンドのPATHが正しく通っているかどうかのチェックについては、事前に確認しておくようにしましょう。
CircleCI ではself-hosted runnerを利用する際のトラブルシューティングガイドも用意しています。もしテストする・運用する中で困ったことなどがあればこちらもぜひご活用ください。








