Utvecklingen av CI i det mobila utvecklingsteamet

Idag utvecklas de flesta mjukvaruprodukter i team. Förutsättningarna för framgång i teamutveckling kan sammanfattas i ett enkelt diagram.

Utvecklingen av CI i det mobila utvecklingsteamet

När du har skrivit koden måste du se till att den:

  1. Работает.
  2. Bryter ingenting, inklusive koden dina kollegor skrev.

Om båda villkoren är uppfyllda är du på väg mot framgång. För att enkelt kontrollera dessa villkor och inte stänga av den lönsamma vägen kom de med kontinuerlig integration.

CI är ett arbetsflöde där du integrerar din kod i den övergripande produktkoden så ofta som möjligt. Och inte bara integrera, utan också hela tiden kontrollera att allt fungerar. Eftersom du behöver kolla mycket och ofta bör du tänka på automatisering. Du kan kontrollera allt om manuell dragkraft, men du borde inte, och här är varför.

  • Kära människor. En timmes arbete för vilken programmerare som helst kostar mer än en timmes arbete för vilken server som helst.
  • människor har fel. Därför kan situationer uppstå när tester kördes på fel gren eller samlade in fel commit för testare.
  • Folk är lata. Med jämna mellanrum, när jag är klar med någon uppgift, har jag en tanke: "Vad finns det att kontrollera? Jag skrev två rader – absolut allt fungerar! Jag tror att vissa av er har sådana tankar ibland också. Men du ska alltid kolla.

Nikolay Nesterov berättar hur Continuous Integration implementerades och utvecklades i Avitos mobila utvecklingsteam, hur de fick från 0 till 450 builds per dag och hur byggmaskiner monteras 200 timmar om dagen (nnesterov) är en deltagare i alla evolutionära förändringar av CI/CD Android-applikationen.

Berättelsen är baserad på exemplet från Android-teamet, men de flesta tillvägagångssätten är tillämpliga på iOS också.


En gång i tiden arbetade en person i Avitos Android-team. Per definition behövde han ingenting från Continuous Integration: det fanns ingen att integrera med.

Men applikationen växte, fler och fler nya uppgifter dök upp och teamet växte därefter. Vid något tillfälle var det dags att mer formellt etablera processen för att integrera koden. Det beslutades att använda Git flow.

Utvecklingen av CI i det mobila utvecklingsteamet

Konceptet med Git-flöde är välkänt: projektet har en gemensam utvecklingsgren, och för varje ny funktion skär utvecklare av en separat gren, förbinder sig till den, pushar, och när de vill hälla sin kod i utvecklargrenen, öppna en pull-begäran. För att dela kunskap och diskutera tillvägagångssätt införde vi kodgranskning, det vill säga att kollegor måste kontrollera och bekräfta varandras kod.

checkar

Att titta på koden med ögonen är coolt, men inte tillräckligt. Därför införs automatiska kontroller.

  • Först och främst kollar vi ARC montering.
  • Mycket Junit testar.
  • Vi överväger kodtäckning, eftersom vi kör testerna.

För att förstå hur man kör dessa kontroller, låt oss titta på utvecklingsprocessen i Avito.

Schematiskt kan det representeras enligt följande:

  • En utvecklare skriver kod på sin bärbara dator. Du kan köra integrationskontroller här - antingen som en commit-hook eller bara köra kontroller i bakgrunden.
  • Efter att utvecklaren har tryckt på koden öppnar han en pull-begäran. För att dess kod ska komma in i utvecklingsgrenen är det nödvändigt att passera en kodgranskning och samla in det nödvändiga antalet bekräftelser. Du kan aktivera kontroller och builds här: tills alla builds är framgångsrika kan pull-begäran inte slås samman.
  • Efter att pull-begäran har slagits samman och koden börjar utvecklas kan du välja en lämplig tidpunkt: till exempel på natten, när alla servrar är lediga, och köra kontroller så mycket du vill.

