Windows-installer meenemen in de bouwlijn op de spiegel — of bewust handwerk laten #1583

Closed
opened 2026-08-19 17:27:28 +00:00 by brenno · 2 comments
Owner

Voortgekomen uit #1208 (PR #1582). De installer bestaat nu, maar wordt met de hand op Windows gebouwd en komt bij geen enkele release terecht. Dit issue is het besluit daarover, apart gehouden omdat het over publiceren gaat en niet over bouwen.

De aanname die niet klopte

Zowel het plan in #1208 als mijn eerste versie van de documentatie ging ervan uit dat een installer per definitie handwerk is, want "er is geen Windows-runner". Dat is onjuist en is inmiddels rechtgezet in docs/BUILD.md en packaging/README.md:

  • De forge (pawprint) heeft geen Windows-machine — dat klopt.
  • Maar .github/workflows/release.yml op de github.com-spiegel is een volwaardige Windows-bouwlijn: windows-latest, bij elke v*-tag, flutter build windows --release, publiceert ocideck-windows-x64-<versie>.zip als release-asset, die .forgejo/workflows/release.yml (job windows-ophalen) met curl terughaalt.

De installer kan daar dus gewoon uit komen. scripts/build_windows_installer.sh is bewust bash en geen make-doel, precies omdat die job zelf al opmerkt dat make er niet betrouwbaar staat — het script kan ongewijzigd die lijn in.

Wat het besluit vraagt

1. Inno Setup op de runner, gepind. windows-latest is naar Server 2025 gemigreerd en levert Inno Setup niet meer mee (Server 2022 deed dat nog, 6.4.0). Dus een expliciete installatie (choco install innosetup) mét een versie in .github/pinned-ci-versions.json, want make check-pins eist elke CI-versie in dat manifest. Zonder pin drijft de installerbouw stil mee met wat Chocolatey die dag levert.

2. Een tweede Windows-artefact, of een vervanging. Komt de installer naast de zip, of in plaats daarvan? De zip heeft één eigenschap die de installer niet heeft: je kunt hem uitpakken zonder iets aan je machine te veranderen. Dat past bij "bouw uit de bron" en bij wie geen beheerdersrechten heeft. Mijn neiging is: beide, met de zip als canoniek.

3. De publicatievoorwaarde uit de bewakerstoets. Vastgelegd in docs/BUILD.md: wordt de installer gepubliceerd, dan moet hij in SHA256SUMS staan en dus onder de minisign-handtekening over dat manifest vallen. Reden: een installer vraagt om verhoging, en een ongetekende installer die om verhoging vraagt leert een slechtere gewoonte aan dan een ongetekende app die je zelf uitpakt — mensen klikken installatievensters weg, en juist daar staat "Onbekende uitgever". Die handtekening komt in de plaats van het Authenticode-certificaat dat #1013 heeft afgewezen. Een gepubliceerde installer die noch getekend is noch in het manifest staat, heeft helemaal geen herkomst — dat is een stap terug ten opzichte van de zip.

Praktisch punt: SHA256SUMS wordt op de forge samengesteld, over de bestanden die daar samenkomen. De installer moet dus net als de zip worden opgehaald vóórdat het manifest wordt gemaakt, niet erna.

4. Borging. test/linux_packaging_test.dart toetst dat de Linux-job élk artefact dat hij maakt ook uploadt. Wordt de installer in de lijn gehangen, dan hoort dezelfde controle in test/windows_packaging_test.dart — anders kan een artefact stil wegvallen.

De geldige uitkomst "nee"

Handwerk laten is een echt antwoord, geen uitstel. De terugkerende kost is dan één handmatige stap per release op een Windows-machine, en de winst is dat de release-keten geen extra bewegend deel krijgt. Wordt dat de keuze, dan hoort dat net als bij #1013 opgeschreven te worden als besluit — met de heroverwegingsdrempel erbij — in plaats van als openstaand punt te blijven staan.

Verwant

  • #1208 — de installer zelf (PR #1582)
  • #1013 — Authenticode-ondertekening, bewust afgewezen
  • #520 — de veilige-distributievraag
