Skip to content

ガイド

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.70

examples/support_bot/ の同じ保存済み実行は、それ自身のポリシーでは 3 でブロックされますが、このポリシーでは次のようになります。

oloproof gate RUN_ID --policy advisory.yaml
exact-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.ndjson
run_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.yaml

YOUR_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 で終了します。判定の対象となる対応付けられた結果がないからです。

次に読むページ

  • CI のゲート では、ポリシーと、終了コードが報告される順序を説明しています。
  • 比較ルール では、比較ポリシーで何を問えるかを説明しています。