Ingen gillade att köra kontroller på sin bärbara dator. När en utvecklare har avslutat en funktion vill de driva den snabbt och öppna en pull-förfrågan. Om för närvarande några långa kontroller lanseras, är detta inte bara inte särskilt trevligt, utan saktar också ner utvecklingen: medan den bärbara datorn kontrollerar något är det omöjligt att arbeta med det normalt.

Vi gillade verkligen att köra kontroller på natten, eftersom det finns mycket tid och servrar kan du roama. Men tyvärr, när funktionskoden började utvecklas, har utvecklaren redan mycket mindre motivation att fixa de buggar som CI hittade. Jag kom på mig själv med jämna mellanrum och tänkte när jag tittade på alla fel som hittats i morgonrapporten att jag skulle fixa dem någon gång senare, för nu finns det en cool ny uppgift i Jira som jag verkligen vill börja göra.

Om kontrollerna blockerar pull-begäran, finns det tillräckligt med motivation, för tills byggen blir gröna kommer koden inte att utvecklas, vilket betyder att uppgiften inte kommer att slutföras.

Som ett resultat valde vi följande strategi: på natten kör vi maximalt möjliga uppsättning kontroller, och de mest kritiska av dem och, viktigast av allt, de snabbaste, lanseras på en pull-begäran. Men vi slutar inte där - parallellt optimerar vi hastigheten för att passera kontroller på ett sådant sätt att de överförs från nattläge till att dra förfrågningskontroller.

På den tiden gick alla våra builds ganska snabbt, så vi inkluderade helt enkelt ARC-bygget, Junit-tester och kodtäckningsberäkning som en blockerare för pull-begäran. De slog på den, tänkte på det - och övergav kodtäckningen, eftersom de ansåg att vi inte behövde den.

Det tog oss två dagar att ställa in den grundläggande CI (hädanefter är tidsuppskattningen ungefärlig, nödvändig för skalan).

Efter det började de fundera vidare – kollar vi överhuvudtaget rätt? Kör vi builds på en pull-begäran korrekt?

Vi körde konstruktionen på den sista commit av grenen som pull-begäran öppnades med. Men recensioner av detta åtagande kan bara visa att koden som utvecklaren skrev fungerar. Men de bevisar inte att han inte har brutit något. Faktum är att du måste kontrollera tillståndet för utvecklingsgrenen efter att en funktion har slagits samman i den.

Utvecklingen av CI i det mobila utvecklingsteamet

För att göra detta skrev vi ett enkelt bash-skript premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Här dras helt enkelt alla de senaste förändringarna från develop upp och slås samman i den nuvarande grenen. Vi lade till premerge.sh-skriptet som första steg i alla builds och började kolla exakt vad vi vill ha, det vill säga integration.

Det tog tre dagar att lokalisera problemet, hitta en lösning och skriva det här skriptet.

Applikationen utvecklades, fler och fler uppgifter dök upp, teamet växte och premerge.sh började ibland svika oss. Develop fick motstridiga förändringar som bröt bygget.

Ett exempel på hur detta går till:

Utvecklingen av CI i det mobila utvecklingsteamet

Två utvecklare börjar arbeta med funktioner A och B samtidigt. Utvecklaren av funktion A upptäcker en oanvänd funktion i projektet answer() och, som en bra scout, tar bort den. Samtidigt lägger utvecklaren av funktion B i sin gren ett nytt anrop till denna funktion.

Utvecklare avslutar arbetet och öppnar pull-förfrågningar samtidigt. Bygger lanseras, premerge.sh kontrollerar båda pull-förfrågningarna mot det färska utvecklingsläget - alla kontroller är gröna. Efter det slås pull-begäran för funktion A samman, pull-begäran för funktion B slås samman... Bom! Utveckla pauser eftersom utveckla koden innehåller ett anrop till en icke-existerande funktion.

Utvecklingen av CI i det mobila utvecklingsteamet

När det inte kommer att utvecklas så är det lokal katastrof. Hela laget kan inte samla in någonting och ge det för testning.

Det blev så att jag oftast var involverad i infrastrukturuppgifter: analys, nätverk, databaser. Det vill säga, det var jag som skrev de funktionerna och klasserna som andra utvecklare använder. På grund av detta hamnar jag ofta i sådana situationer. Jag hade till och med den här bilden ett tag.