Voortgekomen uit #1208 (PR #1582). De installer bestaat nu, maar wordt met de hand op Windows gebouwd en komt bij geen enkele release terecht. Dit issue is het besluit daarover, apart gehouden omdat het over *publiceren* gaat en niet over *bouwen*. ## De aanname die niet klopte Zowel het plan in #1208 als mijn eerste versie van de documentatie ging ervan uit dat een installer per definitie handwerk is, want "er is geen Windows-runner". Dat is onjuist en is inmiddels rechtgezet in `docs/BUILD.md` en `packaging/README.md`: - De forge (pawprint) heeft geen Windows-machine — dat klopt. - Maar `.github/workflows/release.yml` op de github.com-spiegel is een volwaardige Windows-bouwlijn: `windows-latest`, bij elke `v*`-tag, `flutter build windows --release`, publiceert `ocideck-windows-x64-<versie>.zip` als release-asset, die `.forgejo/workflows/release.yml` (job `windows-ophalen`) met `curl` terughaalt. De installer kan daar dus gewoon uit komen. `scripts/build_windows_installer.sh` is bewust bash en geen `make`-doel, precies omdat die job zelf al opmerkt dat `make` er niet betrouwbaar staat — het script kan ongewijzigd die lijn in. ## Wat het besluit vraagt **1. Inno Setup op de runner, gepind.** `windows-latest` is naar Server 2025 gemigreerd en levert Inno Setup niet meer mee (Server 2022 deed dat nog, 6.4.0). Dus een expliciete installatie (`choco install innosetup`) mét een versie in `.github/pinned-ci-versions.json`, want `make check-pins` eist elke CI-versie in dat manifest. Zonder pin drijft de installerbouw stil mee met wat Chocolatey die dag levert. **2. Een tweede Windows-artefact, of een vervanging.** Komt de installer naast de zip, of in plaats daarvan? De zip heeft één eigenschap die de installer niet heeft: je kunt hem uitpakken zonder iets aan je machine te veranderen. Dat past bij "bouw uit de bron" en bij wie geen beheerdersrechten heeft. Mijn neiging is: beide, met de zip als canoniek. **3. De publicatievoorwaarde uit de bewakerstoets.** Vastgelegd in `docs/BUILD.md`: wordt de installer gepubliceerd, dan moet hij in `SHA256SUMS` staan en dus onder de minisign-handtekening over dat manifest vallen. Reden: een installer vraagt om verhoging, en een ongetekende installer die om verhoging vraagt leert een slechtere gewoonte aan dan een ongetekende app die je zelf uitpakt — mensen klikken installatievensters weg, en juist daar staat "Onbekende uitgever". Die handtekening komt in de plaats van het Authenticode-certificaat dat #1013 heeft afgewezen. Een gepubliceerde installer die noch getekend is noch in het manifest staat, heeft helemaal geen herkomst — dat is een stap terug ten opzichte van de zip. Praktisch punt: `SHA256SUMS` wordt op de forge samengesteld, over de bestanden die daar samenkomen. De installer moet dus net als de zip worden opgehaald vóórdat het manifest wordt gemaakt, niet erna. **4. Borging.** `test/linux_packaging_test.dart` toetst dat de Linux-job élk artefact dat hij maakt ook uploadt. Wordt de installer in de lijn gehangen, dan hoort dezelfde controle in `test/windows_packaging_test.dart` — anders kan een artefact stil wegvallen. ## De geldige uitkomst "nee" Handwerk laten is een echt antwoord, geen uitstel. De terugkerende kost is dan één handmatige stap per release op een Windows-machine, en de winst is dat de release-keten geen extra bewegend deel krijgt. Wordt dat de keuze, dan hoort dat net als bij #1013 opgeschreven te worden als besluit — met de heroverwegingsdrempel erbij — in plaats van als openstaand punt te blijven staan. ## Verwant - #1208 — de installer zelf (PR #1582) - #1013 — Authenticode-ondertekening, bewust afgewezen - #520 — de veilige-distributievraag
Author
Owner

Gebouwd en gemerged: PR #1587.

De keten. De spiegel haalt Inno Setup zelf op — rechtstreeks bij de uitgever, niet via Chocolatey, want die zou een extra partij in het releasepad zetten voor een bestand dat upstream gewoon als release-asset publiceert. Dubbel gepind: op versie (ook in .github/pinned-ci-versions.json) en op sha256. Daarna bouwt hij de installer, hangt beide bestanden aan de spiegel-release, en windows-ophalen haalt ze allebei op vóór de Checksums-stap. Daarmee staat de installer in SHA256SUMS en valt hij onder de minisign-handtekening — de voorwaarde uit de bewakerstoets bij #1208 is nu afgedwongen in plaats van beloofd.

