
Julkaisun siirtäminen CI:hin, kahdesti
GeekBye v1.8.4 siirsi julkaisukäännökset CI:hin macOS:lle ja Windowsille. Mitä muutosloki ei kerro on se, että kokeilimme tätä kerran aiemmin, poistimme sen kuukautta myöhemmin runner-kustannusten takia ja saimme sen pysymään vasta toisella kerralla — koska siihen mennessä julkaisuskripti toimi jo käsin.
v1.8.4:n muutoslokissa on rivi joka kuulostaa pelkältä rutiinilta: "Julkaisukäännökset tulevat nyt CI:stä sekä macOS:lle että Windowsille." Se lukee kuin sellainen asia joka tapahtuu kerran, siististi, eikä sitä koskaan enää ajatella. Näin ei ollut. Tiimi oli jo kerran laittanut julkaisut CI:hin — ja repinyt sen irti. Tämä julkaisu on toinen yritys, ja syy siihen että se jäi voimaan on se varsinainen insinöörioppi, joten kerrotaan se järjestyksessä.
Ensimmäinen yritys ja miksi se kuoli
Takaisin lokakuussa 2025 oli olemassa release.yml. Sen laukaisi tag push — työnnä v*.*.*-tagi ja macOS-runner käynnistyi, käänsi ja julkaisi. Se teki oman allekirjoitusasetuksensa käsin: vaihe joka purki allekirjoitusvarmenteen, loi ja avasi väliaikaisen keychainin, toi varmenteen jotta codesign löytäisi sen, ja vastaava siivousvaihe lopussa. Se toimi. Se oli myös vain macOS — Windows-julkaisut eivät olleet CI:ssä lainkaan.
- marraskuuta se poistettiin. Committiviesti on epätavallisen suora siitä miksi: "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." Siinä on koko ensimmäisen yrityksen tarina yhdessä lauseessa. GitHub laskuttaa macOS-runnerin ajasta kymmenkertaisen hinnan Linuxiin verrattuna, ja tagin laukaisema julkaisu tarkoittaa että jokainen ainoa tagi — mukaan lukien kertakäyttöiset, uudelleentägäykset, ne "hups, unohdin nostaa version" -tyyppiset — kuluttaa hiljaa sata laskutettua minuuttia. Automaatio jota et hallitse on automaatiota joka kuluttaa rahaa tietämättäsi. Niinpä julkaisut palasivat kehittäjän Macille seuraavaksi kolmeksi ja puoleksi kuukaudeksi.
Missä vaikeat ongelmat oikeasti ratkaistiin
Tässä on se osa joka saa toisen yrityksen toimimaan, ja se tapahtui täysin CI:n ulkopuolella. Niiden kolmen ja puolen kuukauden paikallisten julkaisujen aikana scripts/release.js — se tavallinen Node-skripti jonka kehittäjä ajaa käsin — imi itseensä jokaisen paketointiongelman joka sovelluksella oli, yksi korjaus kerrallaan:
- White-label-palautus. Tämä on white-label-koodikanta joka kääntää sekä GeekByen että Pavleurin yhdestä lähteestä, mikä tarkoittaa että julkaisu vaihtaa
package.json-kentät ja kuvakeresurssit kohdetuotteelle. Kaksi korjausta opetti skriptin laittamaan kaiken jälkeenpäin takaisin, jottei Pavleurin kääntäminen jättänyt git-puutasi likaiseksi Pavleurin identiteetillä. - Kahden arkkitehtuurin Windows. Korjaus joka kääntää molemmat x64- ja arm64-Windows-asennusohjelmat yhden sijaan.
- Allekirjoittamattoman Windowsin kikka. Uudempi electron-builder jätti huomiotta konfiguraatiolipun jonka oli tarkoitus poistaa Windows-allekirjoitus käytöstä, joten skripti oppi pakottamaan allekirjoittamattoman käännöksen asettamalla sen sijaan ympäristöön
CSC_IDENTITY_AUTO_DISCOVERY=false— mutka jonka löydät vain törmäämällä siihen. - Notarisoinnin automaattinen tunnistus. Skripti oppi katsomaan ympäristöään ja päättämään: allekirjoitustunnukset paikalla? Allekirjoita. Applen notarisointitunnukset myös paikalla? Notarisoi. Ei kumpaakaan? Käännä allekirjoittamaton. Ei yhtään lippua muistettavana; salaisuuksien läsnäolo on konfiguraatio.
Mikään tuosta ei ole hohdokasta. Kaikki se on sellaista joka, jos se yllättää sinut CI-runnerin sisällä, maksaa sinulle tunnin push-odota-epäonnistu-lue-lokit per yritys — 10x-laskutuksella. Ratkaistuna Macilla jonka edessä istut, jokainen niistä maksaa minuutin.
Toinen yritys: kuusikymmentäkuusi riviä
Kun CI palasi versiossa v1.8.4, workflow oli 66 riviä, ja sen määrittävä ominaisuus on se kuinka vähän se tekee. Commit kuvaa sen suoraan: "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." Jokainen sen sisältämä suunnittelupäätös kumpuaa siitä mitä ensimmäinen yritys opetti kantapään kautta:
workflow_dispatch, ei tagin laukaisemana. Julkaisun aloitat klikkaamalla "Run workflow." Ihminen portittaa jokaisen maksullisen macOS-minuutin. Kustannusongelma joka tappoi ensimmäisen version ratkaistaan yksinkertaisesti olemalla automatisoimatta laukaisinta — sen ainoan kohdan jossa automaatio oli aktiivisesti haitallinen.product-syöte. Dispatch ottaa pudotusvalikon —geekbyetaipavleur— joten sama workflow toimittaa kummankin brändin. White-label-sauma ulottuu koko matkan aina julkaisunappiin asti.- Kaksi rinnakkaista jobia.
build-macympäristössämacos-latest,build-winympäristössäwindows-latest, ajossa samaan aikaan. Windows CI:ssä on tässä aidosti uutta; lokakuun workflow ei koskaan kääntänyt sitä. - Ei allekirjoituslogiikkaa YAML:ssa. Tämä on koko pointti. Ei keychainin jongleerausta, ei varmenteen tuontivaihetta, ei siivousta. Mac-job ajaa
node scripts/release.js <product> --publishja Windows-job ajaa saman--no-sign-lipulla. Kaikki minkä ensimmäinen workflow teki käsin YAML:ssa asuu nyt skriptissä joka jo toimii. Workflow on orkestroija, ei toteutus.
Molemmat alustat haluavat vastakkaisia asioita, ja jobit heijastavat sen rehellisesti. macOS kääntää karaistun runtimen alla, allekirjoitettuna ja notarisoituna electron-builderin sisäänrakennetun polun kautta (@electron/notarize), tunnukset toimitettuina repositoryn salaisuuksista ja skriptin automaattisesti tunnistamina. Windows kääntää allekirjoittamattomat NSIS-asennusohjelmat x64:lle ja arm64:lle. Yksi workflow, kaksi jobia, kaksi täysin eri käsitystä siitä mitä on "valmis."
Todiste on siinä mitä ei tapahtunut
Näin tiedät että järjestys oli oikea: kahden saman päivän hienosäädön jälkeen jotka nimesivät ajot ja korjasivat yhden token-salaisuuden nimen, release.yml-tiedostoon ei koskettu enää neljään kuukauteen. Ei allekirjoitusvirheen pikakorjausta. Ei notarisoinnin-hylkäyksen sähläystä. Ei "natiivibinääri puuttuu runnerilta" -paniikkia. Koodin-allekirjoitus-ja-notarisointi-putkelle — sille CI:n lajille joka on pahamaineisin riepottelustaan — neljän kuukauden hiljaisuus on lähes ennenkuulumatonta.
Oli hiljaista koska melu oli jo tapahtunut jossain halvemmalla. Taistelut jotka yleensä käydään CI:n lokivälilehdellä, 10x-laskutuksella, yksi force-push kerrallaan, oli käyty kehittäjien Maceilla paikallisella aikakaudella. CI:n ei tarvinnut olla se paikka jossa paketointi debugattiin, koska paketointi oli jo debugattu. Siinä on teesi yhdellä rivillä: siirrä käännös pois Maciltasi vasta kun Macisi on lakannut yllättämästä sinua.
Se yksi kytkös joka voi vielä kostautua
Se ei ole aivan ilman heikkoa kohtaa, ja se kannattaa mainita koska se on hienovarainen. Swift-binäärit joista macOS-sovellus riippuu — OCR, ruudunkaappaus, transkriboijat — on talletettu gitiin. Mutta julkaisu ei toimita talletettuja kopioita; käännös kääntää ne uudelleen runnerilla. Ja check-swift-version.js-portti kaataa koko julkaisun kovalla kädellä jos kääntäjä ei ole kiinnitetty versio. Tässä julkaisussa se kiinnitys oli Swift 6.2.x, eikä mikään workflow'ssa asenna sitä — job vain luottaa siihen että macos-latest:n oletus-Swift täsmää. Sinä päivänä kun GitHub nostaa runner-imagensa kiinnityksen ohi, julkaisu pysähtyy, ei siksi että sovelluksessa olisi mitään vikaa, vaan siksi että putki on hiljaa kytketty konekuvaan jota se ei hallitse. Se on se yksi toteutusyksityiskohta jota tämä ohut workflow ei työntänyt alas johonkin minkä se omistaa.
Julkaisun toinen puolisko: pienemmät kuormat
Julkaisu kantoi yhtä erillistä ominaisuutta joka ansaitsee maininnan, koska se on siisti esimerkki latenssikorjauksesta vähentämällä. Assist Me -toiminto lähetti backendille enemmän kontekstia kuin se tarvitsi jokaisella pyynnöllä. Yksi commit karsi kaksi asiaa: mukana lähetetty transkriptiohistoria putosi viimeisistä 30 merkinnästä viimeisiin 15:een, ja käyttäjän profiilin kontekstitiedostot — jotka syötetään järjestelmäpromptiin jokaisella kutsulla — saivat kovan katon 4,000 merkin kohdalla katkaisumerkin kera. Vähemmän serialisoitavaa, vähemmän ladattavaa, vähemmän mallin luettavaa ennen kuin se alkaa vastata, mikä onkin se mittari jota commit optimoi: time-to-first-token. Rehellisyyden nimissä: commit väittää nopeutuksen mutta ei mittaa sitä — historiassa ei ole ennen/jälkeen-lukua, joten suhtaudu siihen ennemmin hyvin perusteltuna karsintana kuin vertailuluvuin todistettuna voittona.
Kolme asiaa jotka tämä julkaisu opetti meille
- CI on ohut kääre skriptin päällä joka jo toimii. 66-rivisellä workflow'lla ei ole omaa allekirjoituslogiikkaa; se kutsuu skriptiä jonka kolme kuukautta paikallisia julkaisuja oli jo debugannut. Laita mekanismi asiaan jonka voit ajaa käsin, ja anna CI:n vain päättää milloin se ajetaan.
- Automatisoi työ, ei välttämättä laukaisinta. Ensimmäinen yritys kuoli koska tagin laukaisemat julkaisut kuluttivat automaattisesti 10x-laskutettuja runner-minuutteja. Manuaalinen
workflow_dispatchsäilyttää automaation ja poistaa sen osan joka maksoi rahaa — joskus ihminen silmukassa on se ominaisuus. - Debuggaa siellä missä iterointi on halpaa. Jokainen kehittäjän Macilla ratkaistu paketointitaistelu on taistelu joka ei koskaan tapahdu CI:n lokivälilehdellä kymmenkertaisella hinnalla. Siirry pois Macilta viimeisenä, älä ensimmäisenä.
Edellinen luku v1-tarinassa: kolmenkymmenen kielen toimittaminen ilman turvaverkkoa (v1.8.3); ja koko kaarelle, ohjelmiston toimittamisen anatomia täydellisyyteen asti.