Utvecklingen av CI i det mobila utvecklingsteamet

Eftersom detta inte passade oss började vi utarbeta alternativ för hur vi skulle kunna förhindra detta.

Hur man inte bryta utveckla

Det första alternativet: bygga om alla pull-förfrågningar vid uppdatering av develop. Om, i vårt exempel, en pull-begäran med funktion A börjar utvecklas först, kommer pull-begäran för funktion B att byggas om, och följaktligen kommer kontrollerna att misslyckas på grund av ett kompileringsfel.

För att förstå hur lång tid det kommer att ta, överväg exemplet med två PR. Vi öppnar två PR: två builds, två lanseringar av kontroller. Efter att den första PR har slagits samman till utveckla måste den andra byggas om. Totalt tar två PR:er tre kontroller: 2 + 1 = 3.

I grund och botten är det bra. Men vi tittade på statistiken, och en typisk situation i vårt team var 10 öppna PR, och då är antalet kontroller summan av progressionen: 10 + 9 + ... + 1 = 55. Det vill säga att acceptera 10 PRs, du behöver bygga om 55 gånger. Och detta är i en idealisk situation, när alla kontroller passerar första gången, när ingen öppnar en extra pull-begäran medan detta dussin bearbetas.

Föreställ dig dig själv som en utvecklare som måste vara den första att trycka på "sammanfoga"-knappen, för om en granne gör detta måste du vänta tills alla byggen går igenom igen ... Nej, det kommer inte att fungera, det kommer att bromsa utvecklingen rejält.

Andra möjliga sättet: samla in pull-begäran efter kodgranskning. Det vill säga öppna en pull-förfrågan, samla in det antal godkännanden som krävs från kollegor, fixa det du behöver och kör sedan byggen. Om de lyckas slås pull-begäran samman till develop. I det här fallet finns det inga ytterligare omstarter, men återkopplingen saktas ner kraftigt. Som utvecklare, när jag öppnar en pull-förfrågan, vill jag genast se om det kommer att göra det. Till exempel, om något test har fallit måste du snabbt fixa det. Vid ett försenat bygge bromsar feedbacken, och därmed hela utvecklingen. Det passade inte oss heller.

Som ett resultat återstod bara det tredje alternativet - cykling. All vår kod, alla våra källor lagras i ett arkiv i Bitbucket-servern. Därför var vi tvungna att utveckla ett plugin för Bitbucket.

Utvecklingen av CI i det mobila utvecklingsteamet

Denna plugin åsidosätter sammanslagningsmekanismen för pull-begäran. Början är standard: PR öppnas, alla builds lanseras, kodgranskning genomförs. Men efter att kodgranskningen är klar och utvecklaren bestämmer sig för att klicka på "sammanfoga", kontrollerar plugin-programmet mot vilket utvecklingstillstånd kontrollerna kördes. Om develop lyckades uppdatera efter byggnaderna kommer plugin inte att tillåta en sådan pull-begäran att slås samman med huvudgrenen. Det kommer helt enkelt att starta om byggen med avseende på den nya utvecklingen.

Utvecklingen av CI i det mobila utvecklingsteamet

I vårt exempel med motstridiga ändringar kommer sådana builds att misslyckas på grund av ett kompileringsfel. Följaktligen måste utvecklaren av funktion B fixa koden, starta om kontrollerna, sedan kommer plugin-programmet automatiskt att tillämpa pull-begäran.

Innan vi implementerade detta plugin hade vi i genomsnitt 2,7 utcheckningar per pull-begäran. Med plugin blev det 3,6 lansering. Det passade oss.

Det är värt att notera att detta plugin har en nackdel: det startar bara om bygget en gång. Det vill säga, det finns fortfarande ett litet fönster genom vilket motstridiga förändringar kan utvecklas. Men sannolikheten för detta är låg, och vi gjorde den här kompromissen mellan antalet lanseringar och sannolikheten för ett haveri. På två år sköt den bara en gång, så förmodligen inte förgäves.

Det tog oss två veckor att skriva den första versionen av plugin för Bitbucket.

Nya kontroller