Vier dingen die het besluit anders maakten dan hierboven geschetst.

  1. De installer wordt vóór het zippen gebouwd. Het script tekent de exe en de dll's ter plekke zodra er een certificaat is; zip je eerst, dan draagt de zip ongetekende binaries en de installer getekende — twee downloads die niet dezelfde bouw zijn.
  2. De versie komt uit de tag, niet uit pubspec.yaml. De forge haalt op onder een naam die uit de tag is afgeleid; pubspec lezen zou bij een tag die even vooruitloopt een bestand opleveren dat de forge niet kan vinden.
  3. have_asset eist beide bestanden. Anders verlaat een halve spiegel-run deze job groen en publiceert de forge een release waarin stilzwijgend één bestand ontbreekt.
  4. De pin staat op 7.1.0, niet op de 6-lijn. Inno Setup zit inmiddels op 7, dat uitdrukkelijk achterwaarts compatibel is — de gedocumenteerde breekpunten zitten in Pascal Script en preprocessor-functies, waarvan dit .iss er geen heeft (een [Code]-sectie is door de poort verboden). Op 6 pinnen zou de monitor permanent op "behind" zetten, en een monitor die altijd afgaat leest niemand. Daarvoor kreeg check_pinned_versions wel een optionele tag_regex: upstream tagt is-7_1_0, geen 7.1.0.

"Nee" bleek niet nodig. De geldige uitkomst uit dit issue — handwerk laten — is niet gekozen: de bouwlijn bestond al, de installer erin hangen kostte geen extra bewegend deel in de keten, en release_auto.sh en sign_release.sh bleken artefact-agnostisch (die controleren alleen SHA256SUMS + handtekening). Nagelopen in plaats van aangenomen: release_package_layout_test.dart en homebrew_cask_test.dart raken de installer niet.

Website. Aparte PR, inmiddels gemerged: LibreKAT/website#14. Het installerblok verschijnt daar automatisch zodra een release hem draagt — vast in hugo.toml zetten zou tot de volgende tag naar een 404 wijzen. Die PR droeg ook een bug die hier los van stond: de site toonde een verkeerde Windows-checksum (4D199381… terwijl v0.4.6 e026681d… heeft), doordat het bumpscript alleen de kleine-letter Linux-hash verving en PowerShell hoofdletters afdrukt. Wie netjes verifieerde kreeg te horen dat zijn goede download niet klopte. Gecorrigeerd, en het script leidt de hash nu af uit het Get-FileHash-commando ernaast.

Toetsen. make check groen, acht nieuwe ketencontroles, zes van de zes mutaties betrapt — waarvan één een echte zwakte in mijn eigen assertie blootlegde (die eiste de bestandsnaam érgens in de releasetekst in plaats van in de downloadtabel).

Gebouwd en gemerged: PR #1587. **De keten.** De spiegel haalt Inno Setup zelf op — rechtstreeks bij de uitgever, niet via Chocolatey, want die zou een extra partij in het releasepad zetten voor een bestand dat upstream gewoon als release-asset publiceert. Dubbel gepind: op versie (ook in `.github/pinned-ci-versions.json`) en op sha256. Daarna bouwt hij de installer, hangt beide bestanden aan de spiegel-release, en `windows-ophalen` haalt ze allebei op vóór de Checksums-stap. Daarmee staat de installer in `SHA256SUMS` en valt hij onder de minisign-handtekening — de voorwaarde uit de bewakerstoets bij #1208 is nu afgedwongen in plaats van beloofd. **Vier dingen die het besluit anders maakten dan hierboven geschetst.** 1. *De installer wordt vóór het zippen gebouwd.* Het script tekent de exe en de dll's ter plekke zodra er een certificaat is; zip je eerst, dan draagt de zip ongetekende binaries en de installer getekende — twee downloads die niet dezelfde bouw zijn. 2. *De versie komt uit de tag, niet uit `pubspec.yaml`.* De forge haalt op onder een naam die uit de tag is afgeleid; pubspec lezen zou bij een tag die even vooruitloopt een bestand opleveren dat de forge niet kan vinden. 3. *`have_asset` eist beide bestanden.* Anders verlaat een halve spiegel-run deze job groen en publiceert de forge een release waarin stilzwijgend één bestand ontbreekt. 4. *De pin staat op 7.1.0, niet op de 6-lijn.* Inno Setup zit inmiddels op 7, dat uitdrukkelijk achterwaarts compatibel is — de gedocumenteerde breekpunten zitten in Pascal Script en preprocessor-functies, waarvan dit `.iss` er geen heeft (een `[Code]`-sectie is door de poort verboden). Op 6 pinnen zou de monitor permanent op "behind" zetten, en een monitor die altijd afgaat leest niemand. Daarvoor kreeg `check_pinned_versions` wel een optionele `tag_regex`: upstream tagt `is-7_1_0`, geen `7.1.0`. **"Nee" bleek niet nodig.** De geldige uitkomst uit dit issue — handwerk laten — is niet gekozen: de bouwlijn bestond al, de installer erin hangen kostte geen extra bewegend deel in de keten, en `release_auto.sh` en `sign_release.sh` bleken artefact-agnostisch (die controleren alleen `SHA256SUMS` + handtekening). Nagelopen in plaats van aangenomen: `release_package_layout_test.dart` en `homebrew_cask_test.dart` raken de installer niet. **Website.** Aparte PR, inmiddels gemerged: LibreKAT/website#14. Het installerblok verschijnt daar automatisch zodra een release hem draagt — vast in `hugo.toml` zetten zou tot de volgende tag naar een 404 wijzen. Die PR droeg ook een bug die hier los van stond: de site toonde een **verkeerde** Windows-checksum (`4D199381…` terwijl v0.4.6 `e026681d…` heeft), doordat het bumpscript alleen de kleine-letter Linux-hash verving en PowerShell hoofdletters afdrukt. Wie netjes verifieerde kreeg te horen dat zijn goede download niet klopte. Gecorrigeerd, en het script leidt de hash nu af uit het `Get-FileHash`-commando ernaast. **Toetsen.** `make check` groen, acht nieuwe ketencontroles, zes van de zes mutaties betrapt — waarvan één een echte zwakte in mijn eigen assertie blootlegde (die eiste de bestandsnaam érgens in de releasetekst in plaats van in de downloadtabel).
Author
Owner

