Dela via


Så utvecklas Microsoft med DevOps

Microsoft strävar efter att använda One Engineering System för att skapa och distribuera alla Microsoft-produkter med en solid DevOps-process centrerad på ett Git-förgrenings- och versionsflöde. Den här artikeln beskriver praktisk implementering, hur systemet skalar från små tjänster till enorma plattformsutvecklingsbehov och lärdomar från att använda systemet i olika Microsoft-team.

Att införa en standardiserad utvecklingsprocess är ett ambitiöst åtagande. Kraven för olika Microsoft-organisationer varierar kraftigt och kraven för olika team inom organisationer skalas med storlek och komplexitet. För att hantera dessa olika behov använder Microsoft en trunkbaserad förgreningsstrategi för att snabbt utveckla produkter, distribuera dem regelbundet och leverera ändringar på ett säkert sätt till produktionen.

Microsoft använder också plattformstekniska principer som en del av sitt One Engineering System.

Microsofts versionsflöde

Varje organisation bör fastställa en standardprocess för kodrelease för att säkerställa enhetlighet mellan teamen. Microsofts versionsflöde innehåller DevOps-processer från utveckling till lansering. De grundläggande stegen i versionsflödet består av gren, push, pull-begäran och sammanslagning.

Filial

För att åtgärda ett fel eller implementera en funktion skapar en utvecklare en ny gren utanför huvudintegreringsgrenen. Git Lightweight-förgreningsmodellen skapar dessa kortlivade ämnesgrenar för varje kodbidrag. Utvecklare gör tidiga åtaganden och undviker långvariga funktionsbrancher med hjälp av funktionsflaggor.

Tryck

När utvecklaren är redo att integrera och skicka ändringar till resten av teamet skickar de sin lokala gren till en gren på servern och öppnar en pull-begäran. Lagringsplatser med flera hundra utvecklare som arbetar i många grenar använder en namngivningskonvention för servergrenar för att lindra förvirring och grenspridning. Utvecklare skapar vanligtvis grenar med namnet users/<username>/feature, där <username> är deras kontonamn.

Förfrågan om sammanslagning

Kontrollämnesgrenen för pull-begäranden sammanfogas till huvudgrenen och ser till att grenprinciperna är uppfyllda. Pull-begärandeprocessen skapar de föreslagna ändringarna och kör ett snabbt testpass. Testsviterna på första och andra nivån kör cirka 60 000 tester på mindre än fem minuter. Detta är inte den fullständiga Microsoft-testmatrisen, men räcker för att snabbt ge förtroende för pull-begäranden.

Därefter granskar andra medlemmar i teamet koden och godkänner ändringarna. Kodgranskningen fortsätter där de automatiserade testerna slutade och är särskilt användbart för att upptäcka arkitekturproblem. Manuella kodgranskningar säkerställer att andra tekniker i teamet har insyn i ändringarna och att kodkvaliteten förblir hög.

Merge

När pull-begäran uppfyller alla byggprinciper och granskare har loggat ut, kopplas ämnesgrenen till huvudintegreringsgrenen och pull-begäran är klar.

Efter sammanfogning körs andra godkännandetester som tar längre tid att slutföra. Dessa traditionella tester efter incheckningen gör en mer grundlig validering. Den här testprocessen ger en bra balans mellan att ha snabba tester under granskning av pull-begäranden och att ha fullständig testtäckning före lanseringen.

Skillnader från GitHub Flow

GitHub Flow är ett populärt trunkbaserat versionsflöde för utveckling för organisationer för att implementera en skalbar metod för Git. Vissa organisationer upptäcker dock att när deras behov växer måste de skilja sig från delar av GitHub Flow.

En ofta förbisedd del av GitHub Flow är till exempel att pull-begäranden måste distribueras till produktion för testning innan de kan kopplas till huvudgrenen. Den här processen innebär att alla pull-begäranden väntar i distributionskön för sammanslagning.

Vissa team har flera hundra utvecklare som ständigt arbetar på en enda lagringsplats, som kan slutföra över 200 pull-begäranden till huvudgrenen per dag. Om varje pull-begäranden kräver en distribution till flera Azure-datacenter över hela världen för testning, ägnar utvecklare tid åt att vänta på att grenar ska slås samman, i stället för att skriva programvara.

