ガイド
CI での実行
CI のゲート では、リリースポリシーと各終了コードの意味を説明しています。このページで扱うのは CI ジョブの内部で起きる部分です。そこに Oloproof をインストールする方法、ジョブの実行中にエビデンスがどこに置かれるか、表をパースせずに結果を読む方法、そしてプルリクエストをその対象ブランチと比較する方法です。
終了コードがゲートです
oloproof run はゲートの結果で終了します。これを実行する CI ステップはゲートがブロックすると失敗します。通常はそれが望ましい動作であり、追加の配線は必要ありません。
| コード | CI ステップがすべきこと |
|---|---|
| 0 | 成功 |
| 1 | 失敗: ルールが不合格になった |
| 2 | ビルド破損として失敗: 設定が誤っており、何も測定されていない |
| 3 | 失敗、または警告: スイートが判定できなかった |
| 4 | 失敗させ、人に回す |
| 5 | ビルド破損として失敗: 実行が完了しなかった |
チームの間で議論になるのはコード 3 です。デフォルトのポリシーはこれでブロックします。判定するには小さすぎるスイートは、その変更が安全であることを示していないからです。スイートを育てている間はジョブを緑にしたいチームは、終了コードを無視するのではなく、ポリシーでそう宣言できます。
version: 1
block_on: [FAIL, MANUAL_REVIEW]
warn_on: [INSUFFICIENT_EVIDENCE]
rules:
- id: exact-label-floor
metric: exact_label
min: 0.70examples/support_bot/ の同じ保存済み実行は、それ自身のポリシーでは 3 でブロックされますが、このポリシーでは次のようになります。
oloproof gate RUN_ID --policy advisory.yamlexact-label-floor: INSUFFICIENT_EVIDENCE (interval_overlaps_threshold)
about 1614 more cases would decide it, if the observed rate holds (1632 in total)終了コードは 0 です。判定は変わっていません。動いたのはリリースアクションだけであり、それはレビュー対象のファイルがそう定めているから動いたのです。
結果をデータとして読む
--json は 1 行につき 1 つの JSON イベントを標準出力に書き、人間向けの表を標準エラー出力に書きます。そのため CI のログには表が残り、スクリプトはイベントを読めます。run.ndjson に保存すると、実行の ID はすべての行にあり、最後の行に終了コードが入ります。
jq -r 'select(.type == "run_started") | .run_id' run.ndjson
jq -c 'select(.type == "run_finished")' run.ndjsonrun_01M3C3WS0SBTFAG55M7ECM1EZ4
{"run_id":"run_01M3C3WS0SBTFAG55M7ECM1EZ4","timestamp":"2026-09-25T11:06:03.646415Z","type":"run_finished","status":"DECIDED","completeness":"COMPLETE","exit_code":3}進捗と並行処理 にすべてのイベントの種類が載っています。
エビデンスの置き場所
実行は、それを実行した oloproof.yaml の隣の .oloproof/store.sqlite に保存され、oloproof init は .oloproof/ を .gitignore に追加します。CI ジョブは空のストアで始まるため、どのジョブもすべてのケースを再実行し、あるジョブの内容は次のジョブからは見えません。
これが最も問題になるのは比較です。比較には両方の実行が 1 つのストアに入っている必要があります。プロジェクトを 2 つチェックアウトすると、それぞれが独自のストアを持つため、一方のベースライン実行はもう一方からは見つかりません。
Configuration error: unknown run 'run_01M3C3XSX9KY5T8VFZXA1CVBES'OLOPROOF_HOME は、oloproof.yaml がどこにあっても、すべてのコマンドを 1 つのストアに向けます。指定したディレクトリに .oloproof/store.sqlite が置かれます。
ジョブへの Oloproof のインストール
Oloproof はパッケージインデックスに公開されていないため、名前で取得する pip install の 1 行はありません。ジョブは、開発者と同じ方法で、Oloproof リポジトリのチェックアウトからインストールします。actions/checkout の repository: にチームのそのリポジトリのコピーがある場所を指定し、非公開であれば読み取り可能な token: を渡します。リポジトリのルートがパッケージをビルドし、そのパッケージが oloproof コマンドを提供します。
プルリクエストをそのベースと比較する
ベースブランチとプルリクエストを並べてチェックアウトし、それぞれを同じストアに実行して、比較します。
name: oloproof
on: pull_request
jobs:
evaluate:
runs-on: ubuntu-latest
env:
OLOPROOF_HOME: ${{ github.workspace }}/evidence
steps:
- uses: actions/checkout@v4
with:
path: pr
- uses: actions/checkout@v4
with:
ref: ${{ github.base_ref }}
path: main
- uses: actions/checkout@v4
with:
repository: YOUR_ORG/Oloproof
token: ${{ secrets.OLOPROOF_REPO_TOKEN }}
path: oloproof-src
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: python -m pip install ./oloproof-src
- run: mkdir -p "$OLOPROOF_HOME"
- run: oloproof run --config main/oloproof.yaml --json > base.ndjson || true
- run: oloproof run --config pr/oloproof.yaml --json > cand.ndjson || true
- name: compare
run: |
candidate=$(jq -r 'select(.type == "run_started") | .run_id' cand.ndjson)
baseline=$(jq -r 'select(.type == "run_started") | .run_id' base.ndjson)
oloproof compare "$candidate" "$baseline" --config pr/oloproof.yaml --policy pr/compare.yamlYOUR_ORG/Oloproof と OLOPROOF_REPO_TOKEN は、リポジトリのコピーと、それを読み取れるシークレットのプレースホルダーです。2 つの実行に || true が付いているのは、それぞれのゲートはここでの問題ではないからです。問題になるのは比較の終了コードです。
同じ手順を、雛形から作成したプロジェクトを 2 回チェックアウトしてノート PC で実行した結果です。
Comparison sha256:31ac104779bda1726ba55b661107cbe256fae5f1d831c79b1283a07651b58cbf of run_01M3C3XX4TM0WSZW8K81PHRGAW against run_01M3C3XW7X64B0Z0ACZV27WSW6 · 30 paired cases
exact_label: +0.0 points [-16.5, +16.5] · 30 paired · 0 missing · 0 excluded
Decisions
no-regression exact_label non-inferiority, margin 5.0 points INSUFFICIENT_EVIDENCE interval_overlaps_margin
Gate: BLOCK (exit 3)両方の実行は同じスイートに対するものでなければなりません。ケースを編集するプルリクエストはスイートのダイジェストを変えます。比較は、もはや同じケースではなくなったケースを対にするのではなく、拒否します。
Configuration error: runs 'run_01M3C3XXVZ1X0J2PR1ZW1WVGVZ' and 'run_01M3C3XW7X64B0Z0ACZV27WSW6' used different suites (sha256:baff4f101901d9a37cd440f99b9a70032f9488891b4f590f18a81017c26ba794 and sha256:2011286a7ec00c8c31560bb6d037b54a501a15f6251ac7c2d578d0c40e226d72); comparisons pair scenario by scenario over one suite完了しなかった実行の比較は、1 つの実行に対するゲートと同じく 5 で終了します。判定の対象となる対応付けられた結果がないからです。