Slotstuk van de rc-reeks: de keten is bewezen. Het rc5-log bevat de drie regels waar het allemaal om ging:

Inno Setup 7.1.0 geïnstalleerd: C:\Program Files\Inno Setup 7\ISCC.exe
Building the installer with /c/Program Files/Inno Setup 7/ISCC.exe (version 0.4.7-rc5)
Compiler engine version: Inno Setup 7.1.0

De --version-toets slaagt, de doorgifte wijst naar de gepinde installatie (niet meer naar de Chocolatey-shim uit rc2), en de compilatie draait op 7.1.0. Daarmee is elke schakel afzonderlijk bewezen: MSYS-afscherming + bouw + publicatie van beide bestanden (rc2), pad-vondst (rc3), foutmelding-met-banner (rc4), versietoets + gepinde compiler (rc5).

rc5 faalde alsnog, maar op de toetsroute zelf, niet op de keten. De push-mirror van de forge snoeit bij elke sync tags weg die niet op de forge staan — alle vijf rc-tags zijn inmiddels van de spiegel verdwenen. Bij rc5 viel die sync middenin het bouwvenster: tag weg → gh release create weigert ("exists locally but has not been pushed"). Een échte release kan hier niet door geraakt worden: die tag staat op de forge, dus de sync draagt hem juist áán in plaats van hem weg te snoeien. Wie ooit weer mirror-only wil proeftaggen moet dit weten; het alternatief is de al ontworpen route (rc naar beide remotes — de forge-keten slaat website en demo bij -rc zelf over).

Opgeruimd: de Draft-restrelease van rc2 op de spiegel en de vijf lokale rc-tags (repo-gedeeld tag-namespace; een git push --tags van de parallelle release-sessie zou ze anders meeslepen). De vier reparaties uit deze reeks staan op main: #1598, #1601, #1602, #1603.

Slotstuk van de rc-reeks: **de keten is bewezen.** Het rc5-log bevat de drie regels waar het allemaal om ging: ``` Inno Setup 7.1.0 geïnstalleerd: C:\Program Files\Inno Setup 7\ISCC.exe Building the installer with /c/Program Files/Inno Setup 7/ISCC.exe (version 0.4.7-rc5) Compiler engine version: Inno Setup 7.1.0 ``` De `--version`-toets slaagt, de doorgifte wijst naar de gepinde installatie (niet meer naar de Chocolatey-shim uit rc2), en de compilatie draait op 7.1.0. Daarmee is elke schakel afzonderlijk bewezen: MSYS-afscherming + bouw + publicatie van beide bestanden (rc2), pad-vondst (rc3), foutmelding-met-banner (rc4), versietoets + gepinde compiler (rc5). **rc5 faalde alsnog, maar op de toetsroute zelf, niet op de keten.** De push-mirror van de forge snoeit bij elke sync tags weg die niet op de forge staan — alle vijf rc-tags zijn inmiddels van de spiegel verdwenen. Bij rc5 viel die sync middenin het bouwvenster: tag weg → `gh release create` weigert ("exists locally but has not been pushed"). Een échte release kan hier niet door geraakt worden: die tag staat op de forge, dus de sync draagt hem juist áán in plaats van hem weg te snoeien. Wie ooit weer mirror-only wil proeftaggen moet dit weten; het alternatief is de al ontworpen route (rc naar beide remotes — de forge-keten slaat website en demo bij `-rc` zelf over). Opgeruimd: de Draft-restrelease van rc2 op de spiegel en de vijf lokale rc-tags (repo-gedeeld tag-namespace; een `git push --tags` van de parallelle release-sessie zou ze anders meeslepen). De vier reparaties uit deze reeks staan op main: #1598, #1601, #1602, #1603.
Sign in to join this conversation.
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
LibreKAT/Ocideck#1583
No description provided.