I stället fortsätter Microsoft-teamen att utveckla i huvudgrenen av koden och samlar distributioner i batchar till tidsbestämda släpp, som vanligtvis följer en tre veckors sprinttakt.

Implementeringsdetaljer

Här följer några viktiga implementeringsuppgifter för Microsofts versionsflöde:

Strategi för Git-lagringsplats

Olika team har olika strategier för att hantera sina Git-lagringsplatser. Vissa team behåller merparten av sin kod på en Git-lagringsplats. Koden delas upp i komponenter, var och en i sin egen mapp på rotnivå. Stora komponenter, särskilt äldre komponenter, kan ha flera underkomponenter som har separata undermappar i den överordnade komponenten.

Skärmbild som visar en Git-lagringsplatsstruktur.

Adjunct-lagringsplatser

Vissa team hanterar även adjungerade lagringsplatser. Till exempel utvecklas bygg- och släppagenter och uppgifter, VS Code-tillägget och projekt med öppen källkod på GitHub. Konfigurationsändringar registreras i ett separat förråd. Andra paket som teamet är beroende av kommer från andra platser och används via NuGet.

Enkel lagringsplats eller flera lagringsplatser

Medan vissa team väljer att ha en enda monolitisk lagringsplats, en mono-repo, använder andra Microsoft-produkter en metod med flera lagringsplatser. Skype har till exempel hundratals små lagringsplatser som sammanfogas i olika kombinationer för att skapa många olika klienter, tjänster och verktyg. Särskilt för team som arbetar med mikrotjänster kan flera repos vara rätt metod. Äldre produkter som började som monoliter anser att en monorepo-metod är den enklaste övergången till Git, och deras kodorganisation återspeglar det.

Release-förgreningar

Microsofts versionsflöde håller hela tiden huvudgrenen byggbar. Utvecklare arbetar i kortlivade ämnesgrenar som sammanfogas till main. När ett team är redo att lansera, oavsett om det är i slutet av en sprint eller för en större uppdatering, så startar de en ny versionsgren från huvudgrenen. Releasegrenar sammanfogas aldrig tillbaka till huvudgrenen, så de kan kräva cherry-picking av viktiga ändringar.

Följande diagram visar kortlivade grenar i blått och release-grenar i svart. En gren med en incheckning som behöver körsbärsplockning visas i rött.

Diagram som visar git-versionsgrenens struktur.

Grenprinciper och behörigheter

Git-grenprinciper hjälper till att framtvinga versionsgrenstrukturen och hålla huvudgrenen ren. Grenprinciper kan till exempel förhindra direkt överföring till huvudgren.

För att hålla grenhierarkin prydlig använder team behörigheter för att blockera skapande av gren på rotnivå i hierarkin. I följande exempel kan alla skapa grenar i mappar som användare/, funktioner/och team/. Endast versionshanterare har behörighet att skapa grenar under versioner/, och vissa automatiseringsverktyg har behörighet till integreringarna/ mappen.

Skärmbild som visar grenar.

Arbetsflöde för Git-lagringsplats

Utvecklare utför sitt dagliga arbete i lagringsplatsen och grenstrukturen. Arbetsmiljöerna varierar kraftigt beroende på team och individ. Vissa utvecklare föredrar kommandoraden, andra som Visual Studio och andra arbetar på olika plattformar. De strukturer och principer som finns på Microsofts lagringsplatser säkerställer en solid och konsekvent grund.

Ett vanligt arbetsflöde omfattar följande vanliga uppgifter:

Skapa en ny funktion

Att skapa en ny funktion är kärnan i en programvaruutvecklares jobb. Andra delar av processen än Git omfattar att titta på telemetridata, komma med en design och en specifikation och skriva den faktiska koden. Sedan börjar utvecklaren arbeta med arkivet genom att synkronisera med den senaste committen på main. Huvudgrenen är alltid byggbar, så det är garanterat en bra utgångspunkt. Utvecklaren hämtar en ny feature-gren, gör kodändringar, gör en commit, pushar till servern och startar en ny pull request.

