Uh oh!
There was an error while loading. Please reload this page.
fix(ci): restaurer les builds macOS et Linux sur main - #220
Conversation
This reverts commit 610b93e sur la branche release : 1.8.0 ne sort plus Windows-only, on veut les trois plateformes dès la rc.5. Les quatre hunks reviennent ensemble, ils ne se séparent pas : réactiver build-macos et build-linux sans les remettre dans le `needs` de publish-release ne suffirait pas — un job absent du needs ne bloque plus la publication, mais ses artefacts ne sont pas attendus non plus. Et le `continue-on-error` du téléchargement Linux doit sauter avec, sinon un artefact manquant passerait en silence au lieu d'échouer. Ce que ça réintroduit, sciemment : un échec macOS ou Linux bloque de nouveau toute la release. C'était la raison d'être du commit d'origine. Le compromis est assumé — une release amputée d'une plateforme sans que rien ne rougisse est un pire défaut qu'une release qui échoue bruyamment. Sur un tag RC, signature et notarisation sont de toute façon sautées (`!contains(github.ref_name, '-')`), donc le job macOS ne dépend pas des secrets Apple pour aboutir. À noter : `main` porte toujours les mêmes `if: false`. L'avertissement du commit d'origine — « ne laisse pas ça atteindre main » — s'est déjà réalisé, et reste à traiter séparément.
…: false` Les jobs macOS et Linux étaient désactivés depuis le 27/07 (610b93e). Les réactiver a révélé deux pannes réelles, distinctes, que personne ne pouvait voir tant que les jobs étaient sautés. LINUX — whisper-stt-server ne démarre pas Le staging copie bien libwhisper.so.1 à côté du binaire, puis le smoke-test échoue en exit 127 : « cannot open shared object file ». Le commentaire de stage-whisper-stt.sh affirme que « le loader cherche toujours dans le répertoire du binaire » — vrai sur Windows, faux sur Linux, où ld.so ignore le cwd et PATH et n'a que RPATH/RUNPATH. Le correctif existe déjà (aacd65d1) : un RUNPATH `$ORIGIN` dans le CMakeLists. Il avait été annulé trois fois, à chaque fois pour la même raison procédurale — « poussé sur la mauvaise branche, il arrivera par feat/linux-compositor-port ». Il n'est jamais arrivé. Repris ici par cherry-pick. Attention : rebâtir les artefacts whisper-stt est nécessaire. stage-whisper-stt.sh télécharge le dernier artefact publié par build-whisper-stt.yml, pas une compilation locale — sans nouvelle exécution de ce workflow, le staging continuera de récupérer le binaire non relogeable. MACOS — ffmpeg happe le libX11 de Homebrew `libavformat.62.dylib still references build-machine paths after rewriting: /opt/homebrew/opt/libx11/lib/libX11.6.dylib`. Le contrôle de build-macos-compositor-addon.mjs fait son travail : un tel dylib est introuvable sur la machine d'un utilisateur. La cause est que le configure d'ffmpeg auto-détecte ces bibliothèques dans le préfixe Homebrew du runner. On les désactive explicitement plutôt que de les laisser au hasard de ce qui est installé, ce qui rend l'arbre vendorisé dépendant du tarball et du SDK, et de rien d'autre. Aucune n'est utilisée : xlib/libxcb sont de la capture X11, sdl2 ne sert qu'à ffplay, et lzma ne touche que des décodeurs qu'on n'embarque pas. lzma et sdl2 sont désactivés avec, bien qu'ils n'aient pas encore échoué : chaque itération coûte un build macOS complet, et ce sont les seuls autres candidats plausibles à une fuite Homebrew.
`npm run build:linux` échouait dans cargo : « vendored ffmpeg headers are missing at crates/thirdparty/ffmpeg-linux64-lgpl-shared ». Le helper pipewire-capture lie ffmpeg, et rien ne fournissait cet arbre. fetch-ffmpeg.mjs vendorisait déjà la variante « shared », mais uniquement pour Windows, et de trois façons cumulées : SHARED_PINNED n'avait pas d'entrée Linux, la fonction cherchait `ffmpeg.exe` et collectait des `.dll`, et main() la gardait derrière un `if (process.platform === "win32")`. Le commentaire assumait « compositor addon is Windows-only » — vrai quand il a été écrit, faux depuis que le helper Linux lie ffmpeg lui aussi. Quatre points, tous nécessaires : - entrée SHARED_PINNED linux-x64, même tag BtbN et même commit source (n8.1.2-32-gcfa62de001) que les entrées Windows, sha256 épinglé ; - détection des bibliothèques partagées par plateforme (`.dll` / `.so[.N]*`) au lieu de `.dll` en dur ; - destination du SDK sur Linux alignée sur le défaut de build.rs plutôt que sur crates/.cargo/config.toml, qui épingle le chemin Windows ; - garde win32 retirée de main() — fetchSharedDlls sort déjà d'elle-même quand aucun pin n'existe pour la plateforme, donc la garde était redondante ET excluante. Deux détails que seul un essai réel fait apparaître, et qui auraient coûté chacun un cycle de CI : La vérification de licence lançait `ffmpeg -L` sur le binaire du build *shared*, qui est lié dynamiquement : sans LD_LIBRARY_PATH il ne démarre pas, n'imprime rien, et assertLgpl lisait ce silence comme « unrecognised licence » puis refusait de vendoriser. Le lib/ voisin lui est maintenant passé. Et la copie doit préserver les chaînes de symlinks (libavformat.so -> .so.62 -> .so.62.12.102) : copyFileSync les déréférencerait en trois fichiers identiques de 24 Mo. `fetch:ffmpeg` passe en tête de `build:linux`, avant build:native:linux qui en a besoin — même ordre que `build:win`. Vérifié en exécutant le script sur une machine Linux : 21 bibliothèques vendorisées, SDK déposé, en-têtes et libs de link exactement là où build.rs les cherche.
Le job x64 tournait sur macos-latest, qui est Apple Silicon. Tout ce que le
chemin macOS de la 1.8.0 a ajouté se cale sur l'arch de l'HÔTE — configure
ffmpeg en `--arch=${process.arch}`, installation dans `darwin-${process.arch}`,
cargo sans `--target` — donc le job x64 produisait de l'arm64 dans
darwin-arm64/, et l'empaquetage échouait sur « Refusing to package an incomplete
macOS payload — looked in darwin-x64 ».
v1.7.0 livrait bien un DMG x64 : elle n'avait ni addon compositeur ni ffmpeg
vendorisé à construire. Les deux sont arrivés avec la 1.8.0, et le `if: false`
a empêché quiconque de le voir.
Un runner Intel pour x64 règle ça sans faire passer une arch cible à travers le
configure d'ffmpeg, cargo et les chemins de sortie — quatre modifications à
l'aveugle sur une branche de release, dont aucune n'est testable sans Mac.Le vendoring déposait bien les en-têtes — build.rs passait son assert — puis le link échouait sur `unable to find library -lavcodec` et ses quatre voisines. fs.cpSync RÉSOUT les liens symboliques par défaut : lib/libavcodec.so -> libavcodec.so.62.28.102 devenait un lien ABSOLU vers le répertoire temporaire d'extraction, que la fonction appelante supprime juste après. Les cinq liens de développement que le linker cherche étaient donc pendants. verbatimSymlinks les préserve tels quels. Sans effet sur Windows, qui n'a pas de liens dans cette archive. Vérifié en re-vendorisant depuis zéro sur Linux, et en testant la RÉSOLVABILITÉ des cinq liens (-e) et non leur simple présence : un `ls` réussit sur un lien mort, ce qui est précisément ce qui m'avait fait valider la version cassée.
Deux collisions dans electron/native/bin/linux-x64/, introduites en branchant fetch:ffmpeg sur build:linux. La première a cassé le build : le CLI statique est vendorisé sous le nom `ffmpeg` (un FICHIER), alors que build-linux-pipewire-helper.mjs y crée un RÉPERTOIRE `ffmpeg/` — le nom contre lequel le RUNPATH $ORIGIN/ffmpeg du helper est compilé. D'où `EEXIST: mkdir .../linux-x64/ffmpeg`. La seconde n'avait pas encore frappé et aurait été pire à diagnostiquer : les copies runtime des .so partaient elles aussi dans ce répertoire, NON renommées, sous les mêmes noms que les copies à symboles renommés (osff_*) qu'y place build-linux-compositor-addon.mjs pour que l'addon ne se lie pas au ffmpeg de Chromium. L'une aurait écrasé l'autre, et l'addon serait mort au chargement. Ce répertoire appartient donc aux deux scripts natifs ; fetch-ffmpeg n'a rien à y faire sur Linux. La copie runtime est restreinte à Windows, où le loader cherche bien les DLL à côté de l'exécutable, et `--sdk-only` (nouveau script fetch:ffmpeg:sdk) saute le CLI statique. Le SDK, lui, reste nécessaire : pipewire-capture et l'addon compositeur linkent contre lui. Le CLI n'est pas une perte : assertLgpl note que plus rien dans l'app ne lance ffmpeg, et v1.7.0 livrait AppImage/deb/pacman sans. Vérifié depuis un état vierge sur Linux : les cinq bibliothèques que build.rs demande sont résolvables, les en-têtes sont en place, et le chemin linux-x64/ffmpeg est libre pour le mkdir du helper.
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThe change adds Linux shared FFmpeg provisioning, executable-relative RPATHs, and macOS FFmpeg feature exclusions. It enables Linux and macOS CI builds and requires Windows, macOS, and Linux artifacts before release publication. ChangesCross-platform FFmpeg builds
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant BuildScript
participant FetchFFmpeg
participant FFmpegSDK
participant NativeBuild
BuildScript->>FetchFFmpeg: invoke --sdk-only
FetchFFmpeg->>FFmpegSDK: download and extract shared SDK
FetchFFmpeg->>FetchFFmpeg: discover and validate platform libraries
FetchFFmpeg-->>NativeBuild: provide Linux SDK and shared libraries
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/fetch-ffmpeg.mjs (1)
159-182: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winEncoder check and version banner bypass the shared-build environment.
assertLgplacceptsextraEnvand applies it to the-L,-buildconf, and-versionprobes at lines 171, 181-182. The-encoderscheck (line 193) and the closing-versioncall (line 205) still callrun()withoutopts.The function's own comment states a shared ffmpeg binary "cannot resolve its own libav*.so without being told where they are, and a binary that fails to start prints nothing."
fetchSharedDllscallsassertLgpl(exe, sharedEnv)for non-Windows builds, wheresharedEnvcarriesLD_LIBRARY_PATH. Without that same env on the-encoderscall, the shared Linux ffmpeg fails to start,encodersis empty, and the loop that flagslibx264/libx265finds no problems — the "belt and braces" GPL-encoder check silently no-ops for every shared Linux verification instead of catching a misconfigured build.🔒 Proposed fix to propagate opts to the remaining checks
// Belt and braces: whatever the flags claim, the binary must not actually // expose a GPL encoder. - const encoders = run(exePath, ["-hide_banner", "-encoders"]).stdout ?? "";+ const encoders = run(exePath, ["-hide_banner", "-encoders"], opts).stdout ?? ""; for (const lib of ["libx264", "libx265"]) { if (new RegExp(`\\s${lib}\\s`).test(encoders)) problems.push(`exposes the ${lib} encoder`); } @@ - const ver = run(exePath, ["-hide_banner", "-version"]).stdout ?? "";+ const ver = run(exePath, ["-hide_banner", "-version"], opts).stdout ?? ""; return ver.split("\n")[0]?.trim() ?? "";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/fetch-ffmpeg.mjs` around lines 159 - 182, Update the remaining probe calls in assertLgpl to pass the existing opts environment: specifically use opts for the -encoders check and the final -version banner call. Keep the current shared-build environment propagation and GPL encoder/version validation behavior unchanged.
🧹 Nitpick comments (1)
.github/workflows/build.yml (1)
92-104: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winPin the ARM64 runner to an explicit label.
runs-onpinsx64tomacos-15-intel, but it usesmacos-latestforarm64. The native build derives its output from the host architecture. A moving runner label can change the build environment and break this release path.Use
macos-15or another explicit ARM64 label. GitHub currently listsmacos-latestfor macOS 15 ARM64, but documents-latestlabels as moving. (github.com)Suggested change
- runs-on: ${{ matrix.arch == 'x64' && 'macos-15-intel' || 'macos-latest' }}+ runs-on: ${{ matrix.arch == 'x64' && 'macos-15-intel' || 'macos-15' }}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/build.yml around lines 92 - 104, Update the ARM64 branch of the runs-on expression in the build matrix to use an explicit ARM64 macOS label such as macos-15 instead of the moving macos-latest label, while preserving the existing macos-15-intel selection for x64.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build.yml:
- Around line 347-350: Update the release workflow around publish-release and
the macOS artifact download steps so manual releases always build and require
both x64 and arm64 macOS artifacts. Remove continue-on-error from both macOS
downloads, validate that both expected artifacts exist before invoking gh
release, and prevent publication when either architecture is missing.
In `@scripts/fetch-ffmpeg.mjs`:
- Around line 390-405: Update the vendored-library detection in the fetch flow
around alreadyVendored so Linux also evaluates whether the shared FFmpeg
libraries are present, while preserving the existing Windows-specific
directory-entry logic where applicable. Ensure the skip condition uses
alreadyVendored, sdkPresent, and the absence of --force so already-complete
vendoring avoids re-downloads on all supported platforms.
---
Outside diff comments:
In `@scripts/fetch-ffmpeg.mjs`:
- Around line 159-182: Update the remaining probe calls in assertLgpl to pass
the existing opts environment: specifically use opts for the -encoders check and
the final -version banner call. Keep the current shared-build environment
propagation and GPL encoder/version validation behavior unchanged.
---
Nitpick comments:
In @.github/workflows/build.yml:
- Around line 92-104: Update the ARM64 branch of the runs-on expression in the
build matrix to use an explicit ARM64 macOS label such as macos-15 instead of
the moving macos-latest label, while preserving the existing macos-15-intel
selection for x64.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3fe0f929-7edc-488f-b22e-31b6acece8eb
📒 Files selected for processing (5)
.github/workflows/build.ymlelectron/native/whisper-stt/CMakeLists.txtpackage.jsonscripts/fetch-ffmpeg-macos.mjsscripts/fetch-ffmpeg.mjs
Uh oh!
There was an error while loading. Please reload this page.
| const alreadyVendored = | ||
| process.platform === "win32" && | ||
| fs | ||
| .readdirSync(binDir, { withFileTypes: true }) | ||
| .some((e) => e.isFile() && isSharedLib(e.name) && /^(lib)?av/i.test(e.name)); | ||
| // The build-time SDK comes out of this same archive, so a tree that has the | ||
| // DLLs but not the SDK must still re-download — otherwise we skip here and | ||
| // the compositor build fails afterwards on the missing FFMPEG_DIR. | ||
| const sdkDest = ffmpegSdkDest(); | ||
| const sdkPresent = sdkDest == null || fs.existsSync(sdkDest); | ||
| if (alreadyVendored && sdkPresent && !process.argv.includes("--force")) { | ||
| console.log(`\nShared ffmpeg DLLs already present in ${binDir}. Use --force to re-vendor.`); | ||
| console.log( | ||
| `\nShared ffmpeg libraries already present in ${binDir}. Use --force to re-vendor.`, | ||
| ); | ||
| return; | ||
| } |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win
Linux always re-downloads the shared SDK, even when already vendored.
alreadyVendored is gated by process.platform === "win32" &&, so it is always false on Linux. The skip condition on line 400 requires alreadyVendored && sdkPresent && !force, so on Linux the skip never triggers, regardless of sdkPresent. The adjacent comment states re-download should be "driven by --force" once vendoring is in place, which indicates the skip was meant to work on all platforms, not just Windows.
Since the Linux native build script now runs this fetch step before every native compile, this means every native Linux build re-downloads and re-extracts the shared ffmpeg archive from the network, even when crates/thirdparty/ffmpeg-linux64-lgpl-shared is already present and current. This adds unnecessary network I/O and a new failure mode (network flakiness) to every build.
♻️ Proposed fix to make the skip check platform-aware
- const alreadyVendored =- process.platform === "win32" &&- fs- .readdirSync(binDir, { withFileTypes: true })- .some((e) => e.isFile() && isSharedLib(e.name) && /^(lib)?av/i.test(e.name));
// The build-time SDK comes out of this same archive, so a tree that has the
// DLLs but not the SDK must still re-download — otherwise we skip here and
// the compositor build fails afterwards on the missing FFMPEG_DIR.
const sdkDest = ffmpegSdkDest();
const sdkPresent = sdkDest == null || fs.existsSync(sdkDest);
+ // Windows vendors runtime DLLs into binDir; Linux vendors only the SDK, so the+ // SDK's presence alone tells us whether there is anything left to fetch.+ const alreadyVendored =+ process.platform === "win32"+ ? fs+ .readdirSync(binDir, { withFileTypes: true })+ .some((e) => e.isFile() && isSharedLib(e.name) && /^(lib)?av/i.test(e.name))+ : sdkPresent;
if (alreadyVendored && sdkPresent && !process.argv.includes("--force")) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| constalreadyVendored= | |
| process.platform==="win32"&& | |
| fs | |
| .readdirSync(binDir,{withFileTypes: true}) | |
| .some((e)=>e.isFile()&&isSharedLib(e.name)&&/^(lib)?av/i.test(e.name)); | |
| // The build-time SDK comes out of this same archive, so a tree that has the | |
| // DLLs but not the SDK must still re-download — otherwise we skip here and | |
| // the compositor build fails afterwards on the missing FFMPEG_DIR. | |
| constsdkDest=ffmpegSdkDest(); | |
| constsdkPresent=sdkDest==null||fs.existsSync(sdkDest); | |
| if(alreadyVendored&&sdkPresent&&!process.argv.includes("--force")){ | |
| console.log(`\nShared ffmpeg DLLs already present in ${binDir}. Use --force to re-vendor.`); | |
| console.log( | |
| `\nShared ffmpeg libraries already present in ${binDir}. Use --force to re-vendor.`, | |
| ); | |
| return; | |
| } | |
| // The build-time SDK comes out of this same archive, so a tree that has the | |
| // DLLs but not the SDK must still re-download — otherwise we skip here and | |
| // the compositor build fails afterwards on the missing FFMPEG_DIR. | |
| constsdkDest=ffmpegSdkDest(); | |
| constsdkPresent=sdkDest==null||fs.existsSync(sdkDest); | |
| // Windows vendors runtime DLLs into binDir; Linux vendors only the SDK, so the | |
| // SDK's presence alone tells us whether there is anything left to fetch. | |
| constalreadyVendored= | |
| process.platform==="win32" | |
| ? fs | |
| .readdirSync(binDir,{withFileTypes: true}) | |
| .some((e)=>e.isFile()&&isSharedLib(e.name)&&/^(lib)?av/i.test(e.name)) | |
| : sdkPresent; | |
| if(alreadyVendored&&sdkPresent&&!process.argv.includes("--force")){ | |
| console.log( | |
| `\nShared ffmpeg libraries already present in ${binDir}. Use --force to re-vendor.`, | |
| ); | |
| return; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/fetch-ffmpeg.mjs` around lines 390 - 405, Update the vendored-library
detection in the fetch flow around alreadyVendored so Linux also evaluates
whether the shared FFmpeg libraries are present, while preserving the existing
Windows-specific directory-entry logic where applicable. Ensure the skip
condition uses alreadyVendored, sdkPresent, and the absence of --force so
already-complete vendoring avoids re-downloads on all supported platforms.
Deux trouvailles de la revue CodeRabbit sur #220, vérifiées avant correction. assertLgpl propageait l'environnement partagé à -L et -buildconf mais pas au contrôle -encoders ni à la bannière -version finale. Sur un build SHARED Linux, ffmpeg ne résout pas ses propres libav*.so sans LD_LIBRARY_PATH : il n'imprime rien, et le contrôle ceinture-bretelles qui cherche libx264/libx265 opérait donc sur une chaîne vide. Il ne rejetait rien, jamais. Mesuré : 0 octet sans l'environnement, 13 397 octets et 229 encodeurs avec. C'est un garde-fou de conformité LGPL. Passer à vide y est pire qu'échouer. Les téléchargements macOS d'artefacts portaient continue-on-error: true, alors qu'un workflow_dispatch peut cibler une seule arch tout en fournissant un release_tag. Le contrôle final ne rejette qu'un répertoire entièrement vide, si bien qu'une release pouvait se publier avec un seul DMG sur les deux, sans que rien ne rougisse. C'est le mode d'échec silencieux que cette PR entend supprimer, appliqué à macOS au lieu de Windows. Le revert avait déjà retiré le même drapeau côté Linux ; les deux macOS le suivent. Un dispatch délibérément mono-arch échouera désormais à la publication plutôt que de livrer une release incomplète. C'est le comportement voulu : l'opérateur le verra et tranchera.
Uh oh!
There was an error while loading. Please reload this page.
mainporte la désactivation Windows-only de la 1.8.0 sans aucune des réparations qui la rendent inutile. Concrètement : une version coupée depuismainaujourd'hui sortirait Windows-only, en silence — les jobs macOS et Linux sont skipped, donc verts, et la release se publie avec un seul artefact.C'est exactement le mode d'échec contre lequel le commentaire de
610b93e9mettait en garde :L'avertissement est arrivé trop tard : le commit était déjà sur
main.Ce que la PR contient
Six commits cherry-pickés de
release/v1.8.0, sans le bump1.8.0-rc.5qui n'a rien à faire ici. Les quatre fichiers modifiés sont identiques octet pour octet à la branche qui vient de produire une rc.5 verte sur les trois plateformes.e8c4bb0dneedsdepublish-release2883617eRUNPATH $ORIGINpour whisper-stt · macOS :--disable-xlib/libxcb/sdl2/lzmasur ffmpeg9e9de681ab696f10ca13518fverbatimSymlinkspour ne pas casser les liens du SDK9fb7d0c9--sdk-only, la copie runtime reste windows-onlyLes cinq pannes réparées
Rallumer les deux jobs n'a pas révélé un problème mais cinq, empilés, invisibles depuis le 27 juillet :
process.arch, donc le job x64 produisait de l'arm64 dans le mauvais répertoire. v1.7.0 livrait un DMG x64 parce qu'elle n'avait ni compositeur ni ffmpeg vendorisé à construire.cpSyncdéréférençait les symlinks du SDK vers un/tmpsupprimé juste après : en-têtes trouvés, link en échec.Vérification
Preuve principale :
v1.8.0-rc.5est publiée avec les six artefacts (AppImage, deb, pacman, DMG arm64, DMG x64, exe) depuis ces mêmes changements.Sur cette branche :
tscpropre, types de test à 0, 1396 tests verts, biome et docs OK, et aucune conditionif: falseréelle ne subsiste.À noter
mainaffiche1.8.0-rc.4danspackage.json, hérité de la fusion de #219. Cette PR n'y touche pas — c'estpromote.ymlqui doit réconcilier les versions.Quand promote ouvrira sa PR
release/v1.8.0-sync → main, ces commits y seront déjà sous d'autres SHAs. Git écarte en général les patchs identiques ; sinon ce sera un conflit sur des fichiers connus.Summary by CodeRabbit
New Features
Bug Fixes
Chores