GoSuda

Git Monorepon uudelleenajattelu: CAS-natiivi arkkitehtuuri ihmisille ja koodausagenteille

By Lemon Mint views ...

Jokainen kasvava insinööriorganisaatio valitsee ennemmin tai myöhemmin monen repositorion ja yhden repositorion välillä. Kun aloitetaan kymmenillä pienillä repositorioilla, elämä tuntuu aluksi yksinkertaiselta. Jokaisella kirjastolla on oma seurantajärjestelmänsä, oma CI-putkensa ja git clone, joka valmistuu sekunneissa. Sitten muutat tietorakennetta keskeisessä verkkopaketissa ja viettää loppuiltapäivän avaamalla versionpäivityksiä koskevia pull requesteja kuudessa alavirran repositoriossa odottaen, että CI-jonot tyhjenevät topologisessa järjestyksessä.

Siirrä kaikki perinteiseen Git-monoreporitorioon, ja vaihdat repositorioiden välisen koordinoinnin repositorion kokoon. Commit-historian kasvaessa ja binääriomaisuuden kerääntyessä aiempihin versioihin git fetch hidastuu. Työpuut paisuvat gigatavujen kokoisiksi. Ennen pitkää joku ehdottaa mukautetun virtuaalisen tiedostojärjestelmätaemonin, omistetun koodikatselintarkistuspalvelimen tai etärakennustyöntekijöiden laivaston pystyttämistä vain pitämään päivittäinen kehitystyö siedettävänä.

Kun autonomiset koodausagentit liittyvät tiimiin, molemmat virhetilat pahenevat. Polyrepositoriot sokeuttavat agentin projektien välisille kutsujille ja pakottavat sen jonglööraamaan tunnuksilla repositorioiden välillä. Perinteiset monorepositoriot hukuttavat agentin säiliölevyn ja verkon kaistanleveyden jokaisen tehtävän alustuksessa, kun taas samanaikaiset agentit, jotka astuvat saman haaran päälle, luovat loputtomia rebase-kilpailuja.

Inspiroituneena google3-arkkitehtuurista, rakensimme yhden rungon atomiset muutokset, alle sekunnissa tapahtuvan harvan käyttöönoton, hierarkkisen OWNERS-hallinnon ja itsenäiset avoimen lähdekoodin peilit vakiomuotoisilla Git-putkistoilla ja hyödykeobjektitallennuksella.

Suunnittelu ei tarvitse mukautettua tiedostojärjestelmätaemonia eikä kolmannen osapuolen tarkistuslaitetta, koska se käsittelee Gitiä Merkle-puuhun perustuvana sisältöosoitteellisena tallennustilana (Content-Addressable Store, CAS).

Väärinkäsitys hitaiden Git-monorepositorioiden ytimessä

Kun kehittäjät valittavat, että Git ei skaalaudu suuriin monorepositorioihin, he törmäävät harvoin Gitin objektitietokannan rajoitukseen. Kohdassa .git/objects Git tallentaa kolme muuttumatonta primitiiviä, joiden avaimena on niiden SHA-1- (tai SHA-256-) sisältötiiviste:

  1. blob: Yhden tiedoston raakatavutiedot.
  2. tree: Hakemistoluettelo, joka yhdistää tiedostonimet ja käyttöoikeudet blob- tai lapsi-tree-tiivisteisiin.
  3. commit: Pieni tekstin otsikko (tyypillisesti 200–300 tavua), joka osoittaa yhteen ainoaan juuri-tree-tiivisteeseen, nollaan tai useampaan vanhemman commit-tiivisteeseen sekä tekijän metatietoihin.

Jos monorepositorio sisältää 50 000 tiedostoa ja muokkaat yhtä riviä yhdessä tiedostossa, uusi commit käyttää uudelleen tarkat blob- ja tree-tiivisteet muille 49 999 tiedostolle.

