fix(release): apply the review follow-ups of the release-deps stack, drop the linux-x86_64 key #418

Merged
maximus merged 5 commits from review-followups-release-deps into main 2026-10-12 19:33:03 +00:00
Owner

Refs #320, #345, #376, #358

PR de suivis, empilée sur #417 (#358), #416 (#320), #415 (#345) puis #414 (#376) : elle ne montre que son propre diff. Les têtes de ces quatre PR, revues et approuvées, n'ont pas bougé.

Corrections demandées par Max le 2026-10-11 (« retire le repli, corrige les suggestions puis merge »), après les quatre /pr-review (commentaires 22219, 22287, 22437, 22470). Cette PR modifie la garde placée avant le DELETE du latest.json publié : selon /merge-stack, un tel changement passe par sa propre revue avant le merge de la pile.

Ce qui change

Clé générique linux-x86_64 retirée de latest.json (décision de Max, #320) — 230ecd8

  • scripts/build-latest-json.sh n'écrit plus que linux-x86_64-deb, linux-x86_64-rpm et windows-x86_64 ; le filtre de contrôle et verify-release.sh exigent ces trois clés.
  • Sans effet sur les installations .deb, .rpm et Windows : get_urls (tauri-plugin-updater 2.10.0, relu) cherche d'abord {os}-{arch}-{installer}, et les 64 tags qui embarquent l'updater verrouillent tous plugin 2.10.0 et tauri-utils 2.8.2.
  • Les derniers lecteurs de la clé, les AppImage v0.4.3 à v0.4.5 et un binaire lancé hors de son paquet, ne savaient pas installer le .deb qu'elle servait : ils reçoivent désormais TargetsNotFound à la vérification, rien n'est installé. La v0.4.2 n'en était pas (son endpoint répond 404), correction du point 4 de la revue 22437.
  • docs/qa-update-cycle.md, docs/architecture.md, skill /release, STATE.md (puce de release) et CHANGELOG FR/EN (phrase pour ces AppImage) à jour.

Contrôle de latest.json partagé, version épinglée (revue 22437, points 1 et 2) — ba3db7c

  • Le contrôle d'avant le DELETE passe de release.yml à scripts/check-latest-json.jq, appliqué par jq -e --arg version … -f.
  • scripts/build-latest-json.test.mjs applique ce même filtre à chaque PR : sortie du script, mauvaise version, dix manifestes fautifs, forme publiée jusqu'à la v0.17.1, JSON invalide. Il compare aussi les listes de clés du script, du filtre et de verify-release.sh.
  • Deux cas épinglent l'argument de version : 0.18.0 doit ressortir en 0.18.0, une version vide doit échouer (les deux mutations survivantes de la revue).

ADR 0023 et garde windows-sys (revue 22287) — 08d54fd

  • Prémisse corrigée : le conteneur a python3 (dépendance transitive des paquets apt, run 517) ; awk reste, parce que mawk fait partie de l'image de base.
  • « PR #344 (deuxième dérive) » ; le commentaire sur le code de sortie d'awk dit ce que ce test attrape seul ; deux puces de procédure ajoutées (bloc sans arête windows-sys, second bloc hors borne) ; la limite du canari est écrite.
  • /release rejoue le garde juste après l'édition de Cargo.lock (étape 2), puisque le commit de release n'a pas de PR.

Commentaires (revue 22219) — d1d025d

  • audit.yml : la mesure de concurrency ne couvre pas schedule ni workflow_dispatch.
  • reportService.test.ts : la CI tourne sous Node 24 depuis #376 (le harnais node:sqlite relève de #392).
  • Skill /release : /actions/tasks n'ignore limit que sans page (mesuré : 613 lignes sans page, 5 avec ?limit=5&page=2, 30 avec ?page=2).

npm audit (revue 22470) — 9e8c41b

  • CLAUDE.md et docs/architecture.md : aucun job n'échoue sur une advisory npm, mais npm ci en imprime le compte à chaque run de check-frontend, et le Défenseur les relève de son côté.

Preuves

  • Tip cumulé 9e8c41b, worktree avec npm ci propre : sonde rouge rc=1, npm run build vert, 1932 tests / 110 fichiers (1915 + 17).
  • src-tauri/ et .cargo/ identiques à main sur toute la pile. Garde windows-sys rejoué sur le tip : 9 checks, exit 0. Les quatre workflows se parsent (PyYAML).
  • Mutations, une à la fois, restaurées par git : 7 sur le filtre, l'épingle de version et la liste de verify-release.sh ; 3 qui remettent la clé générique (script, filtre, verify-release.sh). Toutes rouges.
  • Tests verts sous jq 1.6 (binaire officiel, sha256 af986793…4c44, la version de la CI et du conteneur de release) comme sous jq 1.7.
  • Étape « Publish » de release.yml rejouée sur son texte exact (curl factice, jq 1.6) : manifeste nominal → DELETE puis PUT ; clé générique, forme publiée en v0.17.1, mauvaise version, JSON invalide → exit 1, aucun appel curl.
  • verify-release.sh v0.17.1 <fichier> sur des manifestes construits avec les vraies signatures de la v0.17.1 : trois clés → VERDICT : OK ; clé générique → INATTENDUE, ÉCHEC ; manifeste publié → ÉCHEC.
  • Commande de rejeu du garde (nouvelle étape 2 de /release) : exit 0 sur le lock de la pile, exit 1 sur une arête colored dérivée.

Ce qui ne se prouve qu'au prochain tag

L'appel du filtre par release.yml et le latest.json à trois clés publié : verify-release.sh en VERDICT : OK et l'étape « Generate latest.json » du journal (puce de STATE.md).

Pour relire en priorité

  1. Le retrait de la clé, et la phrase du CHANGELOG pour les AppImage v0.4.3 à v0.4.5.
  2. scripts/check-latest-json.jq et son appel dans release.yml (garde du DELETE).
  3. Le test d'alignement, qui lit le EXPECTED de verify-release.sh par une regex.
  4. La commande de rejeu du garde à l'étape 2 de /release.

Restent à la synchro post-merge de STATE.md

Les mentions périmées : #376 en status:triage (revue 22219), « 2 restantes, acceptées » et #317 (revue 22470), la puce « Nouveau bug ouvert : #320 … ne pas tester » (revue 22437).

🤖 Generated with Claude Code

Refs #320, #345, #376, #358 > PR de suivis, empilée sur #417 (#358), #416 (#320), #415 (#345) puis #414 (#376) : elle ne montre que son propre diff. Les têtes de ces quatre PR, revues et approuvées, n'ont pas bougé. Corrections demandées par Max le 2026-10-11 (« retire le repli, corrige les suggestions puis merge »), après les quatre `/pr-review` (commentaires 22219, 22287, 22437, 22470). **Cette PR modifie la garde placée avant le `DELETE` du `latest.json` publié** : selon `/merge-stack`, un tel changement passe par sa propre revue avant le merge de la pile. ## Ce qui change ### Clé générique `linux-x86_64` retirée de `latest.json` (décision de Max, #320) — `230ecd8` - `scripts/build-latest-json.sh` n'écrit plus que `linux-x86_64-deb`, `linux-x86_64-rpm` et `windows-x86_64` ; le filtre de contrôle et `verify-release.sh` exigent ces trois clés. - Sans effet sur les installations `.deb`, `.rpm` et Windows : `get_urls` (tauri-plugin-updater 2.10.0, relu) cherche d'abord `{os}-{arch}-{installer}`, et les 64 tags qui embarquent l'updater verrouillent tous plugin 2.10.0 et tauri-utils 2.8.2. - Les derniers lecteurs de la clé, les AppImage v0.4.3 à v0.4.5 et un binaire lancé hors de son paquet, ne savaient pas installer le `.deb` qu'elle servait : ils reçoivent désormais `TargetsNotFound` à la vérification, rien n'est installé. La v0.4.2 n'en était pas (son endpoint répond 404), correction du point 4 de la revue 22437. - `docs/qa-update-cycle.md`, `docs/architecture.md`, skill `/release`, `STATE.md` (puce de release) et CHANGELOG FR/EN (phrase pour ces AppImage) à jour. ### Contrôle de `latest.json` partagé, version épinglée (revue 22437, points 1 et 2) — `ba3db7c` - Le contrôle d'avant le `DELETE` passe de `release.yml` à `scripts/check-latest-json.jq`, appliqué par `jq -e --arg version … -f`. - `scripts/build-latest-json.test.mjs` applique ce même filtre à chaque PR : sortie du script, mauvaise version, dix manifestes fautifs, forme publiée jusqu'à la v0.17.1, JSON invalide. Il compare aussi les listes de clés du script, du filtre et de `verify-release.sh`. - Deux cas épinglent l'argument de version : `0.18.0` doit ressortir en `0.18.0`, une version vide doit échouer (les deux mutations survivantes de la revue). ### ADR 0023 et garde `windows-sys` (revue 22287) — `08d54fd` - Prémisse corrigée : le conteneur a `python3` (dépendance transitive des paquets `apt`, run 517) ; `awk` reste, parce que mawk fait partie de l'image de base. - « PR #344 (deuxième dérive) » ; le commentaire sur le code de sortie d'`awk` dit ce que ce test attrape seul ; deux puces de procédure ajoutées (bloc sans arête `windows-sys`, second bloc hors borne) ; la limite du canari est écrite. - `/release` rejoue le garde juste après l'édition de `Cargo.lock` (étape 2), puisque le commit de release n'a pas de PR. ### Commentaires (revue 22219) — `d1d025d` - `audit.yml` : la mesure de `concurrency` ne couvre pas `schedule` ni `workflow_dispatch`. - `reportService.test.ts` : la CI tourne sous Node 24 depuis #376 (le harnais `node:sqlite` relève de #392). - Skill `/release` : `/actions/tasks` n'ignore `limit` que sans `page` (mesuré : 613 lignes sans `page`, 5 avec `?limit=5&page=2`, 30 avec `?page=2`). ### `npm audit` (revue 22470) — `9e8c41b` - `CLAUDE.md` et `docs/architecture.md` : aucun job n'échoue sur une advisory npm, mais `npm ci` en imprime le compte à chaque run de `check-frontend`, et le Défenseur les relève de son côté. ## Preuves - Tip cumulé `9e8c41b`, worktree avec `npm ci` propre : sonde rouge rc=1, `npm run build` vert, **1932 tests / 110 fichiers** (1915 + 17). - `src-tauri/` et `.cargo/` identiques à `main` sur toute la pile. Garde `windows-sys` rejoué sur le tip : `9 checks, exit 0`. Les quatre workflows se parsent (PyYAML). - Mutations, une à la fois, restaurées par git : 7 sur le filtre, l'épingle de version et la liste de `verify-release.sh` ; 3 qui remettent la clé générique (script, filtre, `verify-release.sh`). Toutes rouges. - Tests verts sous **jq 1.6** (binaire officiel, sha256 `af986793…4c44`, la version de la CI et du conteneur de release) comme sous jq 1.7. - Étape « Publish » de `release.yml` rejouée sur son texte exact (`curl` factice, jq 1.6) : manifeste nominal → `DELETE` puis `PUT` ; clé générique, forme publiée en v0.17.1, mauvaise version, JSON invalide → exit 1, **aucun appel `curl`**. - `verify-release.sh v0.17.1 <fichier>` sur des manifestes construits avec les vraies signatures de la v0.17.1 : trois clés → `VERDICT : OK` ; clé générique → `INATTENDUE`, `ÉCHEC` ; manifeste publié → `ÉCHEC`. - Commande de rejeu du garde (nouvelle étape 2 de `/release`) : exit 0 sur le lock de la pile, exit 1 sur une arête `colored` dérivée. ## Ce qui ne se prouve qu'au prochain tag L'appel du filtre par `release.yml` et le `latest.json` à trois clés publié : `verify-release.sh` en `VERDICT : OK` et l'étape « Generate latest.json » du journal (puce de `STATE.md`). ## Pour relire en priorité 1. Le retrait de la clé, et la phrase du CHANGELOG pour les AppImage v0.4.3 à v0.4.5. 2. `scripts/check-latest-json.jq` et son appel dans `release.yml` (garde du `DELETE`). 3. Le test d'alignement, qui lit le `EXPECTED` de `verify-release.sh` par une regex. 4. La commande de rejeu du garde à l'étape 2 de `/release`. ## Restent à la synchro post-merge de `STATE.md` Les mentions périmées : #376 en `status:triage` (revue 22219), « 2 restantes, acceptées » et #317 (revue 22470), la puce « Nouveau bug ouvert : #320 … ne pas tester » (revue 22437). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
maximus added 5 commits 2026-10-12 19:08:10 +00:00
Review follow-ups of PR #416. The check that release.yml runs before
deleting the published manifest moves from an inline jq program to
scripts/check-latest-json.jq, which release.yml applies with
`jq -e --arg version ... -f`. scripts/build-latest-json.test.mjs now runs
that same filter on every pull request: on the script's output, on a
wrong version, on nine broken manifests and on the shape published up to
v0.17.1. It also compares the key lists of the script, of the filter and
of verify-release.sh, so a list left behind shows before the tag.

Two new cases pin the version argument: 0.18.0 must come out as 0.18.0
(the other fixtures pass 0.17.1, the version the bundle names carry, so a
script that ignored its argument passed them all), and an empty version
must fail. Both mutations survived the review's pass.

No change to what the manifest holds: still four keys.

Refs #320

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Max's decision on PR #416, after its review measured who still read the
key. tauri-plugin-updater looks up "{os}-{arch}-{installer}" first, and
every version that ships the updater (v0.2.1 and later, plugin 2.10.0,
tauri-utils 2.8.2 in each tag's Cargo.lock) carries its bundle-type
marker, so .deb and .rpm installs never reach the generic key. Its last
readers were the AppImage installs v0.4.3 to v0.4.5 (v0.4.2 targets a
route that answers 404, earlier versions read GitHub) and binaries run
outside a package; none of them can install the .deb it served, and the
updater wrote that .deb over the running file. They now get
TargetsNotFound when checking: an error on the Updates card, nothing
installed.

The key leaves the script, scripts/check-latest-json.jq and
verify-release.sh together; the test compares the three lists. Docs fix
the readers named by #416 (v0.4.2 is not one) and the CHANGELOG entry
says what changes for those AppImage installs.

Refs #320

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups of PR #415. The container does have python3 (pulled by
the apt packages of the install step, run 517): awk is kept because mawk
is part of the ubuntu:22.04 base image, which the workflow comment and
the ADR now say. #344 is a PR and the second drift, not the third. The
awk exit-code test is described by what it alone catches (an awk that
fails after printing every fact). The repair procedure gains the two
failures it had no answer for, and the ADR names the canary's limit.

The release commit edits Cargo.lock on main without a PR, so /release
now replays the guard's exact step text right after that edit (step 2),
checked on the stack's lock (exit 0) and on a drifted edge (exit 1).

Refs #345

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-ups of PR #414.
- audit.yml points to the concurrency comment of check-rust.yml, whose
  measurement covers push and pull_request runs only: say this workflow
  runs on schedule and workflow_dispatch, which it does not cover.
- reportService.test.ts said CI runs Node 20, so no node:sqlite; CI runs
  Node 24 since #376, and the harness itself is #392's.
- The release skill said /actions/tasks ignores `limit`. Measured
  2026-10-12: only without `page` (613 rows); with `page` it pages by 30
  or by `limit`.

Refs #376

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs: say what still reports npm advisories after review of #417
All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m53s
PR Check — Rust / rust (pull_request) Successful in 3m48s
9e8c41b1f3
Review follow-up of PR #417. CLAUDE.md and docs/architecture.md said
nothing re-evaluates `npm audit` in CI. No job fails on it, but the
`npm ci` step of check-frontend audits on every run and prints the count
(run 520: found 0 vulnerabilities; runs 512 and 519: 8), and the
Defenseur reports advisories on its side, which is where #358 came from.

Refs #358

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Owner

Revue /pr-review : APPROVE

Résumé. Le retrait de la clé linux-x86_64 est sûr pour toutes les installations empaquetées, la phrase du CHANGELOG sur les AppImage v0.4.3 à v0.4.5 tient, et le filtre partagé refuse tout ce que la PR annonce, sous jq 1.6 comme sous jq 1.7. Aucun bloquant. Cinq suggestions. La première touche la garde du DELETE : sous jq 1.6, un latest.json vide la passe. Le cas n'est pas atteignable aujourd'hui, mais le correctif tient en trois lignes.

Ce que j'ai rejoué (copie hors dépôt de 9e8c41b, supprimée depuis)

  1. CI de la tête, lue dans les journaux. Run 524 (frontend) : HEAD is now at 9e8c41b, Node v24.21.0, jq-1.6, found 0 vulnerabilities à l'étape npm ci, tsc && vite build, scripts/build-latest-json.test.mjs (28 tests), 110 fichiers et 1932 tests, Job succeeded. Run 525 (rust, déclenché par le commentaire modifié de check-rust.yml) : windows-sys pinning: 9 checks, exit 0, 255 tests Rust ; python3 y est bien installé par apt, comme le dit maintenant l'ADR.
  2. Suite locale (npm ci propre) : 110 fichiers et 1932 tests verts sous jq 1.6 (binaire officiel, sha256 af986793…4c44) ; le fichier du script passe à 28/28 sous jq 1.6 comme sous jq 1.7.
  3. Retrait de la clé.
    • get_urls (tauri-plugin-updater 2.10.0) essaie {os}-{arch}-{installer}, puis {os}-{arch}, et check() l'appelle avant de comparer les versions : une installation sans clé à elle échoue donc même quand elle est à jour.
    • L'app ne fixe aucune cible (Builder::new().build(), check() sans option dans useUpdater.ts et ErrorPage.tsx).
    • Relevé tag par tag : les 64 tags de v0.2.1 à v0.17.1 verrouillent plugin 2.10.0, tauri-utils 2.8.2 et @tauri-apps/cli 2.10.0, et v0.1.0 à v0.2.0 n'ont pas d'updater.
  4. Lecteurs AppImage.
    • appimage reste dans bundle.targets jusqu'à la v0.7.3, mais aucune AppImage n'a été publiée après la v0.4.5.
    • Côté Forgejo, release.yml ne copie d'AppImage qu'en v0.4.2 et v0.4.3, puis passe --bundles deb,rpm dès la v0.4.4.
    • Le miroir GitHub (lu par son API) n'a plus de release après la v0.4.5, qui porte sa dernière AppImage.
    • Les endpoints : GitHub jusqu'à la v0.4.1, …/releases/latest/download/latest.json en v0.4.2 (404, revérifié ce jour), le registre dès la v0.4.3. La plage « v0.4.3 à v0.4.5 » tient.
    • « en étaient cassées » tient aussi : la clé publique de l'updater est la même de la v0.4.2 à la tête, donc la signature du .deb passait et install_appimage écrivait ses octets.
    • Le registre sert aujourd'hui {"version":"0.17.1","keys":["linux-x86_64","windows-x86_64"]}.
  5. Garde du DELETE. J'ai extrait l'étape « Publish » de release.yml par PyYAML et l'ai lancée telle quelle (bash --noprofile --norc -e -o pipefail, curl factice qui journalise ses appels) :
    release-assets/latest.json jq 1.6 jq 1.7
    sortie du script (trois clés) exit 0, DELETE puis PUT idem
    clé générique ajoutée exit 1, aucun appel idem
    forme publiée en v0.17.1 exit 1, aucun appel idem
    version 0.17.0 pour le tag v0.17.1 exit 1, aucun appel idem
    JSON tronqué exit 1, aucun appel idem
    fichier absent exit 1, aucun appel idem
    fichier vide (ou fait d'espaces) exit 0, DELETE puis PUT exit 1, aucun appel
    deux documents, le dernier valide exit 0, DELETE puis PUT idem
  6. verify-release.sh v0.17.1 <fichier> sur des manifestes construits avec les vraies signatures de la v0.17.1 : trois clés → VERDICT : OK, exit 0 ; clé générique ajoutée → clé INATTENDUE, ÉCHEC ; latest.json publié → INATTENDUE et deux MANQUANT, ÉCHEC.
  7. Commande de l'étape 2 de /release, lancée depuis la racine : exit 0, dernière ligne windows-sys pinning: 9 checks, exit 0. Une arête colored passée à 0.48.0 donne FAIL: colored 3.1.1 -> windows-sys 0.48.0, pinned at 0.61.2, exit 1. Le texte de l'étape ne lit jamais son entrée standard (awk sur fichier, boucle sur <<<), donc le passage par un tube vers bash ne tronque rien.
  8. /actions/tasks : sans page, 615 lignes, avec ou sans limit=5 ; ?limit=5&page=2 → 5 ; ?page=2 → 30. La phrase du skill tient.
  9. Mutations du relecteur, une à la fois, chacune restaurée par git et la copie vérifiée propre après coup. 17 rouges sur 19 :
    Mutation Tests rouges
    filtre : la clé générique réadmise 3 / 28
    filtre : clause de version remplacée par true 1 / 28
    filtre : clés en trop admises 2 / 28
    filtre : all( → any( 2 / 28
    filtre : contrôle du type de la signature retiré 1 / 28
    filtre : length > 0 → >= 0 1 / 28
    filtre : ligne d'extension .rpm retirée 2 / 28
    filtre : ligne d'extension .deb retirée 1 / 28
    filtre : ligne d'extension .exe retirée 1 / 28
    filtre : endswith(".exe") → contains(".exe") 1 / 28
    filtre : and → or après la version 12 / 28
    script : la clé générique réécrite 4 / 28
    script : version figée à 0.17.1 1 / 28
    script : garde de version vide retirée 1 / 28
    verify-release.sh : la clé générique réattendue 1 / 28
    verify-release.sh : clé Windows retirée 1 / 28
    verify-release.sh : dictionnaire écrit en dict(...) 1 / 28
    filtre : clés manquantes admises 0, équivalente : une clé manquante fait déjà échouer sa clause d'extension sur null
    filtre : version comparée par startswith 0, sans grief (il faudrait 0.17.10 contre 0.17.1)

Points examinés sans grief

  • Fermeture : la timeline des quatre issues porte #418 en ref_action: none. Chacune est fermée par sa propre PR : #376 par #414, #345 par #415, #320 par #416, #358 par #417. Les messages de commit disent Refs.
  • src-tauri/ et .cargo/ sont identiques à main sur toute la pile, et main (87920ec) est ancêtre de la tête.
  • Le commentaire d'audit.yml est cohérent avec la mesure de check-rust.yml (push et pull_request seulement). La phrase sur npm ci est confirmée par le run 524.
  • Les corrections de l'ADR 0023 sont cohérentes avec la table des dérives : #344 est une PR et la deuxième dérive. Le workflow figure bien dans les paths de check-rust.yml.
  • Commits conventionnels, commentaires en anglais, docs en français, CHANGELOG FR/EN alignés sous Fixed / Corrigé.
  • Lignes ajoutées scannées (dépôt public) : aucun secret ni donnée personnelle.

Suggestions (non bloquantes)

  1. La garde du DELETE laisse passer un latest.json vide sous jq 1.6, la version du conteneur de release (ligne en gras du tableau 5).
    • Le défaut. Sous jq 1.6, jq -e sort en 0 quand il ne lit aucune valeur ; jq 1.7 sort en 4. Sous les deux versions, un fichier à deux documents dont le dernier est valide passe aussi, alors que l'updater le refuserait (serde : caractères en trop).
    • Pourquoi non bloquant. Aucun des deux cas n'est atteignable aujourd'hui : l'étape « Generate latest.json » échoue avant, ou écrit un seul document. Le défaut date aussi de l'assertion en ligne de #416. Mais c'est la garde que la PR demande de relire, et l'en-tête du filtre promet un échec fermé.
    • Correctif éprouvé. Ajouter -s aux deux appels (release.yml et check() du test) et envelopper le filtre dans length == 1 and (.[0] | … ). Deux tests à ajouter : check("") et deux documents.
    • Preuve. Avec le correctif, 30/30 sous jq 1.6 et 1.7. Sans lui, sous jq 1.6, ces deux tests rougissent tous les deux. Sous jq 1.7, celui du fichier vide reste vert : seule la CI, en jq 1.6, le voit.
    • Si l'un des deux appels oublie -s, le filtre reçoit l'objet : length vaut alors 4, et l'échec est bruyant, pas silencieux.
    • À appliquer de préférence avant le prochain tag.
  2. « À chaque PR » est trop large pour verify-release.sh.
    • Le constat. check-frontend.yml ignore .claude/** et .forgejo/workflows/release.yml. Une PR qui ne change que le dictionnaire EXPECTED de verify-release.sh, ou que l'appel du filtre dans release.yml, ne lance donc pas le test d'alignement.
    • Ce qui est couvert. Le script et le filtre, sous scripts/, le lancent toujours, et ce sont les deux listes qui comptent avant le DELETE. Une dérive de verify-release.sh ne se verrait qu'au verdict de l'étape 9, après la publication, sans dommage pour le registre.
    • À préciser dans docs/architecture.md, dans l'en-tête de check-latest-json.jq et dans le commentaire de release.yml (« à chaque PR qui touche scripts/ »), ou bien retirer .claude/** du paths-ignore.
  3. Commentaire périmé dans release.yml, étape « Generate latest.json » (ligne 104) : « One key per Linux package, a .deb fallback and the NSIS installer ». Il n'y a plus de repli.
  4. L'appel du filtre par release.yml reste hors des tests (limite déjà écrite dans le corps de la PR).
    • Muter jq -e en jq dans release.yml : la suite reste à 28/28, alors que l'étape rejouée fait alors le DELETE puis le PUT d'un manifeste à clé générique, ou d'une mauvaise version.
    • Le test pourrait extraire l'étape « Publish » de release.yml et la jouer avec un curl factice, comme au point 5.
    • C'est la suite de la suggestion 2 de la revue 22437, une épingle sur un code correct : une issue de suivi plutôt qu'un tour de plus.
  5. Build tauri dev sous Linux. C'est un binaire sans marqueur : sa vérification échoue désormais avec TargetsNotFound, même quand il est à jour, puisque get_urls passe avant la comparaison des versions. Une ligne dans docs/qa-update-cycle.md évitera de prendre cette erreur pour une régression pendant le développement.

Actions faites

  • Copie hors dépôt (clone local de 9e8c41b dans /tmp/pr418-review, avec son npm ci), binaire jq 1.6, journaux des runs 524 et 525, signatures de la v0.17.1, répertoires de rejeu et script de mutations : supprimés (/tmp/pr418-*). Le dépôt principal et le worktree de l'auteur n'ont pas été touchés.
  • Labels : aucun changement. #320, #345, #358 et #376 sont déjà en status:approved, et cette PR n'en ferme aucune.
## Revue `/pr-review` : APPROVE **Résumé.** Le retrait de la clé `linux-x86_64` est sûr pour toutes les installations empaquetées, la phrase du CHANGELOG sur les AppImage v0.4.3 à v0.4.5 tient, et le filtre partagé refuse tout ce que la PR annonce, sous jq 1.6 comme sous jq 1.7. Aucun bloquant. Cinq suggestions. La première touche la garde du `DELETE` : sous jq 1.6, un `latest.json` vide la passe. Le cas n'est pas atteignable aujourd'hui, mais le correctif tient en trois lignes. ### Ce que j'ai rejoué (copie hors dépôt de `9e8c41b`, supprimée depuis) 1. **CI de la tête, lue dans les journaux.** Run 524 (frontend) : `HEAD is now at 9e8c41b`, Node `v24.21.0`, `jq-1.6`, `found 0 vulnerabilities` à l'étape `npm ci`, `tsc && vite build`, `scripts/build-latest-json.test.mjs (28 tests)`, 110 fichiers et 1932 tests, `Job succeeded`. Run 525 (rust, déclenché par le commentaire modifié de `check-rust.yml`) : `windows-sys pinning: 9 checks, exit 0`, 255 tests Rust ; `python3` y est bien installé par `apt`, comme le dit maintenant l'ADR. 2. **Suite locale** (`npm ci` propre) : 110 fichiers et 1932 tests verts sous jq 1.6 (binaire officiel, sha256 `af986793…4c44`) ; le fichier du script passe à 28/28 sous jq 1.6 comme sous jq 1.7. 3. **Retrait de la clé.** - `get_urls` (`tauri-plugin-updater` 2.10.0) essaie `{os}-{arch}-{installer}`, puis `{os}-{arch}`, et `check()` l'appelle **avant** de comparer les versions : une installation sans clé à elle échoue donc même quand elle est à jour. - L'app ne fixe aucune cible (`Builder::new().build()`, `check()` sans option dans `useUpdater.ts` et `ErrorPage.tsx`). - Relevé tag par tag : les 64 tags de v0.2.1 à v0.17.1 verrouillent plugin 2.10.0, `tauri-utils` 2.8.2 et `@tauri-apps/cli` 2.10.0, et v0.1.0 à v0.2.0 n'ont pas d'updater. 4. **Lecteurs AppImage.** - `appimage` reste dans `bundle.targets` jusqu'à la v0.7.3, mais aucune AppImage n'a été publiée après la v0.4.5. - Côté Forgejo, `release.yml` ne copie d'AppImage qu'en v0.4.2 et v0.4.3, puis passe `--bundles deb,rpm` dès la v0.4.4. - Le miroir GitHub (lu par son API) n'a plus de release après la v0.4.5, qui porte sa dernière AppImage. - Les endpoints : GitHub jusqu'à la v0.4.1, `…/releases/latest/download/latest.json` en v0.4.2 (404, revérifié ce jour), le registre dès la v0.4.3. La plage « v0.4.3 à v0.4.5 » tient. - « en étaient cassées » tient aussi : la clé publique de l'updater est la même de la v0.4.2 à la tête, donc la signature du `.deb` passait et `install_appimage` écrivait ses octets. - Le registre sert aujourd'hui `{"version":"0.17.1","keys":["linux-x86_64","windows-x86_64"]}`. 5. **Garde du `DELETE`.** J'ai extrait l'étape « Publish » de `release.yml` par PyYAML et l'ai lancée telle quelle (`bash --noprofile --norc -e -o pipefail`, `curl` factice qui journalise ses appels) : | `release-assets/latest.json` | jq 1.6 | jq 1.7 | |---|---|---| | sortie du script (trois clés) | exit 0, `DELETE` puis `PUT` | idem | | clé générique ajoutée | exit 1, aucun appel | idem | | forme publiée en v0.17.1 | exit 1, aucun appel | idem | | version 0.17.0 pour le tag v0.17.1 | exit 1, aucun appel | idem | | JSON tronqué | exit 1, aucun appel | idem | | fichier absent | exit 1, aucun appel | idem | | **fichier vide** (ou fait d'espaces) | **exit 0, `DELETE` puis `PUT`** | exit 1, aucun appel | | **deux documents, le dernier valide** | **exit 0, `DELETE` puis `PUT`** | **idem** | 6. **`verify-release.sh v0.17.1 <fichier>`** sur des manifestes construits avec les vraies signatures de la v0.17.1 : trois clés → `VERDICT : OK`, exit 0 ; clé générique ajoutée → `clé INATTENDUE`, `ÉCHEC` ; `latest.json` publié → `INATTENDUE` et deux `MANQUANT`, `ÉCHEC`. 7. **Commande de l'étape 2 de `/release`**, lancée depuis la racine : exit 0, dernière ligne `windows-sys pinning: 9 checks, exit 0`. Une arête `colored` passée à `0.48.0` donne `FAIL: colored 3.1.1 -> windows-sys 0.48.0, pinned at 0.61.2`, exit 1. Le texte de l'étape ne lit jamais son entrée standard (`awk` sur fichier, boucle sur `<<<`), donc le passage par un tube vers `bash` ne tronque rien. 8. **`/actions/tasks`** : sans `page`, 615 lignes, avec ou sans `limit=5` ; `?limit=5&page=2` → 5 ; `?page=2` → 30. La phrase du skill tient. 9. **Mutations du relecteur**, une à la fois, chacune restaurée par git et la copie vérifiée propre après coup. 17 rouges sur 19 : | Mutation | Tests rouges | |---|---| | filtre : la clé générique réadmise | 3 / 28 | | filtre : clause de version remplacée par `true` | 1 / 28 | | filtre : clés en trop admises | 2 / 28 | | filtre : `all(` → `any(` | 2 / 28 | | filtre : contrôle du type de la signature retiré | 1 / 28 | | filtre : `length > 0` → `>= 0` | 1 / 28 | | filtre : ligne d'extension `.rpm` retirée | 2 / 28 | | filtre : ligne d'extension `.deb` retirée | 1 / 28 | | filtre : ligne d'extension `.exe` retirée | 1 / 28 | | filtre : `endswith(".exe")` → `contains(".exe")` | 1 / 28 | | filtre : `and` → `or` après la version | 12 / 28 | | script : la clé générique réécrite | 4 / 28 | | script : version figée à `0.17.1` | 1 / 28 | | script : garde de version vide retirée | 1 / 28 | | `verify-release.sh` : la clé générique réattendue | 1 / 28 | | `verify-release.sh` : clé Windows retirée | 1 / 28 | | `verify-release.sh` : dictionnaire écrit en `dict(...)` | 1 / 28 | | filtre : clés manquantes admises | 0, équivalente : une clé manquante fait déjà échouer sa clause d'extension sur `null` | | filtre : version comparée par `startswith` | 0, sans grief (il faudrait `0.17.10` contre `0.17.1`) | ### Points examinés sans grief - **Fermeture** : la timeline des quatre issues porte #418 en `ref_action: none`. Chacune est fermée par sa propre PR : #376 par #414, #345 par #415, #320 par #416, #358 par #417. Les messages de commit disent `Refs`. - `src-tauri/` et `.cargo/` sont identiques à `main` sur toute la pile, et `main` (`87920ec`) est ancêtre de la tête. - Le commentaire d'`audit.yml` est cohérent avec la mesure de `check-rust.yml` (`push` et `pull_request` seulement). La phrase sur `npm ci` est confirmée par le run 524. - Les corrections de l'ADR 0023 sont cohérentes avec la table des dérives : #344 est une PR et la deuxième dérive. Le workflow figure bien dans les `paths` de `check-rust.yml`. - Commits conventionnels, commentaires en anglais, docs en français, CHANGELOG FR/EN alignés sous Fixed / Corrigé. - Lignes ajoutées scannées (dépôt public) : aucun secret ni donnée personnelle. ### Suggestions (non bloquantes) 1. **La garde du `DELETE` laisse passer un `latest.json` vide sous jq 1.6, la version du conteneur de release** (ligne en gras du tableau 5). - **Le défaut.** Sous jq 1.6, `jq -e` sort en 0 quand il ne lit aucune valeur ; jq 1.7 sort en 4. Sous les deux versions, un fichier à deux documents dont le dernier est valide passe aussi, alors que l'updater le refuserait (serde : caractères en trop). - **Pourquoi non bloquant.** Aucun des deux cas n'est atteignable aujourd'hui : l'étape « Generate latest.json » échoue avant, ou écrit un seul document. Le défaut date aussi de l'assertion en ligne de #416. Mais c'est la garde que la PR demande de relire, et l'en-tête du filtre promet un échec fermé. - **Correctif éprouvé.** Ajouter `-s` aux deux appels (`release.yml` et `check()` du test) et envelopper le filtre dans `length == 1 and (.[0] | … )`. Deux tests à ajouter : `check("")` et deux documents. - **Preuve.** Avec le correctif, 30/30 sous jq 1.6 et 1.7. Sans lui, sous jq 1.6, ces deux tests rougissent tous les deux. Sous jq 1.7, celui du fichier vide reste vert : seule la CI, en jq 1.6, le voit. - **Si l'un des deux appels oublie `-s`**, le filtre reçoit l'objet : `length` vaut alors 4, et l'échec est bruyant, pas silencieux. - À appliquer de préférence avant le prochain tag. 2. **« À chaque PR » est trop large pour `verify-release.sh`.** - **Le constat.** `check-frontend.yml` ignore `.claude/**` et `.forgejo/workflows/release.yml`. Une PR qui ne change que le dictionnaire `EXPECTED` de `verify-release.sh`, ou que l'appel du filtre dans `release.yml`, ne lance donc pas le test d'alignement. - **Ce qui est couvert.** Le script et le filtre, sous `scripts/`, le lancent toujours, et ce sont les deux listes qui comptent avant le `DELETE`. Une dérive de `verify-release.sh` ne se verrait qu'au verdict de l'étape 9, après la publication, sans dommage pour le registre. - **À préciser** dans `docs/architecture.md`, dans l'en-tête de `check-latest-json.jq` et dans le commentaire de `release.yml` (« à chaque PR qui touche `scripts/` »), ou bien retirer `.claude/**` du `paths-ignore`. 3. **Commentaire périmé dans `release.yml`**, étape « Generate latest.json » (ligne 104) : « One key per Linux package, a .deb fallback and the NSIS installer ». Il n'y a plus de repli. 4. **L'appel du filtre par `release.yml` reste hors des tests** (limite déjà écrite dans le corps de la PR). - Muter `jq -e` en `jq` dans `release.yml` : la suite reste à 28/28, alors que l'étape rejouée fait alors le `DELETE` puis le `PUT` d'un manifeste à clé générique, ou d'une mauvaise version. - Le test pourrait extraire l'étape « Publish » de `release.yml` et la jouer avec un `curl` factice, comme au point 5. - C'est la suite de la suggestion 2 de la revue 22437, une épingle sur un code correct : une issue de suivi plutôt qu'un tour de plus. 5. **Build `tauri dev` sous Linux.** C'est un binaire sans marqueur : sa vérification échoue désormais avec `TargetsNotFound`, même quand il est à jour, puisque `get_urls` passe avant la comparaison des versions. Une ligne dans `docs/qa-update-cycle.md` évitera de prendre cette erreur pour une régression pendant le développement. ### Actions faites - Copie hors dépôt (clone local de `9e8c41b` dans `/tmp/pr418-review`, avec son `npm ci`), binaire jq 1.6, journaux des runs 524 et 525, signatures de la v0.17.1, répertoires de rejeu et script de mutations : supprimés (`/tmp/pr418-*`). Le dépôt principal et le worktree de l'auteur n'ont pas été touchés. - Labels : aucun changement. #320, #345, #358 et #376 sont déjà en `status:approved`, et cette PR n'en ferme aucune.
maximus changed target branch from issue-358-npm-lock-refresh to main 2026-10-12 19:32:58 +00:00
maximus merged commit 9e8c41b1f3 into main 2026-10-12 19:33:03 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#418
No description provided.