Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 136 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ bash ops/ci/install_cli.sh
CI対象リポジトリで(ローカル):

```bash
cd ~/dev/maakie-brainlab
cd ~/dev/<target-repo>
ci-self up
```

Expand All @@ -25,28 +25,147 @@ ci-self up
- `ci-self` / `verify.yml` は `nix-daemon.sh` を自動読み込みして `nix` を検出(毎回の手動 `source` は不要)
- 既存の `verify.yml` が古い場合は `bash ops/ci/scaffold_verify_workflow.sh --repo <target> --apply --force` で更新

## Mac mini ワンコマンド(推奨)
## 別端末の CI runner を 1 コマンドで使う(推奨)

MacBook から 1 コマンドで「鍵認証確認 -> 同期 -> Mac mini 実行 -> 結果回収」まで行う:
この導線は、特定のリポジトリ専用ではありません。

- マシンA: self-hosted runner / colima / docker を置いている端末
- マシンB: 普段コードを書く端末。ここからマシンAへ verify を依頼する

比喩で言うと、マシンB は普段の机、マシンA は重い作業を引き受ける工房です。
`remote-ci` は、机の上で書いたものを工房へ持ち込み、確認が終わった成果物だけを持ち帰る導線です。

マシンB から 1 コマンドで「鍵認証確認 -> 同期 -> マシンA実行 -> 結果回収」まで行います。

`remote-ci` の同期元は、現在の作業リポジトリです。対象 repo のルートで実行するか、`--local-dir <path>` で明示してください。

`remote-ci` はローカル `rsync` コマンドをそのまま使います。macOS 既定の `openrsync` だと古く、進捗表示や互換性で不利です。

```bash
ci-self remote-ci --host <user>@<mac-mini-ip-or-host> --project-dir '~/dev/maakie-brainlab' --repo mt4110/maakie-brainlab
ci-self remote-ci --host <user>@<machine-a-host> -i ~/.ssh/id_ed25519_for_ci_runner --project-dir '~/dev/<project>' --repo <owner>/<repo>
```

例:

```bash
ci-self remote-ci --host ci@192.168.1.20 -i ~/.ssh/id_ed25519_for_ci_runner --project-dir '~/dev/<target-repo>' --repo <owner>/<repo>
```

`remote-ci` の実行内容:

1. SSH 公開鍵認証(password禁止)を検証
2. ローカル作業ツリーを Mac mini へ `rsync` 同期
3. (repo指定時)runner bootstrap をベストエフォート実行
4. Mac mini で `ops/ci/run_verify_full.sh` を実行
5. `verify-full.status` と `out/logs` をローカル `out/remote/<host>/` に回収
2. マシンB のローカル作業ツリーをマシンA の `--project-dir` へ `rsync` 同期
3. (`--repo` 指定時かつ remote `ci-self` 利用可能時)マシンA 上で `ci-self register` をベストエフォート実行
4. マシンA で、同梱の verify wrapper を SSH 経由で実行
5. `verify-full.status` と `out/logs` をマシンB の `out/remote/<host>/` に回収

注:

- bootstrap は remote 側で `gh auth status` が通るときだけ実行する
- remote 側で GitHub CLI 未導入または未ログインなら、bootstrap は warning ではなく skip され、standalone verify は続行する

同期時の既定:

- `target/`, `dist/`, `node_modules/`, `.venv/`, `coverage/`, `.next/` などの生成物ディレクトリと `.git/` は同期しない
- `rsync --info=progress2` で進捗を表示する
- ローカル `rsync` が `--info=progress2` 非対応なら `-h --progress` へ自動フォールバックする
- build/test が Git メタデータを直接参照する repo だけは `--sync-git-dir` で `.git/` 同期を有効化する

### 初回だけ必要な準備(マシンB -> マシンA)

1. マシンB で SSH 鍵を作る(未作成なら)

```bash
ssh-keygen -t ed25519 -a 100
```

2. マシンB の公開鍵をマシンA の `~/.ssh/authorized_keys` に登録する

```bash
cat ~/.ssh/id_ed25519_for_ci_runner.pub | ssh -i ~/.ssh/id_ed25519_for_ci_runner <user>@<machine-a-host> 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
```

3. パスワードなし SSH を確認する

```bash
ssh -i ~/.ssh/id_ed25519_for_ci_runner -o BatchMode=yes -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no <user>@<machine-a-host> true
```

4. 通ったら `remote-ci` を実行する

```bash
ci-self remote-ci --host <user>@<machine-a-host> -i ~/.ssh/id_ed25519_for_ci_runner --project-dir '~/dev/<project>' --repo <owner>/<repo>
```

### rsync バージョン注意

macOS 既定の `rsync` が古い場合があります。

```bash
rsync --version
```

古い例:

```text
openrsync: protocol version 29
rsync version 2.6.9 compatible
```

推奨:

```bash
brew install rsync
```

`alias rsync=...` だけでは `ci-self` の bash スクリプトには効かないことがあります。`PATH` の先頭に Homebrew 版を入れてください。

Apple Silicon の例:

