
Presun vydaní do CI, dvakrát
GeekBye v1.8.4 presunul buildy vydaní do CI pre macOS a Windows. Čo changelog nehovorí, je, že sme to skúsili už raz predtým, o mesiac neskôr to zmazali pre náklady na runnery a prijalo sa to až na druhýkrát — lebo dovtedy už release skript fungoval ručne.
Changelog v1.8.4 má riadok, ktorý znie ako čisté upratovanie: „Buildy vydaní teraz pochádzajú z CI pre macOS aj Windows". Číta sa to ako niečo, čo sa stane raz, čisto, a už sa na to nikdy nemyslí. Nebolo to tak. Tím už raz dal vydania do CI — a vytrhol to späť. Toto vydanie je druhý pokus a dôvod, prečo sa prijal, je tou skutočnou inžinierskou lekciou, tak si to povedzme po poriadku.
Prvý pokus a prečo zomrel
V októbri 2025 existoval release.yml. Spúšťal sa pri pushnutí tagu — hoď tag v*.*.* a runner macOS sa naštartuje, zostaví a publikuje. Robil si vlastné nastavenie podpisovania ručne: krok, ktorý dekódoval podpisovací certifikát, vytvoril a odomkol dočasný keychain, importoval certifikát, aby ho codesign našiel, a párový upratovací krok na konci. Fungovalo to. Bolo to aj len pre macOS — vydania Windows v CI neboli vôbec.
- novembra ho zmazali. Správa commitu je nezvyčajne úprimná o dôvode: „remove GitHub Actions release workflow to conserve minutes / macOS runners cost 10x multiplier (100 billed minutes per 10-minute release). Releases will be done locally." To je celý príbeh prvého pokusu v jednej vete. GitHub účtuje čas runnera macOS desaťnásobne drahšie ako Linux a vydanie spúšťané tagom znamená, že každý jeden tag — vrátane tých jednorazových, opätovných tagov, tých „ups, zabudol som zvýšiť verziu" — potichu minie sto účtovaných minút. Automatizácia, ktorú neovládaš, je automatizácia, ktorá míňa peniaze, kým spíš. Takže vydania sa vrátili na Mac vývojára na ďalšie tri a pol mesiaca.
Kde sa naozaj vyriešili ťažké problémy
Tu je časť, vďaka ktorej druhý pokus funguje, a stala sa celá mimo CI. Počas tých troch a pol mesiaca lokálnych vydaní scripts/release.js — obyčajný Node skript, ktorý vývojár spúšťa ručne — vstrebal každý problém balenia, ktorý aplikácia mala, po jednej oprave:
- Obnova white-label. Toto je white-label kódová báza, ktorá zostavuje aj GeekBye, aj Pavleur z jedného zdroja, čo znamená, že vydanie vymení polia
package.jsona ikonové assety za cieľový produkt. Dve opravy naučili skript všetko potom vrátiť späť, takže zostavenie Pavleuru nenechalo tvoj git strom špinavý identitou Pavleuru. - Dvojarchitektúrny Windows. Oprava, aby sa zostavovali oba inštalátory Windows, x64 aj arm64, namiesto jedného.
- Obídenie pre nepodpísaný Windows. Novší electron-builder ignoroval konfiguračný príznak, ktorý mal vypnúť podpisovanie Windows, tak sa skript naučil vynútiť nepodpísaný build tým, že namiesto toho nastavil
CSC_IDENTITY_AUTO_DISCOVERY=falsev prostredí — vráska, ktorú nájdeš, až keď na ňu narazíš. - Autodetekcia notarizácie. Skript sa naučil pozrieť na svoje prostredie a rozhodnúť: sú prítomné podpisovacie prihlasovacie údaje? Podpíš. Sú prítomné aj notarizačné údaje Apple? Notarizuj. Ani jedny? Zostav nepodpísané. Žiadne príznaky na zapamätanie; prítomnosť secretov je konfigurácia.
Nič z toho nie je efektné. Všetko je to ten druh vecí, ktoré, ak ťa prekvapia vnútri runnera CI, stoja ťa hodinu cyklu push-čakaj-zlyhanie-čítaj-logy na pokus — pri účtovaní 10x. Vyriešené na Macu, pred ktorým sedíš, každé stojí minútu.
Druhý pokus: šesťdesiatšesť riadkov
Keď sa CI vrátilo vo v1.8.4, workflow mal 66 riadkov a jeho určujúcou vlastnosťou je, ako málo robí. Commit to opisuje priamo: „Manual workflow_dispatch trigger that builds both platforms in parallel, reusing existing release.js script. macOS builds are signed and notarized, Windows builds are unsigned." Každé návrhové rozhodnutie v ňom je jazva z prvého pokusu:
workflow_dispatch, nie spúšťanie tagom. Vydanie začneš kliknutím na „Run workflow". Človek prepúšťa cez bránu každú platenú minútu macOS. Problém nákladov, ktorý zabil prvú verziu, sa rieši jednoducho tým, že sa trigger neautomatizuje — jediné miesto, kde bola automatizácia aktívne škodlivá.- Vstup
product. Dispatch berie rozbaľovací zoznam —geekbyealebopavleur— takže ten istý workflow expeduje ktorúkoľvek značku. Šev white-label siaha až po tlačidlo vydania. - Dve paralelné úlohy.
build-macnamacos-latest,build-winnawindows-latest, bežiace súčasne. Windows v CI je tu naozaj nový; októbrový workflow ho nikdy nezostavil. - Žiadna logika podpisovania v YAML. V tom je celý zmysel. Žiadne žonglovanie s keychainom, žiadny krok importu certifikátu, žiadne upratovanie. Úloha Macu spúšťa
node scripts/release.js <product> --publisha úloha Windows to isté s--no-sign. Všetko, čo prvý workflow robil ručne v YAML, teraz žije v skripte, ktorý už funguje. Workflow je orchestrátor, nie implementácia.
Obe platformy chcú opačné veci a úlohy to odrážajú úprimne. macOS sa zostavuje pod hardened runtime, podpísaný a notarizovaný vstavanou cestou electron-buildera (@electron/notarize), s prihlasovacími údajmi dodanými zo secretov repozitára a autodetegovanými skriptom. Windows zostavuje nepodpísané inštalátory NSIS pre x64 a arm64. Jeden workflow, dve úlohy, dva úplne odlišné pojmy „hotovo".
Dôkaz je v tom, čo sa nestalo
Takto vieš, že poradie bolo správne: po dvoch úpravách z toho istého dňa, ktoré pomenovali behy a opravili názov secretu s tokenom, sa release.yml už štyri mesiace nedotkli. Žiadny urgentný hotfix na zlyhanie podpisovania. Žiadne zháňanie okolo zamietnutia notarizácie. Žiadna panika „natívny binárny súbor chýba na runneri". Na pipeline podpisovania-a-notarizácie — žáner CI najviac neslávne známy svojím mlátením — sú štyri mesiace ticha takmer neslýchané.
Bolo ticho, lebo hluk sa už stal niekde lacnejšie. Boje, ktoré sa zvyčajne odohrávajú v záložke logov CI, pri účtovaní 10x, po jednom force-pushi, sa odohrali na Macoch vývojárov v lokálnej ére. CI nemuselo byť miestom, kde sa balenie ladí, lebo balenie už bolo odladené. To je téza v jednom riadku: presuň build z Macu až potom, čo ťa tvoj Mac prestane prekvapovať.
Jedna previazanosť, ktorá ešte môže uhryznúť
Nie je to celkom bez slabého miesta a stojí za to ho pomenovať, lebo je nenápadné. Binárky Swift, od ktorých závisí aplikácia macOS — OCR, snímanie obrazovky, transkribéry — sú commitnuté v git. Ale vydanie neexpeduje commitnuté kópie; build ich prekompiluje na runneri. A brána check-swift-version.js tvrdo zhodí celé vydanie, ak kompilátor nie je pripnutej verzie. Pri tomto vydaní bola tým pripnutím Swift 6.2.x a nič vo workflow ju neinštaluje — úloha jednoducho verí, že predvolený Swift na macos-latest sa zhoduje. V deň, keď GitHub zvýši image runnera nad pripnutie, sa vydanie zastaví — nie preto, že by bolo niečo zlé s aplikáciou, ale preto, že pipeline je potichu previazaný s image stroja, ktorý neovláda. Je to jediný implementačný detail, ktorý tento tenký workflow nezatlačil nadol do niečoho vlastného.
Druhá polovica vydania: menšie payloady
Vydanie nieslo jednu nesúvisiacu funkciu hodnú zmienky, lebo je to čistý príklad opravy latencie odčítaním. Akcia Assist Me posielala na backend viac kontextu, než potrebovala, pri každej požiadavke. Jeden commit orezal dve veci: priložená história transkriptu klesla z posledných 30 záznamov na posledných 15 a kontextové súbory profilu používateľa — vkladané do systémového promptu pri každom volaní — dostali tvrdý strop 4,000 znakov s markerom skrátenia. Menej serializovať, menej nahrávať, menej čítať pre model, než začne odpovedať, čo je metrika, ktorú commit optimalizuje: time-to-first-token. V záujme poctivosti: commit zrýchlenie tvrdí, ale nemeria ho — v histórii nie je číslo pred/po, takže to ber ako dobre zdôvodnené orezanie, nie ako víťazstvo potvrdené benchmarkom.
Tri veci, ktoré nás toto vydanie naučilo
- CI je tenký obal nad skriptom, ktorý už funguje. 66-riadkový workflow nemá vlastnú logiku podpisovania; volá skript, ktorý tri mesiace lokálnych vydaní už odladili. Daj mechanizmus do niečoho, čo vieš spustiť ručne, a nechaj CI len rozhodnúť, kedy to spustiť.
- Automatizuj prácu, nie nutne trigger. Prvý pokus zomrel, lebo vydania spúšťané tagom automaticky míňali 10x účtované minúty runnera. Ručný
workflow_dispatchzachováva automatizáciu a odstraňuje časť, ktorá stála peniaze — niekedy je človek v slučke tou funkciou. - Laď tam, kde je iterácia lacná. Každý boj o balenie vyriešený na Macu vývojára je boj, ktorý sa nikdy nestane v záložke logov CI za desaťnásobnú cenu. Odíď z Macu posledný, nie prvý.
Pre predchádzajúcu kapitolu príbehu v1 — dodanie tridsiatich jazykov bez záchrannej siete (v1.8.3); a pre celý oblúk — anatómiu dodávania softvéru do dokonalosti.