Steven
Steven5 perc olvasás

Egy kódbázis, két app: hogyan white-label-ezz fork nélkül

A GeekBye és a Pavleur két eltérő brandű desktop alkalmazás, amelyek egyetlen repositoryból épülnek — nincs fork, nincs duplikált kódbázis. Íme a build-időben működő gépezet, amelytől egy kódbázis két termékké fordul le, és az az egysoros hiba, amitől a második appunk rossz néven mutatkozott be.

Mérnöki munka
Architektúra
Build
GeekBye kiadások
Egy kódbázis, két app: hogyan white-label-ezz fork nélkül

A GeekBye egy meetingjegyzetelő. A Pavleur egy AI-alapú interjúgyakorló app. Két különböző terméknek néznek ki, mert két különböző termék is — de egy kódbázisból épülnek, fork nélkül, elsodródó branch nélkül. Ez a white-labeling mérnöki oldala: nem az, hogy „miért adj el brandelt appot" (az egy másik bejegyzés), hanem az, hogy hogyan fordítasz le ténylegesen egy repositoryt két apppá — és az a dicstelen hiba, amely minden white-label rendszerben ott lapul, amíg tudatosan nem kezded keresni.

Generálj, ne branchelj

A rossz módja annak, hogy két terméket futtass egy kódbázisból, ha if (product === 'pavleur') ellenőrzéseket szórsz szét az appban, vagy forkolsz és imádkozol, hogy a két másolat soha ne térjen el. Mindkettő gyorsan rohad.

A GeekBye megközelítése a build-idejű kódgenerálás. Minden terméknek van egy config fájlja — configs/geekbye/config.ts, configs/pavleur/config.ts —, amely az identitását tartalmazza: név, bundle id, URL protokoll, az automatikus frissítések release repositoryja, és így tovább. Build előtt lefut egy script:

node scripts/build-product.js pavleur

Ez a script beolvassa a kiválasztott termék configját, és három konkrét dolgot csinál:

  1. Legenerál két config modult — egyet a renderernek (src/config/product.ts), egyet a main processnek (electron/config/product.ts) —, mindkettőt egy „NE SZERKESZD KÉZZEL — a változtatások felülíródnak" fejléccel lepecsételve. Az app többi része egyszerűen a configból importálja a productName-et, az applicationId-t és a protocol-t, és soha nem gondolkodik azon, melyik brand is ő.
  2. Csak az adott brand assetjeit másolja át — az ikonokat, a kis logót, a toast-értesítés ikonját. Egy GeekBye build fizikailag nulla Pavleur grafikát tartalmaz, és fordítva. Nincs mi kiszivárogjon.
  3. Átírja a package.json-t (release buildeknél) — az app id-t, a terméknevet, az URL protokollt, a GitHub release repót, ahová publikál, és — ami külön szép — a brandelt mikrofonengedély-szöveget, hogy a macOS azt kérdezze: „A Pavleur hozzáférne a mikrofonhoz", ne a rossz brandet.

Az egész app brand-agnosztikus; a brandet build-időben injektáljuk. Nincs futásidejű termékváltó, amit el lehetne rontani, mert futásidőben mindig csak egyetlen termék van beégetve.

Egy backend, két brand

Mindkét app ugyanazzal a backenddel beszél. Honnan tudja hát a szerver, melyik termékhez — és melyik árazáshoz, promptokhoz és limitekhez — tartozik egy kérés?

Két jelzésből, mindkettő build-időben rögzül. Először is egy application id (geekbye vagy pavleur), amely a configba van égetve és a kérésekkel együtt megy, így a backend a megfelelő termék viselkedéséhez tud irányítani. Másodszor egy User-Agent, amelyet a kliens minden backend-hívásához csatol, Product/version (platform) formában — pl. Pavleur/1.2.5 (win32) vagy GeekBye/1.7.3 (darwin). Ez az egy fejléc ingyen ad a backendnek termékenkénti és operációsrendszerenkénti attribúciót, külön analitikamező nélkül. Az automatikus frissítések eközben elszigeteltek maradnak: minden termék a saját release repositoryjába publikál, így egy GeekBye-frissítést soha nem kaphat meg egy Pavleur-telepítés.

Az onboarding is termékenként eltér — a GeekBye varázslója a meetingek átiratozásáról szól, a Pavleuré az interjúgyakorlásról —, és a megfelelőt futásidőben választja ki az egyetlen beégetett application id. Ugyanaz a gépezet, két bejárati ajtó.

A hiba: amikor a Pavleur GeekBye-nak hívta magát

Íme a harctéri sztori, és ez az, amiből minden white-label rendszernek megvan a maga verziója.

A configgenerálás működött. Az ikonok cserélődtek. A mikrofonos kérdés brandelt volt. A protokollok és a bundle id-k stimmeltek. Minden látható mérce szerint egy Pavleur build Pavleur volt. És mégis, egy ideig minden Pavleur build úgy jelentkezett be a backendhez, hogy GeekBye-nak hívta magát.

