Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion doc/CatalogVersioning.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ fce catalog update --solution MyApp.sln

This extracts the catalog, projects it into its snapshot, and writes `errors-baseline.json` (override with `--baseline`, or set `baseline` in `fce.json`). **Commit this file**: it is the accepted contract, and every change to it goes through code review like any other contract change.

**In CI/CD**, seed it automatically the first time so no one has to remember to bootstrap it — create and commit the file only when it is missing. This belongs on a push to your default branch, and needs a token that can push:

```yaml
# Runs on push to main; needs: permissions: { contents: write }.
- name: Seed the error-catalog baseline if missing
run: |
if [ ! -f errors-baseline.json ]; then
fce catalog update --solution MyApp.sln
git add errors-baseline.json
git -c user.name='github-actions[bot]' \
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
commit -m 'chore: seed the error-catalog baseline'
git push
fi
```

Prefer a one-time local bootstrap (run `fce catalog update` and commit) if you would rather keep CI read-only — only `catalog diff` truly needs to run on every pull request.

## 🔍 Detect drift in CI

```bash
Expand All @@ -41,7 +59,8 @@ The command extracts the current catalog, compares it against the baseline, and
| --- | --- |
| `0` | No change at or above the `--fail-on` threshold. |
| `2` | The contract drifted: at least one change reaches the threshold. |
| `1` | Execution error (missing baseline, failed extraction, …). |
| `1` | Execution error — a missing baseline, a failed extraction, or a baseline written by a newer schema (see below). |
| `130` | Cancelled before completing (Ctrl+C). |

`--fail-on` selects the policy: `breaking` (default), `any` (any change at all fails, including additions), or `none` (report only). `--report` selects the output: `text` (default), `markdown` (ready to post as a pull-request comment) or `json` (for tooling).

Expand All @@ -68,6 +87,53 @@ fce catalog update --solution MyApp.sln

The command summarizes what it absorbs (`1 breaking, 2 compatible and 0 documentation change(s) accepted`), and the pull request then shows the baseline diff — a removed code appears as a removed line. The accident becomes impossible; the deliberate change becomes visible and reviewable. This is the same discipline as a public-API baseline file, applied to the error catalog.

**In CI/CD**, make accepting a change one action instead of a manual local step: on a pull request labelled `accept-contract-change`, regenerate the baseline and commit it back onto the PR branch, so the change lands as an explicit, reviewable diff (works for same-repository branches; from a fork, run `fce catalog update` locally and push):

```yaml
# .github/workflows/error-catalog-accept.yml
on:
pull_request:
types: [labeled]

jobs:
accept:
if: github.event.label.name == 'accept-contract-change'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
# Make fce available on the runner (see the full example below).
- name: Regenerate and commit the baseline
run: |
fce catalog update --solution MyApp.sln
git add errors-baseline.json
if git diff --cached --quiet; then
echo 'Baseline already up to date — nothing to accept.'
else
git -c user.name='github-actions[bot]' \
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
commit -m 'chore: accept error-catalog contract change'
git push
fi
```

For a purely local flow, the same two lines behind a `make accept-errors` target work just as well.

## 🛡️ Baseline resilience & schema versioning

The baseline is a checked-in file, so over a project's life it can be corrupted by a bad merge or produced by a different version of the tool. `fce catalog update` handles each case deliberately rather than silently:

* **A corrupt or unreadable baseline is regenerated, never fatal.** Updating is exactly how a baseline is (re)built, so an existing file that cannot be parsed is rewritten from the current catalog with a warning — a broken baseline never blocks you.
* **A baseline written by a _newer_ schema is refused, never downgraded.** Every snapshot carries a `schema` version. If a teammate committed a baseline with a newer tool, an older tool will not overwrite it with an older schema — that would silently drop information — so it stops with an error telling you to upgrade. `fce catalog diff` refuses it the same way. Upgrading the tool, or aligning versions across the team, resolves it.

So `fce catalog update` exits `0` when the baseline is created, already up to date, or refreshed (including a self-healed one); `1` on an execution error or a newer-schema baseline; and `130` if cancelled.

## ⚙️ Snapshots without a baseline

Two more ways to produce and compare snapshots:
Expand Down
68 changes: 67 additions & 1 deletion doc/CatalogVersioning.fr.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ fce catalog update --solution MyApp.sln

Cette commande extrait le catalogue, le projette en snapshot et écrit `errors-baseline.json` (modifiable avec `--baseline`, ou via `baseline` dans `fce.json`). **Commitez ce fichier** : c'est le contrat accepté, et chaque modification passe en revue de code comme n'importe quel autre changement de contrat.

**En CI/CD**, initialisez-la automatiquement au premier passage pour que personne n'ait à y penser — créez et commitez le fichier uniquement s'il est absent. Cela relève d'un push sur votre branche par défaut et nécessite un jeton capable de pousser :

```yaml
# Se déclenche sur push vers main ; nécessite : permissions: { contents: write }.
- name: Seed the error-catalog baseline if missing
run: |
if [ ! -f errors-baseline.json ]; then
fce catalog update --solution MyApp.sln
git add errors-baseline.json
git -c user.name='github-actions[bot]' \
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
commit -m 'chore: seed the error-catalog baseline'
git push
fi
```

Préférez une initialisation locale unique (lancez `fce catalog update` puis commitez) si vous voulez garder la CI en lecture seule — seul `catalog diff` a vraiment besoin de s'exécuter à chaque pull request.

## 🔍 Détecter la dérive en CI

```bash
Expand All @@ -41,7 +59,8 @@ La commande extrait le catalogue courant, le compare à la baseline et écrit un
| --- | --- |
| `0` | Aucun changement au niveau du seuil `--fail-on` ou au-dessus. |
| `2` | Le contrat a dérivé : au moins un changement atteint le seuil. |
| `1` | Erreur d'exécution (baseline manquante, extraction en échec, …). |
| `1` | Erreur d'exécution — baseline manquante, extraction en échec, ou baseline écrite par un schéma plus récent (voir plus bas). |
| `130` | Interrompu avant la fin (Ctrl+C). |