Använda grenprinciper och kontroller

När en pull-begäran skapas kontrollerar automatiserade system att den nya koden bygger, inte bryter mot något och inte bryter mot några säkerhets- eller efterlevnadsprinciper. Den här processen hindrar inte annat arbete från att ske parallellt.

Förgreningsprinciper och kontroller kan kräva en framgångsrik bygg, inklusive godkända tester, godkännande av ägare till berörd kod och flera externa kontroller för att verifiera företagsriktlinjer innan en pull-begäran kan slutföras.

Skärmbild som visar kontrollerna på en pull-begäran.

Integrera med Microsoft Teams

Många team konfigurerar integrering med Microsoft Teams, som meddelar den nya pull-begäran till utvecklarnas teammedlemmar. Ägarna till all kod som berörs läggs automatiskt till som granskare. Microsoft-team använder ofta valfria granskare för kod som många rör vid, till exempel REST-klientgenerering och delade kontroller, för att få expertögon på dessa ändringar.

Skärmbild som visar Teams-integrering.

Skärmbild som visar Teams-meddelande om en pull-begäran.

Distribuera med funktionsflaggor

När granskarna, kodägarna och automatiseringen är nöjda kan utvecklaren slutföra pull-begäran. Om det finns en sammanslagningskonflikt får utvecklaren instruktioner om hur du synkroniserar till konflikten, åtgärdar den och push-överför ändringarna igen. Automatiseringen körs igen på den fasta koden, men människor behöver inte logga ut igen.

Grenen sammanfogas till mainoch den nya koden distribueras i nästa sprint eller större version. Det betyder inte att den nya funktionen visas direkt. Microsoft frikopplar distributionen och exponeringen av nya funktioner med hjälp av funktionsflaggor.

Även om funktionen behöver lite mer arbete innan den är redo att visas upp, är det säkert att gå till main om produkten kompileras och distribueras. Väl i mainblir koden en del av en officiell version, där den testas igen, bekräftas uppfylla principen och signeras digitalt.

Flytta åt vänster för att identifiera problem tidigt

Det här Git-arbetsflödet ger flera fördelar. För det första eliminerar arbetet från en enda huvudgren praktiskt taget sammanslagningsskulden. För det andra är flödet för pull-begäran en vanlig punkt för att framtvinga testning, kodgranskning och felidentifiering tidigt i pipelinen. Den här skifta vänster-strategin hjälper till att förkorta utvecklarnas feedbackcykel eftersom den kan upptäcka fel på minuter istället för timmar eller dagar. Den här strategin ger också förtroende för refaktorisering, eftersom alla ändringar testas hela tiden.

För närvarande kan en produkt med över 200 pull-begäranden producera 300+ kontinuerliga integreringsversioner per dag, vilket motsvarar över 500 testkörningar var 24:e timme. Den här testnivån skulle vara omöjlig utan det trunkbaserade arbetsflödet för förgrening och lansering.

Lansering vid sprintmilstolpar

I slutet av varje sprint skapar teamet en release-gren från huvudgrenen. I slutet av sprint 129 skapar teamet till exempel en ny versionsgren releases/M129. Teamet sätter sedan sprint 129-grenen i produktion.

Efter grenen av versionsgrenen förblir huvudgrenen öppen för utvecklare att sammanfoga ändringar. Dessa ändringar distribueras tre veckor senare i nästa sprintdistribution.

Illustration av releasegrenen för sprint 129.

Släpp snabbkorrigeringar

Ibland måste ändringar snabbt gå till produktion. Microsoft lägger vanligtvis inte till nya funktioner mitt i en sprint, men vill ibland snabbt få in en felkorrigering för att avblockera användare. Problem kan vara mindre, till exempel stavfel eller tillräckligt stora för att orsaka ett tillgänglighetsproblem eller en incident med livewebbplatsen.

Att åtgärda dessa problem börjar med det normala arbetsflödet. En utvecklare skapar en gren från main, hämtar koden granskad och slutför pull-begäran för att sammanfoga den. Processen börjar alltid med att först göra ändringen i main. På så sätt kan du snabbt skapa korrigeringen och verifiera den lokalt utan att behöva växla till versionsgrenen.