```bash
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

確認例:

```text
rsync version 3.4.1 protocol version 32
```

公開鍵未登録時は、`remote-ci` 自体が `authorized_keys` 登録のヒントを出して停止します。

### 外出先からでも使える?

使える場合があります。`remote-ci` が必要としているのは「同一LAN」ではなく「SSH 到達性」です。

- 使える: マシンA に外出先から SSH で到達できる場合
- 典型例: Tailscale / VPN / ポート転送済みの自宅回線 / 固定IP など
- 使えない: マシンA へ SSH 経路が無い場合

`ci-self remote-ci` 自体は、外部公開やトンネル作成までは行いません。そこは別途ネットワーク設計が必要です。

### 今できること / まだできないこと

公開鍵未登録時は、`authorized_keys` 登録のヒントを出して停止します。
- できる: `--project-dir` と `--repo` を切り替えて、任意の CI 対象リポジトリをマシンA で実行
- できる: 未コミット変更を含むローカル作業ツリーを同期して verify を走らせる
- できる: `verify-full.status` と `out/logs` を手元へ回収する
- できる: 同一LANでも外出先でも、SSH 到達性があれば同じコマンドで使う
- まだできない: SSH パスワード認証での `remote-ci` 実行
- まだできない: SSH 経路が無い状態からの自動疎通確立
- まだできない: 複数プロジェクトの自動検出や自動振り分け。どの repo をどこで走らせるかは `--project-dir` / `.ci-self.env` で明示する

補足:

- `--host` は `ssh` の接続先文字列(`user@host` / IP / `~/.ssh/config` のHost別名)
- `--project-dir` に `~` を使う場合は `--project-dir '~/<path>'` のようにクオート
- `--host` は `ssh` の接続先文字列(`user@host` / IP / `~/.ssh/config` の Host 別名)
- `-i` / `--identity` で SSH 鍵ファイルを指定できる。毎回省略したい場合は `.ci-self.env` の `CI_SELF_REMOTE_IDENTITY` を使う
- `remote-ci` の同期元はデフォルトで「今いる repo」。別 repo を送りたい場合は `--local-dir` を使う
- `--project-dir` はマシンA 側の配置先パス。`~` を使う場合は `--project-dir '~/<path>'` のようにクオート
- `--local-dir` を使うと、マシンB 側の同期元を明示できる
- `--sync-git-dir` を付けると `.git/` も同期する。通常は不要
- `*.md`, `*.log`, `*.txt`, `build/`, `bin/`, `10MB超ファイル` は既定除外していない。tracked asset / fixture / source の可能性があるため
- remote `ci-self` 未導入でも verify 自体は動く。影響するのは bootstrap だけ
- `--repo` を省略すると bootstrap は skip されるが、同期済みプロジェクト上での standalone verify は実行できる
- runner 初期化/復旧専用の旧導線は `ci-self remote-up`

## さらに短縮する設定ファイル
Expand All @@ -62,11 +181,12 @@ ci-self config-init
例:

```env
CI_SELF_REPO=mt4110/maakie-brainlab
CI_SELF_REPO=<owner>/<repo>
CI_SELF_REF=main
CI_SELF_PROJECT_DIR=/Users/<you>/dev/maakie-brainlab
CI_SELF_REMOTE_HOST=<you>@mac-mini.local
CI_SELF_REMOTE_PROJECT_DIR=/Users/<you>/dev/maakie-brainlab
CI_SELF_PROJECT_DIR=/Users/<you>/dev/<target-repo>
CI_SELF_REMOTE_HOST=<you>@ci-runner.local
CI_SELF_REMOTE_PROJECT_DIR=/Users/<you>/dev/<target-repo>
CI_SELF_REMOTE_IDENTITY=/Users/<you>/.ssh/id_ed25519_for_ci_runner
CI_SELF_PR_BASE=main
```

Expand All @@ -76,7 +196,7 @@ CI_SELF_PR_BASE=main

- `ci-self up`: ローカル最短(register + run-focus)
- `ci-self focus`: run-focus 後、PR未作成なら自動作成し checks を監視
- `ci-self remote-ci`: 鍵必須・同期・Mac mini実行・結果回収を1コマンドで実行
- `ci-self remote-ci`: 鍵必須・同期・別端末での verify 実行・結果回収を1コマンドで実行
- `ci-self doctor --fix`: 依存/gh auth/colima/docker/runner_health を診断し可能な範囲で修復
- `ci-self doctor --repo-dir <path>`: `flake.nix` リポジトリの Nix 到達性も含めて診断
- `ci-self remote-up`: SSH先で register + run-focus(同期しない旧導線)
Expand Down
168 changes: 168 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
# runner-kit (self-hosted runner + colima + docker)

`runner-kit` is a macOS-oriented toolkit for operating a self-hosted GitHub Actions runner with Colima and Docker.

## Quick Start

Install the CLI once:

```bash
cd ~/dev/ci-self-runner
bash ops/ci/install_cli.sh
```

Run it from the CI target repository:

```bash
cd ~/dev/<target-repo>
ci-self up
```

`ci-self up` runs `register + run-focus` in sequence.

## Use A Remote CI Runner In One Command

- Machine A: the box that hosts the self-hosted runner, Colima, and Docker
- Machine B: the box where you normally write code

Think of Machine B as your desk, and Machine A as the workshop.
`remote-ci` moves your current worktree from the desk to the workshop, runs verification there, then brings back only the results.

```bash
ci-self remote-ci --host <user>@<machine-a-host> -i ~/.ssh/id_ed25519_for_ci_runner --project-dir '~/dev/<target-repo>' --repo <owner>/<repo>
```

What `remote-ci` does:

1. Verifies SSH public-key auth
2. Syncs the local worktree from Machine B to `--project-dir` on Machine A
3. Runs bootstrap on Machine A only when `--repo` is set and remote `gh auth status` succeeds
4. Runs the bundled verify wrapper over SSH on Machine A
5. Collects `verify-full.status` and `out/logs` into `out/remote/<host>/` on Machine B

Defaults during sync:

- Generated directories such as `target/`, `dist/`, `node_modules/`, `.venv/`, `coverage/`, and `.next/` are excluded
- `.git/` is excluded by default
- `rsync --info=progress2` is used when available
- If local `rsync` is too old, it falls back to `-h --progress`
- Use `--sync-git-dir` only when your build or tests need Git metadata directly

Notes:

- If remote `gh` is missing or not authenticated, bootstrap is skipped instead of treated as a hard failure
- Verification itself still continues even when bootstrap is skipped
- `remote-ci` syncs the current repository by default; use `--local-dir <path>` when you want to sync a different local path

## First-Time Setup For Machine B -> Machine A

Generate an SSH key on Machine B if needed:

```bash
ssh-keygen -t ed25519 -a 100
```

Append the public key to `~/.ssh/authorized_keys` on Machine A:

```bash
cat ~/.ssh/id_ed25519_for_ci_runner.pub | ssh -i ~/.ssh/id_ed25519_for_ci_runner <user>@<machine-a-host> 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
```

Confirm passwordless SSH:

```bash
ssh -i ~/.ssh/id_ed25519_for_ci_runner -o BatchMode=yes -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no <user>@<machine-a-host> true
```

Then run:

```bash
ci-self remote-ci --host <user>@<machine-a-host> -i ~/.ssh/id_ed25519_for_ci_runner --project-dir '~/dev/<target-repo>' --repo <owner>/<repo>
```

## rsync Note

macOS ships an older `rsync` in some environments.

```bash
rsync --version
```

Recommended:

```bash
brew install rsync
```

An `alias rsync=...` is often not enough for the `ci-self` bash script. Prefer putting Homebrew first in `PATH`.

Apple Silicon example:

```bash
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