Samtidigt fortsatte vårt team att växa. Nya kontroller har lagts till.

Vi tänkte: varför åtgärda misstag om de kan förhindras? Och så introducerade de statisk kodanalys. Vi började med lint, som ingår i Android SDK. Men vid den tiden visste han inte alls hur han skulle arbeta med Kotlin-kod, och vi hade redan 75 % av ansökan skriven i Kotlin. Därför lades inbyggda till lint Android Studio kontrollerar.

För att göra detta var jag tvungen att pervertera mycket: ta Android Studio, paketera den i Docker och kör den på CI med en virtuell bildskärm så att den tror att den körs på en riktig bärbar dator. Men det fungerade.

Även vid den här tiden började vi skriva mycket testa instrumentering och genomförs skärmdump testning. Det är då en referensskärmdump genereras för en separat liten vy, och testet är att en skärmdump tas från vyn och jämförs med referensen direkt pixel för pixel. Om det finns en diskrepans betyder det att layouten gick fel någonstans eller att något är fel i stilarna.

Men instrumenttester och skärmdumptester måste köras på enheter: på emulatorer eller på riktiga enheter. Med tanke på att det är många tester och att de ofta tävlas behövs en hel gård. Att starta en egen gård är för arbetskrävande, så vi hittade ett färdigt alternativ - Firebase Test Lab.

Firebase Test Lab

Valdes för att Firebase är en produkt från Google, vilket betyder att den ska vara pålitlig och sannolikt inte kommer att dö. Priserna är överkomliga: $5 per timme för en riktig enhet, $1 per timme för en emulator.

Det tog ungefär tre veckor att implementera Firebase Test Lab i vår CI.

Men teamet fortsatte att växa och Firebase började tyvärr svika oss. Vid den tiden hade han ingen SLA. Ibland fick Firebase oss att vänta tills det erforderliga antalet enheter för tester frigjordes och började inte köra dem direkt där, som vi ville. Att stå i kö tog upp till en halvtimme, vilket är väldigt lång tid. Instrumenttester tävlade på varje PR, förseningar bromsade utvecklingen mycket, och sedan kom månadsräkningen med en rund summa. I allmänhet beslutades det att överge Firebase och skära in-house, eftersom teamet hade vuxit tillräckligt.

docker + python + bash

De tog docker, stoppade in emulatorer, skrev ett enkelt Python-program som vid rätt tidpunkt höjer rätt antal emulatorer i rätt version och stoppar dem när det behövs. Och, naturligtvis, ett par bash-manus - var skulle vi vara utan dem?

Det tog fem veckor att skapa vår egen testmiljö.

Resultatet blev en omfattande, sammanslagningsblockerande lista med kontroller för varje pull-begäran:

  • Församling av ARC;
  • Junit tester;
  • Ludd;
  • Android Studio-kontroller;
  • instrumenteringstester;
  • Skärmdump tester.

Detta förhindrade många möjliga haverier. Tekniskt sett fungerade allt, men utvecklarna klagade på att det tog för lång tid att vänta på resultaten.

För lång - hur mycket? Vi laddade upp data från Bitbucket och TeamCity till analyssystemet och insåg det genomsnittlig väntetid 45 minuter. Det vill säga, en utvecklare som öppnar en pull-begäran väntar i genomsnitt 45 minuter på resultatet av byggen. Enligt mig är det här mycket, och det är omöjligt att jobba så här.

Naturligtvis bestämde vi oss för att snabba upp alla våra byggen.

Vi accelererar

Ser att byggen ofta står i kö, vi först och främst köpte mer järn – Omfattande utveckling är det enklaste. Bygger slutade köa, men väntetiderna gick bara ner lite, eftersom vissa kontroller själva jagade väldigt länge.

Ta bort för långa kontroller

Vår kontinuerliga integration kan fånga upp dessa typer av fel och problem.

  • Går inte. CI kan fånga ett kompileringsfel när motstridiga ändringar hindrar något från att byggas. Som sagt, då kan ingen bygga något, utvecklingen stannar av, och alla blir nervösa.
  • Bugg i beteende. Till exempel när applikationen är monterad, men när knappen trycks ned, faller den, eller knappen trycks inte in alls. Detta är dåligt, eftersom en sådan bugg kan komma till användaren.
  • Bugg i layout. Till exempel trycks en knapp ned men flyttas 10 pixlar åt vänster.
  • Ökning av tekniska skulder.

