Skip to content

Przewodniki

Uruchamianie w CI

Bramkowanie CI opisuje politykę wydań i znaczenie każdego kodu wyjścia. Ta strona dotyczy tego, co dzieje się wewnątrz zadania CI: jak zainstalować tam Oloproof, gdzie znajdują się dowody w trakcie działania zadania, jak odczytać wynik bez parsowania tabeli i jak porównać pull request z gałęzią, do której jest kierowany.

Kod wyjścia jest bramką

oloproof run kończy działanie z kodem swojej bramki. Krok CI, który go uruchamia, kończy się niepowodzeniem, gdy bramka blokuje, co zwykle jest pożądane i nie wymaga dodatkowej konfiguracji:

KodKrok CI powinien
0przejść
1zakończyć się niepowodzeniem: reguła nie przeszła
2zakończyć się niepowodzeniem jako zepsuty build: konfiguracja była błędna i nic nie zmierzono
3zakończyć się niepowodzeniem lub ostrzec: zestaw nie mógł rozstrzygnąć
4zakończyć się niepowodzeniem i przekazać sprawę człowiekowi
5zakończyć się niepowodzeniem jako zepsuty build: uruchomienie się nie zakończyło

Kod 3 jest tym, o który zespoły się spierają. Domyślna polityka blokuje przy nim, ponieważ zestaw zbyt mały, by rozstrzygnąć, nie wykazał, że zmiana jest bezpieczna. Zespół, który chce, by zadanie kończyło się na zielono, podczas gdy rozbudowuje swój zestaw, może to zapisać w polityce, zamiast ignorować kod wyjścia:

version: 1
block_on: [FAIL, MANUAL_REVIEW]
warn_on: [INSUFFICIENT_EVIDENCE]
rules:
  - id: exact-label-floor
    metric: exact_label
    min: 0.70

To samo zapisane uruchomienie examples/support_bot/, które przy własnej polityce blokuje z kodem 3, przy tej polityce:

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)

Kończy się kodem 0. Decyzja się nie zmienia. Zmieniła się tylko akcja wydania, a zmieniła się dlatego, że tak stanowi plik podlegający przeglądowi.

Odczytywanie wyniku jako danych

--json zapisuje jedno zdarzenie JSON na wiersz na standardowe wyjście, a tabele dla ludzi na standardowe wyjście błędów, dzięki czemu log CI zachowuje tabele, a skrypt odczytuje zdarzenia. Po zapisaniu do run.ndjson identyfikator uruchomienia znajduje się w każdym wierszu, a ostatni wiersz zawiera kod wyjścia:

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}

Postęp i współbieżność wymienia wszystkie typy zdarzeń.

Gdzie znajdują się dowody

Uruchomienie jest zapisywane w .oloproof/store.sqlite obok pliku oloproof.yaml, z którego zostało uruchomione, a oloproof init dodaje .oloproof/ do .gitignore. Zadanie CI zaczyna z pustym magazynem, więc każde zadanie ponownie wykonuje każdy przypadek i nic z jednego zadania nie jest widoczne w następnym.

Ma to największe znaczenie dla porównania, które wymaga obu uruchomień w jednym magazynie. Dwie kopie robocze projektu mają każda własny magazyn, więc uruchomienia punktu odniesienia z jednej nie da się znaleźć z drugiej:

Configuration error: unknown run 'run_01M3C3XSX9KY5T8VFZXA1CVBES'

OLOPROOF_HOME kieruje każde polecenie do jednego magazynu, niezależnie od tego, gdzie znajduje się jego oloproof.yaml. Wskazany katalog zawiera .oloproof/store.sqlite.

Instalowanie Oloproof w zadaniu

Oloproof nie jest publikowany w indeksie pakietów, więc nie istnieje wiersz pip install, który pobrałby go po nazwie. Zadanie instaluje go z kopii roboczej repozytorium Oloproof, tak samo jak robi to programista: actions/checkout z repository: wskazującym miejsce, w którym znajduje się kopia tego repozytorium używana przez zespół, oraz token:, który może je odczytać, jeśli jest prywatne. Katalog główny repozytorium buduje pakiet, a pakiet udostępnia polecenie oloproof.

Porównywanie pull requesta z jego gałęzią bazową

Należy pobrać gałąź bazową i pull request obok siebie, uruchomić każde z nich w tym samym magazynie i porównać:

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 i OLOPROOF_REPO_TOKEN to symbole zastępcze dla kopii repozytorium i sekretu, który może ją odczytać. Oba uruchomienia mają || true, ponieważ ich własne bramki nie są tutaj przedmiotem pytania; jest nim kod wyjścia porównania.

Te same kroki na laptopie, z wygenerowanym projektem pobranym dwukrotnie:

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)

Oba uruchomienia muszą dotyczyć tego samego zestawu. Pull request, który edytuje przypadek, zmienia skrót zestawu, a porównanie odmawia działania, zamiast parować przypadki, które nie są już tym samym przypadkiem:

Configuration error: runs 'run_01M3C3XXVZ1X0J2PR1ZW1WVGVZ' and 'run_01M3C3XW7X64B0Z0ACZV27WSW6' used different suites (sha256:baff4f101901d9a37cd440f99b9a70032f9488891b4f590f18a81017c26ba794 and sha256:2011286a7ec00c8c31560bb6d037b54a501a15f6251ac7c2d578d0c40e226d72); comparisons pair scenario by scenario over one suite

Porównanie uruchomienia, które się nie zakończyło, kończy się kodem 5, tak samo jak bramka dla takiego uruchomienia: nie ma sparowanego wyniku, na podstawie którego można by rozstrzygnąć.

Co dalej

  • Bramkowanie CI opisuje politykę i kolejność, w jakiej raportowane są kody

wyjścia.