Att följa den här processen garanterar också att ändringen hamnar i main, vilket är avgörande. Om du åtgärdar en bugg i versionsgrenen utan att införa ändringen åter till main skulle felet uppstå igen under nästa distribution, när versionsgrenen för sprint 130 skapas från main. Det är lätt att glömma att uppdatera main under förvirringen och stressen som kan uppstå under ett avbrott. Att göra ändringar i main först betyder att alltid ha ändringarna i både huvudgrenen och release-grenen.

Git-funktioner aktiverar det här arbetsflödet. När en utvecklare har sammanfogat en pull-begäran till main, kan de använda sidan för pull-begäran för att välja ut specifika ändringar till versionsgrenen för att omedelbart föra in ändringarna i produktionen. Den här processen skapar en ny pull request som riktar sig mot versionsgrenen och backporterar innehållet som nyligen sammanfogats till main.

Bild av körsbärsplockning av en snabbkorrigering i gren 129.

Med hjälp av cherry-pick-funktionen kan en pull-begäran öppnas snabbt, vilket ger spårbarhet och tillförlitlighet för branchpolicyer. Körsbärsplockning kan ske på servern, utan att du behöver ladda ned versionsgrenen till en lokal dator. Att göra ändringar, åtgärda sammanslagningskonflikter eller göra mindre ändringar på grund av skillnader mellan de två grenarna kan alla ske på servern. Teams kan redigera ändringar direkt från den webbläsarbaserade textredigeraren eller via konflikttillägget för sammanslagning av pull-begäran för en mer avancerad upplevelse.

När en pull-begäran riktar sig mot versionsgrenen granskar teamkoden den igen, utvärderar grenprinciper, testar pull-begäran och sammanfogar den. Efter sammanfogningen distribueras korrigeringen till den första ring av servrar på några minuter. Därifrån distribuerar teamet stegvis korrigeringen till fler konton med hjälp av distributionsringar. När ändringarna distribueras till fler användare övervakar teamet framgång och verifierar att ändringen åtgärdar felet utan att införa några brister eller avmattningar. Korrigeringen distribueras så småningom till alla Azure-datacenter.

Gå vidare till nästa sprint

Under de kommande tre veckorna har teamet lagt till funktioner i sprint 130 och gör sig redo att distribuera ändringarna. De skapar den nya versionsgrenen releases/M130 från mainoch distribuerar den grenen.

I det här läget finns det faktiskt två grenar i produktionen. Med en ringbaserad distribution för att göra produktionsändringar på ett säkert sätt får den snabba ringen sprint 130-ändringar och de långsamma ringservrarna ligger kvar på sprint 129 medan de nya ändringarna verifieras i produktion.

Snabbkorrigering av en ändring mitt i en distribution kan kräva snabbkorrigering av två olika versioner, sprint 129-versionen och sprint 130-versionen. Teamet portar och distribuerar snabbkorrigeringen till båda versionsgrenarna. 130-grenen återdistribueras med snabbkorrigeringen till ringarna som redan har uppgraderats. 129-grenen omdistribueras med en snabbkorrigering till de externa ringarna som inte har uppgraderats till nästa sprintversion ännu.

När alla ringar har distribuerats överges den gamla sprint 129-grenen helt, eftersom eventuella förändringar som införts i sprint 129-grenen som snabbkorrigeringar också har införts i main. Så dessa ändringar kommer också att finnas i grenen releases/M130 .

Bild av en versionsgren på sprint 130.

Sammanfattning

Versionsflödesmodellen är kärnan i hur Microsoft utvecklar med DevOps för att leverera onlinetjänster. Den här modellen använder en enkel, trunkbaserad förgreningsstrategi. Men i stället för att hålla utvecklarna fast i en distributionskö och vänta på att sammanfoga sina ändringar kan utvecklarna fortsätta att arbeta i Microsofts versionsflöde.

Den här versionsmodellen gör det också möjligt att distribuera nya funktioner i Azure-datacenter regelbundet, trots storleken på Microsofts kodbaser och antalet utvecklare som arbetar i dem. Modellen gör det också möjligt att snabbt och effektivt föra in snabbkorrigeringar i produktion.