Efter att ha tittat på den här listan insåg vi att endast de två första punkterna är kritiska. Vi vill fånga upp sådana problem i första hand. Buggar i layouten upptäcks vid design-granskningsstadiet och fixas enkelt samtidigt. Att arbeta med tekniska skulder kräver en separat process och planering, så vi bestämde oss för att inte kontrollera det för en pull-förfrågan.

Baserat på denna klassificering skakade vi upp hela listan med kontroller. Stryk ut lint och sköt upp lanseringen för natten: bara så att den ger en rapport om hur många problem det finns i projektet. Med tekniska skulder kom vi överens om att arbeta separat, och Android Studio-kontroller övergavs helt. Android Studio i Docker att köra inspektioner låter intressant men orsakar mycket problem i supporten. Varje uppdatering av Android Studio-versioner är en kamp med obegripliga buggar. Det var också svårt att upprätthålla skärmdumpstester, eftersom biblioteket inte var särskilt stabilt, det fanns falska positiva resultat. Skärmdumpstester har tagits bort från listan över kontroller.

Som ett resultat har vi kvar:

  • Församling av ARC;
  • Junit tester;
  • instrumenteringstester.

Gradle fjärrcache

Utan tunga kontroller blev allt bättre. Men det finns ingen gräns för perfektion!

Vår applikation har redan delats upp i cirka 150 gradle-moduler. Gradle remote cache fungerar vanligtvis bra i det här fallet, och vi bestämde oss för att prova.

Gradle remote cache är en tjänst som kan cachebygga artefakter för individuella uppgifter i enskilda moduler. Gradle, istället för att faktiskt kompilera koden, knackar på fjärrcachen via HTTP och frågar om någon redan har utfört denna uppgift. Om ja, ladda bara ner resultatet.

Det är enkelt att köra Gradle fjärrcache eftersom Gradle tillhandahåller en Docker-bild. Vi lyckades göra det på tre timmar.

Allt du behövde göra var att köra Docker och skriva en rad i projektet. Men även om du kan starta det snabbt, kommer det att ta mycket tid att få allt att fungera bra.

Nedan är en graf över cachemissar.

Utvecklingen av CI i det mobila utvecklingsteamet

I början var andelen cachemissar cirka 65. Efter tre veckor lyckades vi få upp detta värde till 20%. Det visade sig att uppgifterna som Android-applikationen samlar in har konstiga transitiva beroenden, vilket gjorde att Gradle missade cachen.

Genom att aktivera cachen påskyndade vi bygget avsevärt. Men förutom montering körs även instrumenttester och de pågår länge. Kanske inte alla tester behöver köras på varje pull-förfrågan. För att ta reda på det använder vi konsekvensanalys.

Konsekvensanalys

På en pull-förfrågan samlar vi git diff och hittar de modifierade Gradle-modulerna.

Utvecklingen av CI i det mobila utvecklingsteamet

Det är vettigt att endast köra de instrumenttester som kontrollerar de modifierade modulerna och alla moduler som är beroende av dem. Det är ingen mening att köra tester för angränsande moduler: koden har inte ändrats där, och ingenting kan gå sönder.

Med instrumenteringstester är saker och ting inte så enkla, eftersom de måste finnas i applikationsmodulen på toppnivå. Vi tillämpade bytekodanalysheuristik för att förstå vilken modul varje test tillhör.

Det tog cirka åtta veckor att modernisera hur instrumenttesterna fungerar så att de bara testar de inblandade modulerna.

Åtgärder för att påskynda inspektionerna har fungerat framgångsrikt. Från 45 minuter kom vi till cirka 15. En kvart att vänta på bygget är redan normalt.

Men nu har utvecklarna börjat klaga på att de inte förstår vilka builds som körs, var man kan se loggen, varför bygget är rött, vilket test som misslyckades osv.

