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은 한 줄에 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 작업은 빈 저장소로 시작하므로, 모든 작업이 모든 케이스를 다시 실행하고 한 작업의 결과는 다음 작업에서 보이지 않습니다.

이것이 가장 중요한 것은 두 실행이 한 저장소에 있어야 하는 비교입니다. 프로젝트를 두 번 체크아웃하면 각각 자기 저장소를 가지므로, 한쪽에서 만든 기준선 실행을 다른 쪽에서 찾을 수 없습니다.

Configuration error: unknown run 'run_01M3C3XSX9KY5T8VFZXA1CVBES'

OLOPROOF_HOME은 oloproof.yaml이 어디에 있든 모든 명령이 하나의 저장소를 가리키게 합니다. 이 변수가 지정하는 디렉터리에 .oloproof/store.sqlite가 저장됩니다.

작업에 Oloproof 설치하기

Oloproof는 패키지 인덱스에 게시되어 있지 않으므로, 이름으로 가져오는 pip install 한 줄은 없습니다. 작업은 개발자와 같은 방식으로 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은 여러분의 저장소 사본과 그것을 읽을 수 있는 시크릿을 위한 자리 표시자입니다. 두 실행에 || true가 붙은 것은 각 실행 자체의 게이트가 여기서의 관심사가 아니기 때문입니다. 중요한 것은 비교의 종료 코드입니다.

같은 단계를 노트북에서, 스캐폴드된 프로젝트를 두 번 체크아웃해 실행하면 다음과 같습니다.

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

완료되지 않은 실행의 비교는 그런 실행에 대한 게이트와 마찬가지로 5로 종료합니다. 결정을 내릴 짝지은 결과가 없기 때문입니다.

다음 단계

  • CI 게이트는 정책과 종료 코드가 보고되는 순서를 다룹니다.
  • 비교 규칙은 비교 정책이 물을 수 있는 것을 다룹니다.