diff --git a/.forgejo/workflows/check-rust.yml b/.forgejo/workflows/check-rust.yml index 6a4f371..bba8cd9 100644 --- a/.forgejo/workflows/check-rust.yml +++ b/.forgejo/workflows/check-rust.yml @@ -30,11 +30,22 @@ on: # it). # # The runner deletes an entry unused for 7 days or created more than 30 days - # ago, and the next Monday run saves a fresh one. Cold runs that do not mean - # #234 is back: every new stable Rust until the next Monday (the toolchain - # floats on `stable`, and rustc is part of the cache key); PR runs once an - # entry that only got exact hits, hence never re-saved, reaches 30 days; and, - # after a week without any PR run, possibly the Monday run itself. + # ago, and keeps only the newest entry per key, whatever its scope; the next + # Monday run saves a fresh one. Cold runs that do not mean #234 is back (a + # timeout would): + # - a new stable Rust (the toolchain floats on `stable`) or a change to this + # job's `env:`: the key hashes rustc and the CARGO*, RUST*, CC*, CFLAGS*, + # CXX* and CMAKE* variables. Cold until the next Monday; + # - a PR run that saves under the shared entry's key evicts it for every PR + # until the next Monday. It saves when its own scope holds an older entry + # for another Cargo.lock, served before the shared one: a PR that bumped a + # dependency, then went back to main's lockfile. Two open PRs on the same + # lockfile, different from main's, evict each other the same way; + # - PR runs once an entry that only got exact hits, hence never re-saved, + # reaches 30 days; + # - after a week without any cache request, the Monday restore can fail with + # a 404: the lookup does not refresh the entry, and the cleanup it triggers + # may delete it (forgejo/runner#1741). The run then saves a fresh entry. # workflow_dispatch re-seeds by hand. schedule: # Mondays 06:30 UTC, after audit.yml (06:00 UTC). @@ -90,8 +101,10 @@ jobs: uses: https://github.com/actions/checkout@v4 # Caches ~/.cargo (registry, git, bin) and src-tauri/target, keyed on the - # rustc version, the Cargo manifests and lockfile, and this job. Saved - # only when the job succeeds and the key was not an exact hit. Served by + # rustc version, the job's CARGO*/RUST* environment, the dependencies + # declared in the Cargo manifests and lockfile (not the app's own + # version), and this job. Saved only when the job succeeds and the key + # was not an exact hit. Served by # the runner's cache proxy on port 28100, which ufw opens to the Docker # job networks only; until 2026-10-03 every restore and save timed out # there (#234, la-compagnie-maximus docs/forgejo-ops.md). What a PR run diff --git a/CLAUDE.md b/CLAUDE.md index 1437f45..c7f8810 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -166,7 +166,7 @@ Workflows Forgejo Actions dans `.forgejo/workflows/`. Le runner est à **capacit - **`audit.yml`** — audit RustSec quotidien (06:00 UTC) + `workflow_dispatch`, pour couvrir les avis de sécurité entre deux PR Rust. Échec bloquant. **Un run vert signifie « zéro advisory hors de la liste acceptée »**, pas « zéro advisory » : cette liste est dans `.cargo/audit.toml` (preuve de non-atteignabilité et condition de retrait par entrée), encadrée par l'[ADR 0018](docs/adr/0018-suppression-advisories-non-atteignables.md). Ne jamais y ajouter une advisory atteignable ni élargir une entrée à un crate entier. - **`release.yml`** — déclenché par les tags `v*`. Build Windows (NSIS `.exe`) + Linux (`.deb`, `.rpm`), signe les binaires et publie le JSON d'updater pour les mises à jour automatiques. -Aucun workflow `check-*` ne filtre sur `branches:` : une PR stackée sur une autre branche de feature déclenche donc bien la CI. Le cache Rust passe par `Swatinem/rust-cache` ([#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234)) : le runner garde ce qu'écrit un run de PR pour cette seule PR, donc c'est le run du lundi (ou un `workflow_dispatch`) qui alimente le cache partagé que lisent les autres PR. Un run à froid reste normal après une nouvelle version stable de Rust, ou quand une entrée expire (7 jours sans usage, 30 jours d'âge). Pas de cache npm : `check-frontend` ne tourne que sur des PR, et `npm ci` y prend 9 s. Le miroir `.github/workflows/` est dormant (aucune PR côté GitHub). +Aucun workflow `check-*` ne filtre sur `branches:` : une PR stackée sur une autre branche de feature déclenche donc bien la CI. Le cache Rust passe par `Swatinem/rust-cache` ([#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234)) : le runner garde ce qu'écrit un run de PR pour cette seule PR, donc c'est le run du lundi (ou un `workflow_dispatch`) qui alimente le cache partagé que lisent les autres PR. Un run à froid reste normal après une nouvelle version stable de Rust ou une modification de l'`env:` du job, quand une entrée expire (7 jours sans usage, 30 jours d'âge), ou quand une PR sauvegarde sous la clé de l'entrée partagée et l'évince, le runner ne gardant qu'une entrée par clé. La liste complète est en tête de `check-rust.yml` ; seul un délai dépassé signale un retour de #234. Pas de cache npm : `check-frontend` ne tourne que sur des PR, et `npm ci` y prend 9 s. Le miroir `.github/workflows/` est dormant (aucune PR côté GitHub). --- diff --git a/docs/architecture.md b/docs/architecture.md index 654750b..3366d75 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -493,7 +493,12 @@ Entre `cargo check` et `cargo test`, une étape **bloquante** rejoue la justific Aucun `branches:` : une PR stackée sur une autre branche de feature — ce que produit `/autopilot` — déclenche donc bien la CI. -**Cache** ([#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234)) : `Swatinem/rust-cache` garde `~/.cargo` et les dépendances compilées de `src-tauri/target`, sous une clé faite de la version de rustc, des manifestes et du lockfile Cargo, et du job. Il passe par le proxy de cache du runner, sur le port 28100 qu'ufw n'ouvre qu'aux réseaux Docker des jobs (procédure et retour arrière dans `docs/forgejo-ops.md` de la-compagnie-maximus). Le runner (v12.7.0) garde ce qu'écrit un run de PR pour cette seule PR : ses pushes suivants le relisent, les autres PR non. Le run du lundi et `workflow_dispatch` sont donc les seuls à écrire le cache partagé, sur lequel une PR se rabat quand rien ne correspond dans sa propre portée. Le runner supprime une entrée inutilisée depuis 7 jours ou créée il y a plus de 30 jours. Un run à froid est donc normal après une nouvelle version stable de Rust (rustc fait partie de la clé) jusqu'au lundi suivant, et quand une entrée expire. +**Cache** ([#234](https://git.lacompagniemaximus.com/maximus/simpl-resultat/issues/234)) : `Swatinem/rust-cache` garde `~/.cargo` et les dépendances compilées de `src-tauri/target`, sous une clé faite de la version de rustc, des variables `CARGO*` et `RUST*` du job, des dépendances déclarées dans les manifestes et le lockfile Cargo (la version de l'app n'en fait pas partie), et du job. Il passe par le proxy de cache du runner, sur le port 28100 qu'ufw n'ouvre qu'aux réseaux Docker des jobs (procédure et retour arrière dans `docs/forgejo-ops.md` de la-compagnie-maximus). Le runner (v12.7.0) garde ce qu'écrit un run de PR pour cette seule PR : ses pushes suivants le relisent, les autres PR non. Le run du lundi et `workflow_dispatch` sont donc les seuls à écrire le cache partagé, sur lequel une PR se rabat quand rien ne correspond dans sa propre portée. Le runner supprime une entrée inutilisée depuis 7 jours ou créée il y a plus de 30 jours, et ne garde qu'une entrée par clé, toutes portées confondues. Un run à froid est donc normal dans les cas suivants ; seul un délai dépassé signale un retour de #234 : + +- après une nouvelle version stable de Rust ou une modification de l'`env:` du job, jusqu'au lundi suivant ; +- quand une PR sauvegarde sous la clé de l'entrée partagée : elle l'évince pour toutes les PR jusqu'au lundi suivant. Ça arrive quand sa propre portée contient une entrée plus ancienne pour un autre `Cargo.lock`, servie avant l'entrée partagée, par exemple une PR qui a monté une dépendance puis est revenue au lockfile de `main`. Deux PR ouvertes sur un même lockfile, différent de celui de `main`, s'évincent l'une l'autre ; +- quand une entrée qui n'a eu que des correspondances exactes, donc jamais re-sauvegardée, atteint 30 jours ; +- un lundi après une semaine sans requête au cache, la restauration peut échouer en 404 : la recherche ne rafraîchit pas l'entrée, et le ménage qu'elle déclenche peut la supprimer ([forgejo/runner#1741](https://code.forgejo.org/forgejo/runner/issues/1741)). Le run repart alors à froid et re-sauvegarde. ### `check-frontend.yml` — Vérifications frontend sur PR