Utvecklingen av CI i det mobila utvecklingsteamet

Feedbackproblem bromsar utvecklingen, så vi har försökt ge så tydlig och detaljerad information som möjligt om varje PR och bygg. Vi började med kommentarer i Bitbucket till PR, som indikerar vilket bygge som föll och varför, och skrev riktade meddelanden i Slack. Till slut gjorde vi en dashboard för PR-sidan med en lista över alla builds som körs för närvarande och deras status: i kön, igång, kraschade eller slutförda. Du kan klicka på byggnaden och komma till dess logg.

Utvecklingen av CI i det mobila utvecklingsteamet

Sex veckor ägnades åt detaljerad feedback.

planer

Låt oss gå vidare till den senaste historien. Efter att ha löst problemet med feedback nådde vi en ny nivå - vi bestämde oss för att bygga vår egen emulatorfarm. När det finns många tester och emulatorer är de svåra att hantera. Som ett resultat flyttade alla våra emulatorer till ett k8s-kluster med flexibel resurshantering.

Dessutom finns andra planer.

  • Returnera lint (och annan statisk analys). Vi arbetar redan i denna riktning.
  • Kör allt på PR-blockerare end-to-end tester på alla SDK-versioner.

Så vi har spårat historien om utvecklingen av kontinuerlig integration i Avito. Nu vill jag ge några råd från den erfarnas synvinkel.

Советы

Om jag bara kunde ge ett råd så skulle det vara detta:

Var försiktig med skalskript!

Bash är ett mycket flexibelt och kraftfullt verktyg, det är väldigt bekvämt och snabbt att skriva skript på det. Men med honom kan du falla i en fälla, och vi hamnade tyvärr i den.

Allt började med enkla skript som kördes på våra byggmaskiner:

#!/usr/bin/env bash
./gradlew assembleDebug

Men som ni vet utvecklas allt och blir mer komplicerat med tiden - låt oss köra ett skript från ett annat, låt oss skicka några parametrar dit - som ett resultat var vi tvungna att skriva en funktion som bestämmer på vilken nivå av bash-kapsling vi nu befinner oss i för att ersätta de nödvändiga offerterna för att få igång det hela.

Utvecklingen av CI i det mobila utvecklingsteamet

Du kan föreställa dig det arbete som är involverat i att utveckla sådana manus. Jag råder dig att inte falla i denna fälla.

Vad kan bytas ut?

  • Vilket skriptspråk som helst. skriva på Python eller Kotlin Script bekvämare eftersom det är programmering, inte skript.
  • Eller beskriv hela bygglogiken i formuläret Anpassade graderade uppgifter för ditt projekt.

Vi bestämde oss för att välja det andra alternativet, och nu tar vi systematiskt bort alla bash-skript och skriver många anpassade gradle-uppgifter.

Tips #2: Lagra infrastruktur i kod.

Det är praktiskt när inställningen för kontinuerlig integration inte lagras i Jenkins eller TeamCity UI, etc., utan i form av textfiler direkt i projektförrådet. Detta ger versionshantering. Det kommer inte att vara svårt att återställa eller bygga koden på en annan gren.

Skript kan lagras i ett projekt. Och vad ska man göra med miljön?

Tips #3: Docker kan hjälpa till med miljön.

Det kommer definitivt att hjälpa Android-utvecklare, tyvärr inte iOS än.

Det här är ett exempel på en enkel docker-fil som innehåller jdk och android-sdk:

FROM openjdk:8

ENV SDK_URL="https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" 
    ANDROID_HOME="/usr/local/android-sdk" 
    ANDROID_VERSION=26 
    ANDROID_BUILD_TOOLS_VERSION=26.0.2

# Download Android SDK
RUN mkdir "$ANDROID_HOME" .android 
    && cd "$ANDROID_HOME" 
    && curl -o sdk.zip $SDK_URL 
    && unzip sdk.zip 
    && rm sdk.zip 
    && yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses

# Install Android Build Tool and Libraries
RUN $ANDROID_HOME/tools/bin/sdkmanager --update
RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" 
    "platforms;android-${ANDROID_VERSION}" 
    "platform-tools"