## Can I Use It Away From Home?

Sometimes, yes. The real requirement is not “same LAN”, but “SSH reachability”.

- Works when Machine A is reachable over SSH
- Common setups: Tailscale, VPN, port forwarding, fixed-IP home network
- Does not work when no SSH route exists

`remote-ci` does not create tunnels or expose the machine by itself.

## What It Can And Cannot Do

- Can: run any target repository on Machine A by changing `--project-dir` and `--repo`
- Can: sync uncommitted local changes and verify them remotely
- Can: collect `verify-full.status` and `out/logs` back to Machine B
- Can: use the same command both on a local network and remotely, as long as SSH works
- Cannot yet: run over password-based SSH
- Cannot yet: create SSH reachability for you when no route exists
- Cannot yet: auto-detect or auto-route multiple repositories without explicit config

## Optional Config File

`ci-self` auto-loads `.ci-self.env`.

Create it with:

```bash
ci-self config-init
```

Example:

```env
CI_SELF_REPO=<owner>/<repo>
CI_SELF_REF=main
CI_SELF_PROJECT_DIR=/Users/<you>/dev/<target-repo>
CI_SELF_REMOTE_HOST=<you>@ci-runner.local
CI_SELF_REMOTE_PROJECT_DIR=/Users/<you>/dev/<target-repo>
CI_SELF_REMOTE_IDENTITY=/Users/<you>/.ssh/id_ed25519_for_ci_runner
CI_SELF_PR_BASE=main
```

## Main Commands

- `ci-self up`: fastest local path (`register + run-focus`)
- `ci-self focus`: runs `run-focus`, creates a PR if missing, then watches checks
- `ci-self remote-ci`: SSH-required sync + remote verify + result collection in one command
- `ci-self doctor --fix`: checks dependencies, `gh auth`, Colima, Docker, and runner health
- `ci-self remote-up`: older SSH path for `register + run-focus` without syncing
- `ci-self config-init`: generates a `.ci-self.env` template

## Security Assumptions

- Intended for single-owner personal operation
- Self-hosted execution is gated by `SELF_HOSTED_OWNER`
- For external collaborators or fork PRs, review `docs/ci/SECURITY_HARDENING_TASK.md` first

## More

- `README.md`
- `docs/ci/QUICKSTART.md`
- `docs/ci/RUNBOOK.md`
- `docs/ci/SECURITY_HARDENING_TASK.md`
Loading
Loading