Skip to content

Guides

Exécution en CI

Porte de CI couvre la politique de publication et la signification de chaque code de sortie. Cette page traite de ce qui se passe à l'intérieur d'un job de CI : comment y installer Oloproof, où résident les preuves pendant l'exécution du job, comment lire un résultat sans analyser un tableau, et comment comparer une pull request à la branche qu'elle cible.

Le code de sortie est le gate

oloproof run se termine selon son gate. Une étape de CI qui l'exécute échoue lorsque le gate bloque, ce qui est généralement le comportement voulu et ne demande aucun câblage supplémentaire :

CodeUne étape de CI devrait
0réussir
1échouer : une règle a échoué
2échouer comme un build cassé : la configuration était erronée et rien n'a été mesuré
3échouer, ou avertir : la suite n'a pas pu trancher
4échouer et renvoyer vers une personne
5échouer comme un build cassé : l'exécution ne s'est pas terminée

Le code 3 est celui dont les équipes débattent. La politique par défaut bloque sur ce code, car une suite trop petite pour trancher n'a pas montré que la modification est sûre. Une équipe qui veut que le job passe au vert pendant qu'elle agrandit sa suite peut le dire dans la politique, plutôt qu'en ignorant le code de sortie :

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

La même exécution stockée de examples/support_bot/, qui bloque avec 3 sous sa propre politique, sous celle-ci :

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)

Elle se termine avec 0. La décision est inchangée. Seule l'action de publication a changé, et elle a changé parce qu'un fichier soumis à revue le dit.

Lire le résultat comme des données

--json écrit un événement JSON par ligne sur la sortie standard et les tableaux lisibles sur la sortie d'erreur, de sorte qu'un journal de CI conserve les tableaux et qu'un script lit les événements. Enregistré dans run.ndjson, l'identifiant de l'exécution figure sur chaque ligne, et la dernière ligne porte le code de sortie :

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}

Progression et concurrence liste tous les types d'événements.

Où résident les preuves

Une exécution est stockée dans .oloproof/store.sqlite à côté du oloproof.yaml à partir duquel elle a été lancée, et oloproof init ajoute .oloproof/ au .gitignore. Un job de CI démarre avec un stockage vide : chaque job réexécute donc chaque cas, et rien d'un job n'est visible du suivant.

Cela compte surtout pour une comparaison, qui a besoin des deux exécutions dans un même stockage. Deux extractions d'un projet ont chacune leur propre stockage, si bien qu'une exécution de référence faite dans l'une est introuvable depuis l'autre :

Configuration error: unknown run 'run_01M3C3XSX9KY5T8VFZXA1CVBES'

OLOPROOF_HOME fait pointer toutes les commandes vers un même stockage, où que se trouve leur oloproof.yaml. Le répertoire qu'elle désigne contient .oloproof/store.sqlite.

Installer Oloproof dans un job

Oloproof n'est publié sur aucun index de paquets : aucune ligne pip install ne le récupère par son nom. Un job l'installe à partir d'une extraction du dépôt Oloproof, comme le fait un développeur : actions/checkout avec un repository: désignant l'endroit où se trouve la copie de ce dépôt de votre équipe, et un token: capable de le lire s'il est privé. La racine du dépôt construit le paquet, et le paquet fournit la commande oloproof.

Comparer une pull request à sa base

Extrayez côte à côte la branche de base et la pull request, exécutez chacune dans le même stockage, puis comparez :

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 et OLOPROOF_REPO_TOKEN sont des valeurs à remplacer par votre copie du dépôt et par un secret capable de la lire. Les deux exécutions portent || true parce que leurs propres gates ne sont pas la question ici ; c'est le code de sortie de la comparaison qui l'est.

Les mêmes étapes sur un ordinateur portable, avec le projet généré extrait deux fois :

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)

Les deux exécutions doivent porter sur la même suite. Une pull request qui modifie un cas change l'empreinte de la suite, et la comparaison refuse plutôt que d'apparier des cas qui ne sont plus le même cas :

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

La comparaison d'une exécution qui ne s'est pas terminée se termine avec 5, comme un gate sur une telle exécution : il n'y a aucun résultat apparié sur lequel décider.

Pour aller plus loin

  • Porte de CI couvre la politique et l'ordre dans lequel les codes de sortie sont

signalés.

demander.