Perinteinen Git-monorepositorio tuntuu raskaalta, koska käytäntö ylikuormittaa yhden viittauksen, refs/heads/main, kolmella keskenään ristiriidassa olevalla tehtävällä:

  • Se pitää sisällään jokaisen projektin koko yhtenäisen hakemistopuun.
  • Se vetää mukanaan koko historiallisten commitien vanhempaan linkitettyä ketjua aina ensimmäiseen päivään asti.
  • Se sijaitsee osoitteessa refs/heads/*, nimiavaruudessa, jota Git-palvelimet mainostavat ja neuvottelevat oletusarvoisesti jokaisen git clone- ja git fetch-komennon yhteydessä.

Joka kerta kun kehittäjä tai CI-ajuri hakee haaran refs/heads/main, asiakas ja palvelin neuvottelevat commit-graafin saavutettavuudesta tuhansien historiallisten versioiden yli. Jos joku vahingossa commitoi 100 megatavun arkiston kolme vuotta sitten ja poisti sen seuraavana päivänä, sen blob roikkuu edelleen historiallisessa tree-rakenteessa, joka on saavutettavissa osoitteesta refs/heads/main.

Viittausnimiavaruuden erottaminen

Gitin siirtoprotokolla mainostaa vain osoitteita refs/heads/* ja refs/tags/* vakion noudon aikana. Viittaukset mukautettujen nimiavaruuksien, kuten refs/trunk/* tai refs/ws/*, alla elävät aivan samassa objektivarastossa palvelimella, hyötyvät samasta pakettitiedoston deltapakkauksesta ja ne voidaan hakea tai työntää erikseen, mutta ne eivät aiheuta lainkaan kuormitusta oletuskopioille.

Näiden tehtävien jakaminen erillisiin viittauksiin yhdessä repositoriossa poistaa pullonkaulan:

1refs/heads/main               Vain ohjaustaso (~20 kt: säännöt, .gitconfig, synkronointiasetukset, skriptit)
2refs/trunk/main               Isätön tilannevedoksen commit, joka osoittaa uusimpaan yhtenäiseen juuripuuhun
3refs/trunk/history            Lineaarinen isään linkitetty commit-ketju, joka jakaa tarkan juuripuun SHA-1-tiivisteen
4refs/ws/<actor>/<id>          Erilliset työtilan tilannevedokset (muutosluettelot) kehittäjää tai agenttia kohden
5refs/ws/cl/<change-id>/<tip>  Muuttumattomat korjaussarjat: jokainen tarkistettavaksi lähetetyn muutoksen kärki
6refs/heads/land/<id>          Ohimenevä yhdistämisjonon liipaisin, joka poistetaan heti maihinnousun jälkeen

1. Ohjaustaso (refs/heads/main)

Oletushaara ei sisällä mitään sovelluksen lähdekoodia. Se seuraa vain repositorion toimintasääntöjä (AGENTS.md, README.md), työnkulun aliasten jaettua .gitconfig-tiedostoa, Starlark-synkronointiasetuksia (sync.star) ja palvelinpuolen yhdistämisskriptejä. Oletushaaran kloonaus siirtää noin 20 kilotavua ja valmistuu millisekunneissa.

2. Isätön rungon tilannevedos (refs/trunk/main)

Osoite refs/trunk/main osoittaa koko organisaation täydelliseen, yhtenäiseen lähdepuuhun (//web/*, //net/*, //ipc/*, //storage/*, //crypto/*, //ai/*, //devtools/*, //corp/*, //third_party/*, //experimental/*), mutta sen commit-objekti luodaan ilman -p-isälippua.

Koska osoitteella refs/trunk/main on nolla isää (parents = []), sen hakeminen vaatii nollan commit-graafin neuvottelun. Git-palvelin ei käy läpi historiaa; se lähettää yhden päätason commitin ja sen nykyisen hakemiston tree-objektit. Historialliset binäärit tai viime kuussa poistetut tiedostot ovat saavuttamattomissa kohteesta refs/trunk/main eikä niitä koskaan siirretä.

3. Lineaarinen tarkastushistoria (refs/trunk/history)

Kehittäjät tarvitsevat edelleen komentoja git blame ja git log, kun he tutkivat regressioita. Joka kerta kun muutos laskeutuu, yhdistämisskripti luoduntuu kaksi commit-objektia, jotka osoittavat tarkasti samaan juurialueen $NEW_TREE SHA-1-tiivisteeseen:

 1# Isätön tilannevedoksen commit heti syvyyden 1 työtilan tarkistusta varten
 2SNAP=$(git commit-tree "$NEW_TREE" -m "$RAW_MSG")
 3
 4# Isään linkitetty commit lineaarista git log- ja git blame -historiaa varten
 5HIST=$(git commit-tree "$NEW_TREE" -p "$OLD_HIST" -m "$RAW_MSG")
 6
 7git push --atomic origin \
 8  --force-with-lease="refs/trunk/main:${OLD_MAIN}" \
 9  --force-with-lease="refs/trunk/history:${OLD_HIST}" \
10  "${SNAP}:refs/trunk/main" \
11  "${HIST}:refs/trunk/history"

Sekä osoitteen refs/trunk/main että osoitteen refs/trunk/history pitäminen ei kaksinkertaista tallennustilaa. Koska molemmat commitit viittaavat identtiseen $NEW_TREE-tiivisteeseen, Gitin sisältöosoitteellinen tallennustila poistaa kaikkien tree- ja blob-objektien kaksoiskappaleet 100-prosenttisesti. Isättömän tilannevedoksen ylimääräinen tallennustilakustannus on yksi 250 tavun commit-otsikko.

4. Erilliset työtilat (refs/ws/<actor>/<id>)

Keskeneräiset haarat työnnetään kohteeseen refs/ws/<actor>/<id> eikä kohteeseen refs/heads/*. Sata koodausagentkia voi tallentaa tarkistuspisteitä joka minuutti saastuttamatta haara-pudotusvalikoita tai hidastamatta ihmisinsinöörien tekemää komentoa git fetch.

Käyttöönotto neljässä vaiheessa: Miten harva ja blob-vapaa tarkistus toimii

Tällä viittausasettelulla uusi kehittäjä tai ohimenevä koodausagenttisäiliö ei asenna mukautettua CLI:tä tai FUSE-ajuria. Käyttöönotto vaatii neljä vaihetta vakiomuotoisella Gitillä ja repositorion aliaksilla:

 1# 1. Kloonaa 20 kt:n ohjaustaso blob-suodatuksella ja harvalla tilalla otettuna käyttöön
 2git clone --filter=blob:none --sparse https://github.com/example-org/monorepo.git
 3cd monorepo
 4
 5# 2. Lataa repositorion aliakset ja liitä osoitteet refs/trunk/*
 6git config include.path ../.gitconfig
 7git trunk-init
 8
 9# 3. Ilmoita verkkotunnuksen hakemistot, joita tähän tehtävään tarvitaan
10git sparse-checkout set net/relay ipc/codec
11
12# 4. Luo erillinen työtila, jonka juurena on uusin rungon tilannevedos
13git ws-new alice/optimize-framing

Jokainen vaihe noutaa vain sen, mitä se tarvitsee:

  1. git clone --filter=blob:none --sparse lataa 20 kilotavun ohjaustason osoitteessa refs/heads/main.
  2. git trunk-init määrittää arvon +refs/trunk/*:refs/remotes/origin/trunk/* ja suorittaa blob-vapaan noudon. Git lataa tree-metatiedot kohteelle refs/trunk/main (tyypillisesti muutaman tusinan kilotavua) ja nolla tiedostoblobia.
  3. git sparse-checkout set net/relay ipc/codec ohjeistaa Gitin kartiomoodin indeksisuodattimen toteuttamaan vain juurihakemiston ja kyseiset kaksi alipuuta.
  4. git ws-new siirtyy uuteen haaraan, jonka juurena on origin/trunk/main. Git pyytää sen jälkeen pyynnöstä vain hakemistojen net/relay ja ipc/codec sisällä olevat blob-objektit. Monorepositorion loput 95 % ei koskaan ladata levylle.

Tulevaisuuden horisontti: Osoitteen refs/trunk/main liittäminen virtuaaliseksi tiedostojärjestelmäksi (VFS)

Harva tarkistus blob-vapailla klooneilla kattaa päivittäiset työnkulut ilman ylimääräisiä asiakastyökaluja. Koska refs/trunk/main on jo valmiiksi puhdas Merkle-puu sisältöosoitteellisessa tallennustilassa, arkkitehtuuri tarjoaa myös suoran pohjan valinnaiselle käyttäjätilan virtuaaliselle tiedostojärjestelmälle (VFS) FUSE:n kautta Linuxissa, FileProviderin kautta macOS:ssä tai ProjFS:n kautta Windowsissa:

  1. Välitön koko puun liitos: Kevyt paikallinen liitostaemon lukee osoitteen refs/trunk/main juuri-tree-objektin ja projisoi koko monorepositorion hakemistohierarkian työhakemistoon millisekunneissa, mikä poistaa komennon git sparse-checkout set suorittamisen tarpeen.
  2. Pyynnöstä tapahtuva blobin vikaantuminen: Tiedostojen sisällöt pysyvät virtuaalisina, kunnes kääntäjä, IDE tai agentti antaa järjestelmäkutsun open(2) tai read(2). Daemon noutaa sitten vastaavan SHA-1-blob-objektin CAS-päätepisteestä ja välimuistittaa sen paikalliselle NVMe-tallennustilalle.
  3. Copy-on-Write-peitekerros työtiloille: Paikalliset muokkaukset kirjoitetaan kevyeen ylempään peitekerrokseen. Komennon git ws-save suorittaminen laskee tiivisteet vain kyseisen peitekerroksen muuttuneille poluille, kirjoittaa päivitetyt blob- ja tree-objektit ja työntää tuloksena olevan commitin kohteeseen refs/ws/<actor>/<id> skannaamatta muuttumattomia hakemistoja.

Muutosluettelomalli puhtaalla Gitillä: Muistissa tapahtuva palvelinpuolen maihinnousu

Perinteisessä Git-työnkulussa ominaisuushaaran yhdistäminen joko luo kahden isän merge-commitin, mikä tekee historiasta epälineaarisen, tai vaatii kehittäjiä tekemään rebasen manuaalisesti ja kilpailemaan samanaikaisten päähaaran main työntöjen kanssa.

Innoitetun google3-muutosluettelomallin (CL) mukaisesti jokainen arkkitehtuurimme työtila edustaa yhtä atomista muutosta suhteessa rungon tilannevedokseen. Työskennellessään paikallisesti hakemistossa ws/alice/optimize-framing, kehittäjä tai agentti saattaa tehdä kymmenen inkrementaalista commitia (wip, fix tests, lint). Kun muutos on valmis laskeutumaan, palvelin tiivistää työtilan deltan yhdeksi lineaariseksi runkoversioksi tarkistamatta koskaan työhakemistoa CI-ajurissa.

Näin maihinnoususkripti (land.sh) suoritetaan muistissa käyttäen Gitin 2.40+ -putkistoa:

 1# 1. Tunnista juuritilannevedoksen commit, josta työtila haarautui
 2BASE=$(git rev-list --max-parents=0 "$WORK_SHA")
 3
 4BASE_TREE=$(git rev-parse "${BASE}^{tree}")
 5MAIN_TREE=$(git rev-parse "${OLD_MAIN}^{tree}")
 6WORK_TREE=$(git rev-parse "${WORK_SHA}^{tree}")
 7
 8# 2. Laske yhdistetty juuripuu muistissa ilman työpuun tarkistusta
 9if [ "$MAIN_TREE" = "$BASE_TREE" ]; then
10  NEW_TREE="$WORK_TREE"
11elif OUT=$(git merge-tree --write-tree --merge-base="$BASE_TREE" "$MAIN_TREE" "$WORK_TREE"); then
12  NEW_TREE=$(head -n1 <<<"$OUT")
13else
14  echo "Merge conflict detected; run git ws-sync to rebase." >&2
15  exit 1
16fi

Vaiheessa 2:

  • Riippumatta siitä, kuinka monta paikallista commitia työtilahaaralle tehtiin, skripti vertaa vain kolmea puutiivistettä: alkuperäistä perustilannevedosta ($BASE_TREE), nykyistä rungon tilannevedosta ($MAIN_TREE) ja lopullista työtilan puuta ($WORK_TREE).
  • Jos osoite refs/trunk/main eteni kohteessa //web/blog Alicen muokatessa kohdetta //net/relay, git merge-tree --write-tree laskee yhdistetyn juuripuun $NEW_TREE suoraan Gitin objektivarastossa millisekunneissa kirjoittamatta tiedostoja ajurin tiedostojärjestelmään.
  • Kun alla olevat käytäntötarkistukset läpäistään, yksi komento git push --atomic argumentilla --force-with-lease päivittää osoitteen refs/trunk/main ja liittää yhden lineaarisen commitin osoitteeseen refs/trunk/history, ja maihinnousun liipaisin refs/heads/land/<id> poistetaan.

Arkkitehtuurirajojen valvonta: Nelitasoinen näkyvyys ja hierarkkiset OWNERS-määritykset

Koodin konsolidoiminen yhteen repositorioon toimii vain, jos toimialueiden väliset rajat valvotaan mekaanisesti ennen kuin commit voi laskeutua. Heti sen jälkeen, kun git merge-tree --write-tree tuottaa kohteen $NEW_TREE (ja ennen kuin git push --atomic päivittää rungon), käytäntömoottorimme suorittaa kaksi O(delta)-tarkistusta komennolle git diff-tree "$MAIN_TREE" "$NEW_TREE".

1. Nelitasoinen verkkotunnuksen näkyvyys

Juuripuu on jaettu neljään näkyvyystasoon:

HakemistoetuliiteTasoSallitut tuonnitKielletyt tuonnitOWNERS-portti
//web/*, //net/*, //ipc/*, //storage/*, //crypto/*, //ai/*, //devtools/*Julkinen tuotantoJulkinen tuotanto, //third_party/*//corp/*, //experimental/*Valvottu
//third_party/*Ulkoinen toimittajaItsenäinen tai //third_party/*Kaikki muut kuin third_party-verkkotunnuksetValvottu
//corp/*Sisäinen yksityinenJulkinen tuotanto, //corp/*, //third_party/*//experimental/*Valvottu
//experimental/<actor>/*HiekkalaatikkoMikä tahansa muu kuin corp-paketti//corp/*Vapautettu (automaattisesti hyväksytty)

Jos julkinen paketti kohteessa //web/* yrittää tuoda sisäisen paketin kohteesta //corp/* tai valmistumattoman prototyypin kohteesta //experimental/*, maihinnousutehtävä keskeytetään ennen kuin se koskettaa osoitetta refs/trunk/main.

2. Hierarkkinen OWNERS-todennus ilman Gerrit-palvelinta

Tarkastaja valvoo hakemistotason OWNERS-tiedostoja perimyssäännöillä:

  • Jokaiselle kohteiden $MAIN_TREE ja $NEW_TREE välillä muokatulle polulle tarkastaja kävelee ylöspäin tiedoston hakemistosta kohteeseen //OWNERS.
  • Mikä tahansa OWNERS-tiedosto voi ilmoittaa säännön set noparent estääkseen perityt hyväksynnät ylemmistä hakemistoista tai säännön per-file *.sql=@dba-team rajatakseen hyväksynnät tiedostonimimallin mukaan.
  • Peukaloinnin estävä invariantti: Olemassa olevat OWNERS-tiedostot luetaan aina kohteesta $MAIN_TREE (nykyinen runkopuu), ei koskaan kohteesta $NEW_TREE. Hyväksymätön tekijä ei voi antaa itselleen lupaa muokkaamalla OWNERS-tiedostoa samassa työtilan commitissa.
  • Hiekkalaatikkovapautus: Mikä tahansa polku hiekkalaatikon //experimental/<actor>/* alla ohittaa OWNERS-tarkistukset, jotta insinöörit ja agentit voivat luoda prototyyppejä vapaasti komennolla git ws-exp <actor> <project> ja myöhemmin valmistua paketin tuotantoalueelle komennolla git ws-graduate.

Koodikatselintarkistus ilman kitkaa: Ohimenevät PR:t ja tilannevedosdeltat

Koska osoite refs/heads/main pitää sisällään vain ohjaustason ja refs/trunk/main on isätön commit, vakio-muotoisen GitHub Pull Requestin avaaminen suoraan työtilahaarasta päähaaraan main yrittäisi verrata toisiinsa liittymättömiä historia-arvoja. Ratkaisimme tämän kolmella eri muutoksiin räätälöidyllä katselintarkistustyönkululla:

  1. Välittömät kahden pisteen työtiladeltat (git ws-save + reunadeltareititin) Työtilan työntäminen komennolla git ws-save tuo osoitteen refs/ws/<actor>/<id> näkyviin kevyen reunatyöntekijän kautta. Tämä työntekijä ratkaisee osoitteen refs/trunk/main ja työtilaviittauksen niiden commit-SHA-tiivisteiksi ja ohjaa GitHubin kahden pisteen vertailunäkymään (/compare/<trunk-sha>..<ws-sha>). Pienille korjauksille tai agentin luomille muutoksille arvostelijat voivat tarkastaa deltan ja napsauttaa painiketta Land suoraan verkkokäyttöliittymässä.
  2. Ohimenevät GitHub Pull Requestit (git ws-pr) Rivi riviltä tapahtuvaa katselintarkistusta varten GitHubissa komento git ws-pr työntää juuritilannevedoksen commitin ($(git rev-list --max-parents=0 HEAD)) osoitteeseen refs/heads/base/<id> ja työtilan kärjen osoitteeseen refs/heads/review/<id>. Se avaa sitten GitHub Pull Requestin, joka vertaa haaraa review/<id> haaraan base/<id>. Koska pohjahaara on se tilannevedos, josta työtila haarautui, GitHubin Files changed -välilehti näyttää vain työtilan deltan. Kun arvostelija napsauttaa painiketta Merge pull request, verkkokoukku (webhook) edistää päätason commitin osoitteeseen refs/heads/land/<id>, suorittaa muistissa tapahtuvan maihinnousuputken ja poistaa automaattisesti sekä osoitteen refs/heads/base/<id> että osoitteen refs/heads/review/<id>.
  3. Ulkoiset peilipull requestit Avoimen lähdekoodin avustajien ei koskaan tarvitse oppia monorepositorion työnkulkua. He tekevät haarautumisen (fork) ja avaavat pull requesteja itsenäisiin peilirepositorioihin tavalliseen tapaan.

Muutokset, korjaussarjat ja hyväksyntöjen siirto eteenpäin

Haaran nimi ei voi yksilöidä muutosta. Agentti saattaa nimetä haaransa uudelleen, korjata kärkeä tai tehdä rebasen uudemmalle rungolle useita kertoja ennen maihinnousua. Kuten Gerritissä, työnkulkutunniste tunnistaa muutoksen kärjen commit-viestissä olevasta Change-Id: I<40 hex> -jälkiliitteestä. Komennot git ws-save, git ws-pr ja git ws-land lisäävät jälkiliitteen, kun kärjessä ei ole mitään, ja säilyttävät sen muuten, joten tunnus säilyy korjausten, rebase-toimenpiteiden ja uudelleennimeämisten yli. Maihin laskeutunut rungon commit pitää jälkiliitteen ja tallentaa katselintarkistuksen pull requestin numeron, joten git trunk-cl <number|Change-Id> löytää sen osoitteesta refs/trunk/history.

Jokainen tarkistettavaksi lähetetty kärki muuttuu korjaussarjaksi. Komento git ws-pr työntää sen muuttumattomaan viittaukseen refs/ws/cl/<change-id>/<tip> katselintarkistushaaran viereen. Komennon git ws-pr suorittaminen uudelleen korjauksen tai git ws-sync-komennon jälkeen lisää korjaussarjan samaan pull requestiin. Komento git ws-ps listaa nykyisen muutoksen korjaussarjat, ja git ws-psdiff <a> <b> tulostaa kahden korjaussarjan välisen keskinäisen deltan, joten tarkastaja lukee vain sen, mikä on muuttunut edellisen kierroksen jälkeen.

GitHub sitoo hyväksynnän yhteen ainoaan commitiin, joten jokainen rebase vaatisi normaalisti uuden katselintarkistuksen. Maihinnousuputki hyväksyy myös samalle muutokselle toiselle korjaussarjalle annetun hyväksynnän, kun molemmat korjaussarjat tekevät saman korjauksen omaan pohjatilannevedokseensa. Se vertaa komentoa git patch-id --verbatim koko binäärideltan yli. Puhdas rebase uudemmalle rungolle laskeutuu ilman uutta katselintarkistusta, kun taas kaikki sisällön muokkaukset, mukaan lukien tyhjemerkkien tai tiedostotilan muutokset, vaativat uuden hyväksynnän.

O(delta)-kaksisuuntainen synkronointi ja erilliset tuotantohaarat

Monet organisaatiot julkaisevat yksittäisiä paketteja itsenäisinä GitHub-repositorioina, jotta ulkoiset käyttäjät voivat käyttää komentoja go get, cargo install tai haarauttaa yksittäisen projektin koskematta monorepositorioon. Jotkut projektit, kuten staattiset blogit tai julkaisurajoitetut verkkosovellukset, ylläpitävät myös erillistä production-haaraa päähaaran main rinnalla.

Starlark-synkronointimoottorimme käsittelee sekä lähteviä vientitoimintoja että saapuvia osallistumisia O(delta)-ajassa, joka on verrannollinen commitissa muutettujen tiedostojen määrään eikä monorepositorion kokoon.

  • Blob-vapaa indeksin liitos: Kun liitetään peilirepositorion alipuu monorepositorion juuripuuhun tai siitä pois, moottori asettaa arvon GIT_NO_LAZY_FETCH=1 ja suorittaa komennon git update-index --index-info ja sen jälkeen komennon git write-tree --missing-ok. Muuttumattomat alipuut ja blob-objektit pysyvät SHA-1-tiivisteen viittaamina eikä niitä koskaan ladata CI-ajurille.
  • Vain deltoja sisältävä blob-esihaku: Ennen vietyn commitin työntämistä itsenäiseen peiliin skripti suorittaa komennon git diff-tree -r --diff-filter=AM "$ext_parent" "$export_tree" ja hakee etukäteen vain muutettujen tiedostojen vanhat ja uudet blob-objektit komennolla git cat-file --batch. Git voi sitten laskea ohuen deltapaketin ja työntää sen peilirepositorioon sekunneissa.
  • Työnkulun ja julkaisutason haaran säilyttäminen: Lähtevän viennin aikana synronisoija säilyttää kunkin itsenäisen repositorion oman .github/workflows/-hakemiston, jotta julkiset CI-ajurit suorittavat projektitestejä peilissä. Starlark-määrityksen jokainen työnkulku kohdistuu nimenomaiseen haaraan, kuten main, mikä säilyttää julkaisurajat repositorioille, jotka otetaan käyttöön erillisestä production-haarasta. Monorepositorion maihinnousut synkronoituvat peilin main-haaran kanssa, ja automaattiset metatiedot tai käännöksen commitit haaraan main synkronoituvat takaisin osoitteeseen refs/trunk/main verkkokoukun kautta. Päähaaran main ylentäminen tuotannoksi (production) pysyy nimenomaisena julkaisuvaiheena.

Loppuajatuksia

Tämä arkkitehtuuri käsittelee Gitin objektivarastoa sisältöosoitteellisena tallennustilana (CAS), erottaa osoitteen refs/heads/main osoitteista refs/trunk/main ja refs/trunk/history, tunnistaa jokaisen muutoksen Change-Id-tunnuksella ja muuttumattomilla korjaussarjoilla sekä yhdistää puut muistissa komennolla git merge-tree --write-tree. Käyttöönoton kustannus kasvaa sen mukaan, mitä hakemistoja tehtävä tarvitsee, ja maihinnousun sekä peilisynkronoinnin kustannukset kasvavat muutoksen koon mukaan, eivät repositorion koon mukaan.