M6 Mac miniをGiteaのCIサーバーにする


M6 Mac miniを書いました!

ので、CIサーバーとして活用します。

環境を汚さずに日常使いも同時にできるCIサーバーを作る

せっかくのApple Siliconなので、Linux CIに加えてmacOS CIにもします。

CIサーバーにするのは前々からの目的ではあるものの、CIだけにはもったいないので、日常使いもできるようにします。

しかし、CIに環境を汚されてしまっては困ります。なのでマルチユーザーかつコンテナ/VMで隔離されたCI環境を作ります。

構成検討

以前のmacOS CIサーバーはOrbStackを使用してdocker互換socketを生やしていましたが、OrbStackはGUI前提のようなアプリのため今回は別のものを使用します。

Apple Containerというものがちょっと前に公式から出て流行っていた雰囲気があるので調査しましたが、どうやらDockerやDocker Composeとの互換性がまだ不十分のようなのでCI用途には不採用としました。

そこで、ColimaをDockerランタイムに使用します。

また、macOS Runnerも必要です。
しかし、macOS RunnerをMac miniのホスト上で直接動作させるとCIによってホスト環境が汚染されます。

そこでTartというものを見つけました。どうやらOpenAI(に移管された?)が作っているようです。

これはmacOS VMをCLIから簡単に管理、作成できるようなツールになっています。

ユーザーを分離する

普段遣いのAdministratorユーザーのsim1222と、CI向け一般ユーザーのciを作成した。

Homebrewをどうしよう

ColimaやTartはパッケージマネージャーなどから導入したいため、homebrewが選択肢に挙がります。
しかし、homebrewはデフォルトで/opt/homebrewなどを使用するため、普通にマルチユーザーにすると管理が大変になります。

なので、

  • メインのユーザーでhomebrew経由でtartやColimaなどの必要なツールをインストール
  • ciユーザーのpathに/opt/homebrew/bin/を通す
  • ciはhomebrewを触らないが、homebrew経由でパッケージが管理される

ようにしました。

Colimaでdocker socketを生やす

まず、普段のユーザーからColimaをインストールします。

Terminal window
brew install colima

dockerコマンドとそのランタイムは別なのでdockerコマンドもインストールします

Terminal window
brew install docker docker-compose

dockerコマンドからCompose Pluginを見つけられるようにします。

~/.docker/config.json

{
"cliPluginsExtraDirs": [
"/opt/homebrew/lib/docker/cli-plugins"
]
}

Colimaを自動起動する

通常であれば、この後に

Terminal window
brew services start colima

でLaunchAgentでColimaを自動起動させますが、homebrewで複数ユーザーかつcolimaを動作させるのが通常権限ユーザーだとログの書き込みに失敗して落ちます。

Homebrewが生成するLaunchAgentのplistは、/opt/homebrew/var/log/colima.logにログを書き込もうとしますが、当然そこへの書き込み権限はありません。

/opt/homebrew/var/log/の権限を緩めてもいいですが、今回は普段使いユーザーでもcolimaを使いたいのでログが衝突してしまう危険性があります。
なので、自動生成のLaunchAgentのplistではなく、それをベースに自分で書きます。

今回はログを/Users/ci/Library/Logs/colima.logに置きます。

/Users/ci/Library/LaunchAgents/com.sim1222.ci-colima.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.sim1222.ci-colima</string>
<key>ProgramArguments</key>
<array>
<string>/opt/homebrew/opt/colima/bin/colima</string>
<string>start</string>
<string>-f</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/ci</string>
<key>EnvironmentVariables</key>
<dict>
<key>HOME</key>
<string>/Users/ci</string>
<key>PATH</key>
<string>/opt/homebrew/bin:/opt/homebrew/sbin:/usr/bin:/bin:/usr/sbin:/sbin</string>
<key>COLIMA_HOME</key>
<string>/Users/ci/.colima</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key>
<true/>
</dict>
<key>StandardOutPath</key>
<string>/Users/ci/Library/Logs/colima.log</string>
<key>StandardErrorPath</key>
<string>/Users/ci/Library/Logs/colima.log</string>
</dict>
</plist>

そして登録、起動します

Terminal window
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.sim1222.ci-colima.plist
launchctl kickstart gui/$(id -u)/com.sim1222.ci-colima

これで、LaunchAgentによってColimaがciユーザーのログイン時に自動実行されるようになりました。

Linux Gitea Runner

LinuxのGitea Runnerはdockerコンテナとして起動し、CIごとにコンテナを生やせるようにします。

gitea-runner-linux/compose.yaml

services:
runner:
image: docker.io/gitea/runner:3
container_name: gitea-runner-linux
restart: unless-stopped
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: "${GITEA_INSTANCE_URL}"
#GITEA_RUNNER_REGISTRATION_TOKEN: "${GITEA_RUNNER_REGISTRATION_TOKEN}"
GITEA_RUNNER_NAME: "m6-linux-arm64"
GITEA_RUNNER_LABELS: "linux-arm64:docker://docker.gitea.com/runner-images:ubuntu-latest"
volumes:
- runner-data:/data
- ./config.yaml:/config.yaml:ro
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "8088:8088"
volumes:
runner-data:

.envにはGiteaのインスタンスURLとRunner registration tokenを入れます。

GITEA_INSTANCE_URL=https://gitea.example.com/
GITEA_RUNNER_REGISTRATION_TOKEN=xxxxxxxx
cache:
enabled: true
dir: ""
host: host.docker.internal
port: 8088

macOS Runner

Terminal window
brew install openai/tools/tart
Terminal window
tart clone ghcr.io/cirruslabs/macos-golden-gate-xcode:latest golden-gate-xcode
tart clone golden-gate-xcode macos-runner
tart run --no-graphics macos-runner
Terminal window
ssh admin@$(tart ip golden-gate-xcode)

あとは同様にgitea runnerをhostモードで動作させ、tartをLaunchAgentで自動起動