A tettes egyetlen beégetett string volt, és az elképzelhető legkevésbé csillogó helyen bujkált: a User-Agent összeállítóban, egy hálózati retry segédfüggvénybe dugva. Minden felhasználó felé látszó dolgot átkötöttünk a configra, de ebben az egy mélyen fekvő csővezeték-utilityben még mindig ott volt egy `GeekBye/${version}` literál. Egy retry utilityre senki sem gondol „brandingként", így senki sem ellenőrizte. A javítás négy sor volt — importáld a dinamikus productName-et a configból, és azt interpoláld a beégetett brand helyett —, de a tanulság maga a lényeg:

A white-labeling nem az, hogy „kicserélődött-e a logó". Hanem az, hogy „minden identitás-string a configon keresztül megy-e". És az utolsó kimaradók sosem a UI-ban élnek, ahol keresnéd őket. A User-Agentben élnek, a deep-link protokollkezelőben, az engedélykérő szövegben, a hibaüzenetekben — a csővezetékben, amit senki sem sorol a „brand" címke alá. Az egyetlen megbízható védekezés, ha a brand literált aktívan vadászandó dologként kezeled: greppeld végig a kódbázist a beégetett névre, és buktasd el a buildet, ha bárhol felbukkan azon a configon kívül, amelynek hivatott definiálnia.

Három dolog, amit a white-labeling tanított nekünk

  1. Generálj, ne branchelj. Két apró config modul build-idejű kódgenerálása plusz szelektív assetmásolás veri a forkot is és a futásidejű termékellenőrzés-bozótot is. Az app brand-agnosztikus marad; a brand egy build-bemenet.
  2. Az identitás-stringek beszivárognak a csővezetékbe. A UI a könnyű 90%. A nehéz 10% a User-Agent, az URL protokoll, a mikrofonengedély-string, a hibaszövegek. Vezesd át mindet egyetlen productName / applicationId exporton — és greppelj a nyers brandnévre CI-kapuként, hogy egy kóbor literál soha ne kerülhessen ki.
  3. Egy backend, sok brand, megkülönböztetés id-val és fejléccel. Egy build-idejű application id plusz egy Product/version (platform) User-Agent termékenkénti és platformonkénti attribúciót ad nulla duplikált infrastruktúrával — tisztán szétválasztva a megváltoztathatatlan build-idejű identitást a futásidejű viselkedéstől.

A saját branded white-label jegyzetelő futtatásának termék- és adatvédelmi oldaláról lásd a white-label AI jegyzetelőt. Ez a hatodik fejezete annak a v1-történetnek, amelyből a GeekBye v2 lesz — az előző fejezetért lásd mi is valójában egy 127 commitos kiadás (v1.7.0); a teljes ívért pedig a szoftver tökéletesre szállításának anatómiája.

Kapcsolódó cikkek

Mi is valójában egy 127 commitos kiadás
Steven
Steven5 perc olvasás

Mi is valójában egy 127 commitos kiadás

A GeekBye v1.7.0 tizenegy nap alatt 127 commit volt. Kívülről ez száz apró dolognak tűnik. Belülről két nagy funkció összefonása volt — és az egyiket rossz helyre építettük, majd menet közben kitéptük és újraépítettük. Íme egy nagy kiadás anatómiája.

Mérnöki munka
Kiadás
Architektúra
Egy megszakadt kapcsolatnak nem szabadna összeomlasztania az egész alkalmazást — de a miénk ezt tette
Steven
Steven6 perc olvasás

Egy megszakadt kapcsolatnak nem szabadna összeomlasztania az egész alkalmazást — de a miénk ezt tette

Amikor a backendünk értekezlet közben elesett, nem csak a leiratozást állította le — összeomlasztotta az egész alkalmazást. Az ok egyetlen kezeletlen esemény volt, a javítás pedig tíz sor. Ez az a kiadási csokor, amely elérte, hogy a GeekBye bejelentkezve és kapcsolódva maradjon azokon a dolgokon át, amelyek korábban megölték.

Mérnöki munka
Megbízhatóság
Electron
A tökéletesre csiszolt szoftverszállítás anatómiája: hogyan kapta el a kódellenőrzés azt, amit a tesztek nem
Steven
Steven6 perc olvasás

A tökéletesre csiszolt szoftverszállítás anatómiája: hogyan kapta el a kódellenőrzés azt, amit a tesztek nem

A GeekBye v2 sorozatban újra és újra ugyanaz történik: egy javítás átmegy minden teszten a fejlesztő gépén, majd a kódellenőrzés bebizonyítja, hogy szinte mindenki másnál elbukott volna. Ez a kilenc kiadás mögötti munkafolyamat — az ellenőrzési kapu, a javítás-előbb elkapott hibák és a szállítás-előtti tesztelési fegyelem, amely a „nálam működik” állapotot „működik” állapottá változtatja.

Mérnöki munka
Folyamat
Kódellenőrzés