RUN mkdir /application
WORKDIR /application

Efter att ha skrivit denna docker-fil (jag ska berätta en hemlighet, du behöver inte skriva den, men ladda ner den från GitHub) och bygga bilden får du en virtuell maskin på vilken du kan bygga applikationen och köra Junit-tester .

De två huvudargumenten till varför detta är vettigt är skalbarhet och repeterbarhet. Med docker kan du snabbt höja ett dussin byggagenter, som kommer att ha exakt samma miljö som den föregående. Detta gör livet för CI-ingenjörer mycket enklare. Att trycka in android-sdk i docker är ganska enkelt, med emulatorer är det lite svårare: du måste arbeta lite hårdare (nåja, eller ladda ner det igen från GitHub).

Tips nummer 4: glöm inte att kontroller görs inte för kontrollernas skull, utan för människor.

Snabb och, viktigast av allt, förståelig feedback är mycket viktig för utvecklare: vad som gick sönder, vilket test misslyckades, var kan man se byggloggen.

Tips #5: Var pragmatisk när du utvecklar kontinuerlig integration.

Förstå tydligt vilka typer av fel du vill förhindra, hur mycket du är villig att spendera resurser, tid, maskintid. Checkar som är för långa kan till exempel flyttas över natten. Och de av dem som fångar inte särskilt viktiga fel bör helt överges.

Tips #6: Använd färdiga verktyg.

Nu finns det många företag som tillhandahåller moln CI.

Utvecklingen av CI i det mobila utvecklingsteamet

För små team är detta en bra lösning. Du behöver inte underhålla någonting, bara betala lite pengar, bygga din applikation och till och med köra instrumenteringstester.

Tips nummer 7: Interna lösningar är mer lönsamma i ett stort team.

Men förr eller senare, med teamets tillväxt, kommer interna lösningar att bli mer lönsamma. Det finns en poäng med dessa beslut. Det finns en lag om minskande avkastning inom ekonomi: i alla projekt är varje successiv förbättring svårare, kräver mer och mer investeringar.

Ekonomi beskriver hela vårt liv, inklusive kontinuerlig integration. Jag byggde ett schema över arbetskostnader för varje steg i utvecklingen av vår kontinuerliga integration.

Utvecklingen av CI i det mobila utvecklingsteamet

Det kan ses att varje förbättring ges svårare och svårare. När du tittar på den här grafen kan du förstå att du behöver utveckla kontinuerlig integration i takt med att teamets storlek växer. För ett team på två personer är det ingen bra idé att lägga 50 dagar på att utveckla en intern emulatorfarm. Men samtidigt, för ett stort team, är det också en dålig idé att inte göra kontinuerlig integration alls, eftersom integrationsproblem, kommunikationsreparation osv. det kommer att ta ännu mer tid.

Vi började med att automatisering behövs för att människor är dyra, de gör misstag och är lata. Men folk automatiserar också. Därför gäller alla samma problem för automatisering.

  • Automatisering är dyrt. Kom ihåg arbetsschemat.
  • När det kommer till automatisering gör människor misstag.
  • Ibland är det för lat för att automatisera, för allt fungerar ändå. Varför förbättra något annat, varför all denna kontinuerliga integration?

Men jag har statistik: fel fångas i 20% av sammanställningarna. Och det beror inte på att våra utvecklare skriver dålig kod. Detta beror på att utvecklare är säkra på att om de gör något misstag, kommer det inte att utvecklas, det kommer att fångas upp av automatiserade kontroller. Följaktligen kan utvecklare lägga mer tid på att skriva kod och intressanta saker, snarare än att lokalt jaga och kontrollera något.

Gör kontinuerlig integration. Men med måtta.

Förresten, Nikolai Nesterov gör inte bara bra presentationer själv, utan är också medlem i programkommittén AppsConf och hjälpa andra att förbereda meningsfulla presentationer för dig. Fullständigheten och användbarheten av programmet för nästa konferens kan bedömas utifrån ämnen i schema. Och för detaljer, kom 22-23 april till Infospace.

Källa: will.com

Lägg en kommentar