`--fail-on` choisit la politique : `breaking` (défaut), `any` (tout changement fait échouer, y compris les ajouts) ou `none` (rapport seul). `--report` choisit la sortie : `text` (défaut), `markdown` (prêt à poster en commentaire de pull request) ou `json` (pour l'outillage).

Expand All @@ -68,6 +87,53 @@ fce catalog update --solution MyApp.sln

La commande résume ce qu'elle absorbe (`1 breaking, 2 compatible and 0 documentation change(s) accepted`), et la pull request montre alors le diff de la baseline — un code supprimé apparaît comme une ligne supprimée. L'accident devient impossible ; le changement délibéré devient visible et relisible. C'est la même discipline qu'un fichier de baseline d'API publique, appliquée au catalogue d'erreurs.

**En CI/CD**, faites de l'acceptation une action unique plutôt qu'une étape locale manuelle : sur une pull request portant le label `accept-contract-change`, régénérez la baseline et recommitez-la sur la branche de la PR, pour que le changement apparaisse comme un diff explicite et relisible (fonctionne pour les branches du même dépôt ; depuis un fork, lancez `fce catalog update` en local et poussez) :

```yaml
# .github/workflows/error-catalog-accept.yml
on:
pull_request:
types: [labeled]

jobs:
accept:
if: github.event.label.name == 'accept-contract-change'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
# Rendez fce disponible sur le runner (voir l'exemple complet plus bas).
- name: Regenerate and commit the baseline
run: |
fce catalog update --solution MyApp.sln
git add errors-baseline.json
if git diff --cached --quiet; then
echo 'Baseline already up to date — nothing to accept.'
else
git -c user.name='github-actions[bot]' \
-c user.email='41898282+github-actions[bot]@users.noreply.github.com' \
commit -m 'chore: accept error-catalog contract change'
git push
fi
```

Pour un flux purement local, les deux mêmes lignes derrière une cible `make accept-errors` font tout aussi bien l'affaire.

## 🛡️ Résilience de la baseline & versionnage du schéma

La baseline est un fichier versionné : au fil de la vie d'un projet, elle peut être corrompue par un merge malheureux ou produite par une version différente de l'outil. `fce catalog update` traite chaque cas de façon délibérée plutôt que silencieuse :

* **Une baseline corrompue ou illisible est régénérée, jamais fatale.** Mettre à jour, c'est précisément la façon de (re)construire une baseline : un fichier existant impossible à parser est réécrit à partir du catalogue courant, avec un avertissement — une baseline cassée ne vous bloque jamais.
* **Une baseline écrite par un schéma _plus récent_ est refusée, jamais rétrogradée.** Chaque snapshot porte une version de `schema`. Si un collègue a commité une baseline avec un outil plus récent, un outil plus ancien ne l'écrasera pas avec un schéma plus ancien — cela supprimerait silencieusement de l'information — : il s'arrête avec une erreur vous invitant à mettre à jour. `fce catalog diff` la refuse de la même manière. Mettre à jour l'outil, ou aligner les versions dans l'équipe, résout le problème.

Ainsi `fce catalog update` sort `0` quand la baseline est créée, déjà à jour ou rafraîchie (y compris auto-réparée) ; `1` sur une erreur d'exécution ou une baseline de schéma trop récent ; et `130` en cas d'interruption.

## ⚙️ Des snapshots sans baseline

Deux autres façons de produire et comparer des snapshots :
Expand Down