Guide · Ändringar över flera repon

En ändring, flera repon, ingen trasig main

De flesta riktiga funktioner korsar tjänstegränser. En enda agent ser bara en del; det svåra är att planera hela ändringen och merga delarna i en ordning där varje repo förblir driftsättningsbart i varje steg.

Av Aerunit-teamet · Senast uppdaterad

Problemet

Varför arbete över flera repon går sönder

Föreställ dig en funktion som berör ett API, dess klientbibliotek och webbappen. Ge varje repo till sin egen agent med samma vaga beskrivning och var och en gör något rimligt. API-agenten byter namn på ett fält, klientagenten behåller det gamla namnet, webbagenten hittar på ett tredje. Varje agent har rätt i sitt eget repo och fel tillsammans.

Två saker går fel: kontraktet mellan reponarna glider isär, och mergeordningen spelar roll. Mergar du konsumenten före producenten är main trasig tills den andra PR:en landar.

Planera en gång

Planera en gång, på arkitekturnivå

Skriv en överordnad story som beskriver hela ändringen — uppdraget, det nya kontraktet, ordningen — och sedan ett underärende per repo, vart och ett med egna acceptanskriterier. Linear stödjer precis detta med överordnade ärenden och underärenden. [4] Det överordnade ärendet håller arkitekturen; varje underärende är tillräckligt litet för en agentkörning. Hur man skriver vart och ett täcks i vår guide om stories för kodningsagenter.

Håll driftsättningsbart

Expand, migrate, contract

Det säkraste sättet att ändra ett gränssnitt som flera repon beror på är ett gammalt. Martin Fowler kallar det parallel change:

"Parallel change, även känt som expand and contract, är ett mönster för att implementera bakåtinkompatibla ändringar av ett gränssnitt på ett säkert sätt, genom att dela upp ändringen i tre distinkta faser: expand, migrate och contract." [1]

Expand

Producenten accepterar och returnerar både den gamla och den nya formen.

Migrate

Varje konsument flyttar till den nya formen, ett repo i taget.

Contract

När varje konsument har flyttat, ta bort den gamla formen.

Varje steg går att driftsätta på egen hand. Googles bok om storskaliga ändringar gör samma poäng i större skala: "den största möjliga atomära ändringen minskar kontraintuitivt" när en kodbas växer, så stora ändringar delas upp i oberoende delar. [2]

Gör det explicit

Koda ordningen som beroenden

Håll inte ordningen i huvudet. I Linear, markera konsument-underärendet som blockerat avproducent-underärendet — blockerade ärenden visas med en orange flagga under "Blocked by" i ärendets sidopanel. [5] Konsumentdelen börjar inte förrän producentdelen har mergats.

Exempel: byt namn customer_name → display_name
Parent: Show customers' chosen display name everywhere
├─ API-1  Expand: accept + return display_name alongside customer_name
├─ SDK-1  Use display_name in the typed client      (blocked by API-1)
├─ WEB-1  Render display_name in account pages      (blocked by SDK-1)
└─ API-2  Contract: remove customer_name            (blocked by WEB-1)

Blocked-by betyder mergad — så se till att mergning av producenten också driftsätter eller publicerar den (för ett SDK, en släppt version) innan konsumentdelen beror på den. Om dina driftsättningar inte sker vid merge, lägg till ett utgivningssteg i producentens story.

Läst uppifrån och ner är det både planen och mergeordningen — och varje rad lämnar main driftsättningsbar. Det är samma idé som att merga parallellt arbete en gren i taget, vilket vi täcker i vår guide om parallella kodningsagenter.

Fånga det i CI

Fastställ kontraktet

Ett kontrakt skrivet bara i en story kan fortfarande glida isär. Fastställ det i kod, så att en mismatch misslyckas i CI: en delad typad klient genererad från en källa, en OpenAPI-spec som båda sidor validerar mot, eller konsumentdrivna kontrakttester. Pact beskriver idén: ett kontrakt är mellan en konsument — "en klient som vill ta emot viss data" — och en leverantör — "ett API på en server som tillhandahåller den data klienten behöver." [3] Konsumentens tester registrerar vad den förväntar sig; leverantörens CI kontrollerar att den fortfarande levererar det.

Ett val

En agent över repon, eller en per repo?

Cursors Cloud Agents kan köras i multirepo-miljöer, där en agent ändrar flera repon i en enda körning och öppnar en pull request i varje. [6] När är det rätt verktyg?

En agent över repon

En liten, tätt sammankopplad ändring som är säker att leverera tillsammans — samma personer äger varje repo och du kan driftsätta dem samtidigt.

En agent per repo

En större ändring, olika ägare, eller något som behöver stegvisa driftsättningar. Separata delar med blocked-by-ordning håller varje steg granskningsbart och driftsättningsbart.

Var vi kommer in

Var Aerunit passar in

Den här guiden kräver två saker: en plan för hela ändringen, och en explicit ordning som håller main driftsättningsbar. Aerunit gör båda. Dess story-skrivare läser varje repo som ändringen berör och föreslår ett överordnat ärende plus ett underärende per berört repo, vart och ett med omfattning, acceptanskriterier och icke-mål.

Aerunit följer Linears blocks / blocked-by-relationer, så när producentdelens PR mergas köas de underärenden den blockerade automatiskt till Cursor Cloud Agents — nästa del börjar ovanpå mergad kod, utan att du dirigerar för hand.

En plan

Ett överordnat ärende plus ett underärende per repo, skrivet från din faktiska kod.

Explicit ordning

Blocked-by-relationer gör mergeordningen synlig i Linear.

En granskning per repo

Varje del är sin egen PR, granskad mot sitt eget underärende.

Snabba svar

Vanliga frågor

Bör vi gå över till en monorepo för agenter?

Inte bara för agenters skull. En monorepo låter en ändring landa atomärt, men även Google, med en av de största monorepos som finns, undviker stora atomära ändringar i skala och delar upp dem i mindre, oberoende delar. Vanorna i den här guiden — planera en gång, expand-migrate-contract, explicit ordning — fungerar i båda uppsättningarna. [2]

Hur stoppar jag agenter i två repon från att hitta på olika fältnamn?

Bestäm kontraktet innan någon agent börjar, skriv in det i den överordnade storyn och fastställ det i kod: en delad typad klient, en OpenAPI-spec eller konsumentdrivna kontrakttester. Då misslyckas en mismatch i CI i stället för i produktion. [3]

Vad händer om en nedströms-del misslyckas efter att den uppströms har mergats?

Det är poängen med expand-migrate-contract: uppströmsändringen accepterar både den gamla och nya formen, så inget går sönder medan den nedströms delen fixas eller görs om. Ta bara bort den gamla formen när varje konsument har flyttat. [1]

Aerunit

Håll agenterna sysselsatta. Du står för tänkandet.

Aerunit är i tidig åtkomst, endast på inbjudan. Betala för det du använder — inga prenumerationer att glömma, och team delar en gemensam kreditpott utan extra kostnad.

Ansök om tidig åtkomst