Evolusjon av CI i det mobile utviklingsteamet

I dag utvikles de fleste programvareproduktene i team. Forutsetningene for vellykket teamutvikling kan representeres i form av et enkelt diagram.

Evolusjon av CI i det mobile utviklingsteamet

Når du har skrevet koden din, må du sørge for at den:

  1. Det fungerer.
  2. Det bryter ingenting, inkludert koden kollegene dine skrev.

Hvis begge betingelsene er oppfylt, er du på vei til suksess. For enkelt å sjekke disse forholdene og ikke avvike fra den lønnsomme veien, kom vi opp med Kontinuerlig integrasjon.

CI er en arbeidsflyt der du integrerer koden din i den generelle produktkoden så ofte som mulig. Og du integrerer ikke bare, men sjekker også hele tiden at alt fungerer. Siden du trenger å sjekke mye og ofte, er det verdt å tenke på automatisering. Du kan sjekke alt manuelt, men du bør ikke, og her er hvorfor.

  • Kjære folk. En time med arbeid for enhver programmerer er dyrere enn en times arbeid for en server.
  • Folk gjør feil. Derfor kan det oppstå situasjoner når tester ble kjørt på feil gren eller feil commit ble kompilert for testere.
  • Folk er late. Fra tid til annen, når jeg er ferdig med en oppgave, dukker tanken opp: «Hva er det å sjekke? Jeg skrev to linjer - alt fungerer! Jeg tror noen av dere også noen ganger har slike tanker. Men du bør alltid sjekke.

Hvordan Continuous Integration ble implementert og utviklet i Avitos mobile utviklingsteam, hvordan de gikk fra 0 til 450 bygg per dag, og at byggemaskiner monteres 200 timer om dagen, sier Nikolai Nesterov (nnesterov) er en deltaker i alle evolusjonære endringer av CI/CD Android-applikasjonen.

Historien er basert på eksemplet med en Android-kommando, men de fleste tilnærmingene kan også brukes på iOS.


Det var en gang en person som jobbet i Avito Android-teamet. Per definisjon trengte han ikke noe fra Continuous Integration: det var ingen å integrere med.

Men søknaden vokste, flere og flere nye oppgaver dukket opp, og teamet vokste deretter. På et tidspunkt er det på tide å mer formelt etablere en kodeintegrasjonsprosess. Det ble bestemt å bruke Git flow.

Evolusjon av CI i det mobile utviklingsteamet

Konseptet med Git-flyt er velkjent: et prosjekt har én felles utviklingsgren, og for hver ny funksjon kutter utviklere en egen gren, forplikter seg til den, pusher, og når de vil slå sammen koden sin til utviklingsgrenen, åpner du en pull forespørsel. For å dele kunnskap og diskutere tilnærminger, introduserte vi kodegjennomgang, det vil si at kolleger må sjekke og bekrefte hverandres kode.

sjekker

Å se kode med øynene er kult, men ikke nok. Derfor innføres automatiske kontroller.

  • Først og fremst sjekker vi ARK forsamling.
  • Mye Junit tester.
  • Vi vurderer kodedekning, siden vi kjører tester.

For å forstå hvordan disse sjekkene skal kjøres, la oss se på utviklingsprosessen i Avito.

Det kan representeres skjematisk slik:

  • En utvikler skriver kode på den bærbare datamaskinen sin. Du kan kjøre integrasjonssjekker her - enten med en commit-hook, eller bare kjøre sjekker i bakgrunnen.
  • Etter at utvikleren har presset koden, åpner han en pull-forespørsel. For at koden skal inkluderes i utviklingsgrenen, er det nødvendig å gå gjennom en kodegjennomgang og samle inn det nødvendige antallet bekreftelser. Du kan aktivere kontroller og bygg her: før alle bygg er vellykkede, kan ikke pull-forespørselen slås sammen.
  • Etter at pull-forespørselen er slått sammen og koden er inkludert i develop, kan du velge et passende tidspunkt: for eksempel om natten, når alle serverne er ledige, og kjøre så mange sjekker du vil.

Ingen likte å kjøre skanninger på den bærbare datamaskinen. Når en utvikler har fullført en funksjon, vil han raskt presse den og åpne en pull-forespørsel. Hvis det i dette øyeblikket lanseres noen lange sjekker, er dette ikke bare ikke veldig hyggelig, men bremser også utviklingen: mens den bærbare datamaskinen sjekker noe, er det umulig å jobbe normalt med det.

Vi likte veldig godt å kjøre sjekker om natten, fordi det er mye tid og servere, du kan streife rundt. Men, dessverre, når funksjonskoden begynner å utvikle seg, har utvikleren mye mindre motivasjon til å fikse feilene som CI fant. Jeg tok meg selv med jevne mellomrom og tenkte når jeg så på alle feilene som ble funnet i morgenrapporten at jeg ville fikse dem en dag senere, for nå er det en kul ny oppgave i Jira som jeg bare vil begynne å gjøre.

Hvis sjekker blokkerer en pull-forespørsel, er det nok motivasjon, for før byggene blir grønne, vil ikke koden komme i utvikling, noe som betyr at oppgaven ikke blir fullført.

Som et resultat valgte vi følgende strategi: vi kjører det maksimalt mulige settet med sjekker om natten, og starter de mest kritiske av dem og, viktigst av alt, de raskeste på en pull-forespørsel. Men vi stopper ikke der – parallelt optimaliserer vi hastigheten på sjekkene for å overføre dem fra nattmodus til å trekke forespørselssjekker.

På den tiden ble alle byggene våre fullført ganske raskt, så vi inkluderte ganske enkelt ARK-bygget, Junit-tester og kodedekningsberegninger som en blokkering for pull-forespørselen. Vi slo den på, tenkte på det og forlot kodedekningen fordi vi trodde at vi ikke trengte den.

Det tok oss to dager å fullstendig sette opp den grunnleggende CI (heretter er tidsestimatet omtrentlig, nødvendig for skala).

Etter det begynte vi å tenke videre – sjekker vi i det hele tatt riktig? Kjører vi builds på pull-forespørsler riktig?

Vi startet byggingen på den siste forpliktelsen til grenen som pull-forespørselen ble åpnet fra. Men tester av denne forpliktelsen kan bare vise at koden som utvikleren skrev fungerer. Men de beviser ikke at han ikke har ødelagt noe. Faktisk må du sjekke tilstanden til utviklingsgrenen etter at en funksjon er slått sammen i den.

Evolusjon av CI i det mobile utviklingsteamet

For å gjøre dette skrev vi et enkelt bash-skript premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Her er alle de siste endringene fra develop ganske enkelt trukket opp og slått sammen til den nåværende grenen. Vi la til premerge.sh-skriptet som det første trinnet i alle bygg og begynte å sjekke nøyaktig hva vi vil ha, dvs. integrering.

Det tok tre dager å lokalisere problemet, finne en løsning og skrive dette skriptet.

Applikasjonen utviklet seg, flere og flere oppgaver dukket opp, teamet vokste, og premerge.sh begynte noen ganger å svikte oss. Develop hadde motstridende endringer som brøt bygget.

Et eksempel på hvordan dette skjer:

Evolusjon av CI i det mobile utviklingsteamet

To utviklere begynner samtidig å jobbe med funksjon A og B. Utvikleren av funksjon A oppdager en ubrukt funksjon i prosjektet answer() og fjerner den, som en flink speider. Samtidig legger utvikleren av funksjon B et nytt kall til denne funksjonen i sin filial.

Utviklere fullfører arbeidet og åpner en pull-forespørsel samtidig. Byggene er lansert, premerge.sh sjekker begge pull-forespørslene angående siste utviklingstilstand - alle sjekker er grønne. Etter det blir pull-forespørselen til funksjon A slått sammen, pull-forespørselen til funksjon B blir slått sammen... Bom! Utvikle pauser fordi utviklingskoden inneholder et kall til en ikke-eksisterende funksjon.

Evolusjon av CI i det mobile utviklingsteamet

Når det ikke kommer til å utvikle seg, er det det lokal katastrofe. Hele teamet kan ikke samle inn noe og sende det inn for testing.

Det har seg slik at jeg oftest jobbet med infrastrukturoppgaver: analyser, nettverk, databaser. Det vil si at det var jeg som skrev de funksjonene og klassene som andre utviklere bruker. På grunn av dette befant jeg meg veldig ofte i lignende situasjoner. Jeg hadde til og med dette bildet hengende en stund.

Evolusjon av CI i det mobile utviklingsteamet

Siden dette ikke passet oss, begynte vi å utforske alternativer for hvordan vi kunne forhindre dette.

Hvordan ikke bryte utviklingen

Det første alternativet: gjenoppbygg alle pull-forespørsler når du oppdaterer develop. Hvis, i vårt eksempel, pull-forespørselen med funksjon A er den første som inkluderes i utvikling, vil pull-forespørselen til funksjon B bli gjenoppbygd, og følgelig vil sjekkene mislykkes på grunn av en kompileringsfeil.

For å forstå hvor lang tid dette vil ta, bør du vurdere et eksempel med to PR-er. Vi åpner to PR-er: to builds, to runs of checks. Etter at den første PR er slått sammen til utvikling, må den andre bygges om. Totalt krever to PR-er tre kontroller: 2 + 1 = 3.

I prinsippet er det greit. Men vi så på statistikken, og den typiske situasjonen i teamet vårt var 10 åpne PR-er, og da er antall kontroller summen av progresjonen: 10 + 9 +... + 1 = 55. Det vil si å akseptere 10 PRs, du må bygge om 55 ganger. Og dette er i en ideell situasjon, når alle sjekker passerer første gang, når ingen åpner en ekstra pull-forespørsel mens disse dusinene behandles.

Se for deg selv som en utvikler som må være den første til å klikke på «flett sammen»-knappen, for hvis en nabo gjør dette, må du vente til alle byggene går gjennom igjen... Nei, det vil ikke fungere , vil det for alvor bremse utviklingen.

Andre mulige måte: samle inn pull-forespørsler etter kodegjennomgang. Det vil si at du åpner en pull-forespørsel, samler inn nødvendig antall godkjenninger fra kollegaer, korrigerer det som trengs, og starter deretter byggene. Hvis de lykkes, blir pull-forespørselen slått sammen til develop. I dette tilfellet er det ingen ekstra omstarter, men tilbakemeldingen er sterkt bremset. Som utvikler, når jeg åpner en pull-forespørsel, vil jeg umiddelbart se om det kommer til å fungere. For eksempel, hvis en test mislykkes, må du raskt fikse den. Ved forsinket bygg bremser tilbakemeldingen, og dermed hele utviklingen. Dette passet ikke oss heller.

Som et resultat gjensto bare det tredje alternativet - sykkel. All vår kode, alle våre kilder er lagret i et depot på Bitbucket-serveren. Derfor måtte vi utvikle en plugin for Bitbucket.

Evolusjon av CI i det mobile utviklingsteamet

Denne plugin-en overstyrer sammenslåingsmekanismen for pull-forespørsel. Begynnelsen er standard: PR-en åpnes, alle sammenstillinger lanseres, kodegjennomgangen er fullført. Men etter at kodegjennomgangen er fullført og utvikleren bestemmer seg for å klikke på "slå sammen", sjekker plugin-modulen mot hvilken utviklingstilstand sjekkene ble kjørt. Hvis utviklingen har blitt oppdatert etter byggingene, vil ikke plugin tillate at en slik pull-forespørsel flettes inn i hovedgrenen. Det vil ganske enkelt starte byggene til en relativt nylig utvikling på nytt.

Evolusjon av CI i det mobile utviklingsteamet

I vårt eksempel med motstridende endringer, vil slike bygg mislykkes på grunn av en kompileringsfeil. Følgelig må utvikleren av funksjon B korrigere koden, starte sjekkene på nytt, så vil plugin-en automatisk bruke pull-forespørselen.

Før vi implementerte denne plugin-en, hadde vi i gjennomsnitt 2,7 gjennomganger per pull-forespørsel. Med plugin var det 3,6 lanseringer. Dette passet oss.

Det er verdt å merke seg at denne plugin-en har en ulempe: den starter bare bygget på nytt én gang. Det vil si at det fortsatt er et lite vindu som motstridende endringer kan utvikle seg gjennom. Men sannsynligheten for dette er lav, og vi gjorde denne avveiningen mellom antall starter og sannsynligheten for feil. På to år skjøt det bare en gang, så det var nok ikke forgjeves.

Det tok oss to uker å skrive den første versjonen av Bitbucket-plugin.

Nye sjekker

I mellomtiden fortsatte teamet vårt å vokse. Nye sjekker er lagt til.

Vi tenkte: hvorfor gjøre feil hvis de kan forebygges? Og det var derfor de implementerte statisk kodeanalyse. Vi startet med lo, som er inkludert i Android SDK. Men på det tidspunktet visste han ikke hvordan han skulle jobbe med Kotlin-kode i det hele tatt, og vi hadde allerede 75 % av søknaden skrevet i Kotlin. Derfor ble innebygde lagt til lo Android Studio sjekker.

For å gjøre dette, måtte vi gjøre mye pervertering: ta Android Studio, pakke det i Docker og kjør det på CI med en virtuell skjerm, slik at den tror den kjører på en ekte bærbar datamaskin. Men det fungerte.

Det var også i denne tiden vi begynte å skrive mye instrumenteringstester og implementert testing av skjermbilder. Dette er når et referanseskjermbilde genereres for en egen liten visning, og testen består i å ta et skjermbilde fra visningen og sammenligne det med standarden direkte piksel for piksel. Hvis det er et avvik, betyr det at oppsettet har gått feil et sted eller at det er noe galt i stilene.

Men instrumenteringstester og skjermbildetester må kjøres på enheter: på emulatorer eller på ekte enheter. Med tanke på at det er mange tester og de kjøres ofte, trengs en hel gård. Å starte egen gård er for arbeidskrevende, så vi fant et ferdig alternativ - Firebase Test Lab.

Firebase Test Lab

Det ble valgt fordi Firebase er et Google-produkt, noe som betyr at det skal være pålitelig og usannsynlig å dø. Prisene er rimelige: $ 5 per driftstime for en ekte enhet, 1 $ per time drift av en emulator.

Det tok omtrent tre uker å implementere Firebase Test Lab i vår CI.

Men teamet fortsatte å vokse, og Firebase begynte dessverre å svikte oss. På det tidspunktet hadde han ingen SLA. Noen ganger fikk Firebase oss til å vente til det nødvendige antallet enheter var ledige for tester, og begynte ikke å utføre dem umiddelbart, slik vi ønsket. Å vente i kø tok opptil en halvtime, noe som er veldig lang tid. Instrumenteringstester ble kjørt på hver PR, forsinkelser bremset virkelig utviklingen, og så kom månedsregningen med en rund sum. Generelt ble det besluttet å forlate Firebase og jobbe internt, siden teamet hadde vokst nok.

Docker + Python + bash

Vi tok Docker, stappet emulatorer inn i den, skrev et enkelt program i Python, som i rett øyeblikk henter opp det nødvendige antallet emulatorer i den nødvendige versjonen og stopper dem når det er nødvendig. Og selvfølgelig et par bash-manus - hvor ville vi vært uten dem?

Det tok fem uker å lage vårt eget testmiljø.

Som et resultat, for hver pull-forespørsel var det en omfattende sammenslåingsblokkerende liste over sjekker:

  • ARK montering;
  • Junit tester;
  • lo;
  • Android Studio sjekker;
  • Instrumentering tester;
  • Skjermbildetester.

Dette forhindret mange mulige sammenbrudd. Teknisk fungerte alt, men utviklerne klaget over at ventetiden på resultater var for lang.

Hvor lang er for lang? Vi lastet opp data fra Bitbucket og TeamCity til analysesystemet og innså det gjennomsnittlig ventetid 45 minutter. Det vil si at en utvikler, når han åpner en pull-forespørsel, venter i gjennomsnitt 45 minutter på byggeresultatene. Etter min mening er dette mye, og du kan ikke jobbe slik.

Selvfølgelig bestemte vi oss for å øke hastigheten på alle byggene våre.

La oss øke hastigheten

Ser at bygg ofte står i kø, det første vi gjør er kjøpte mer maskinvare — omfattende utbygging er det enkleste. Bygg sluttet å stå i kø, men ventetiden gikk bare litt ned, fordi enkelte kontroller tok veldig lang tid.

Fjerne sjekker som tar for lang tid

Vår kontinuerlige integrasjon kan fange opp denne typen feil og problemer.

  • Kommer ikke til. CI kan fange opp en kompileringsfeil når noe ikke bygges på grunn av motstridende endringer. Som jeg allerede sa, da kan ingen sette sammen noe, utviklingen stopper opp, og alle blir nervøse.
  • Feil i oppførsel. For eksempel når applikasjonen er bygget, men krasjer når du trykker på en knapp, eller knappen ikke trykkes i det hele tatt. Dette er dårlig fordi en slik feil kan nå brukeren.
  • Feil i layout. For eksempel er en knapp klikket, men har flyttet 10 piksler til venstre.
  • Økning i teknisk gjeld.

Etter å ha sett på denne listen, innså vi at bare de to første punktene er kritiske. Vi ønsker å fange opp slike problemer først. Feil i oppsettet oppdages på design-revisjonsstadiet og kan lett rettes opp da. Håndtering av teknisk gjeld krever en egen prosess og planlegging, så vi bestemte oss for å ikke teste det på en pull-forespørsel.

Basert på denne klassifiseringen ristet vi opp hele listen over sjekker. Strøket ut Lo og utsatte lanseringen over natten: bare slik at den skulle produsere en rapport om hvor mange problemer det var i prosjektet. Vi ble enige om å jobbe separat med teknisk gjeld, og Android Studio-sjekker ble fullstendig forlatt. Android Studio i Docker for å kjøre inspeksjoner høres interessant ut, men forårsaker mye problemer med støtte. Enhver oppdatering til Android Studio-versjoner betyr en kamp med uforståelige feil. Det var også vanskelig å støtte skjermbildetester, fordi biblioteket ikke var veldig stabilt og det var falske positiver. Skjermbildetester er fjernet fra sjekklisten.

Som et resultat satt vi igjen med:

  • ARK montering;
  • Junit tester;
  • Instrumenteringstester.

Gradle ekstern cache

Uten tunge sjekker ble alt bedre. Men det er ingen grense for perfeksjon!

Vår søknad var allerede delt inn i rundt 150 gradle-moduler. Gradle ekstern cache fungerer vanligvis bra i dette tilfellet, så vi bestemte oss for å prøve det.

Gradle remote cache er en tjeneste som kan cache bygge artefakter for individuelle oppgaver i individuelle moduler. Gradle, i stedet for å faktisk kompilere koden, bruker HTTP til å banke på den eksterne cachen og spørre om noen allerede har utført denne oppgaven. Hvis ja, laster den bare ned resultatet.

Det er enkelt å kjøre Gradle ekstern cache fordi Gradle gir et Docker-bilde. Vi klarte dette på tre timer.

Alt du måtte gjøre var å starte Docker og skrive én linje i prosjektet. Men selv om det kan lanseres raskt, vil det ta ganske lang tid før alt fungerer bra.

Nedenfor er grafen for cache-misser.

Evolusjon av CI i det mobile utviklingsteamet

Helt i begynnelsen var prosentandelen cache-misser omtrent 65. Etter tre uker klarte vi å øke denne verdien til 20 %. Det viste seg at oppgavene som Android-applikasjonen samler inn har merkelige transitive avhengigheter, på grunn av hvilke Gradle savnet cachen.

Ved å koble til hurtigbufferen satte vi kraftig fart på byggingen. Men i tillegg til montering er det også instrumenteringstester, og de tar lang tid. Kanskje ikke alle tester må kjøres for hver pull-forespørsel. For å finne ut av det bruker vi konsekvensanalyse.

Konsekvensanalyse

På en pull-forespørsel samler vi inn git diff og finner de modifiserte Gradle-modulene.

Evolusjon av CI i det mobile utviklingsteamet

Det er fornuftig å kun kjøre instrumenteringstester som sjekker de endrede modulene og alle moduler som er avhengige av dem. Det er ingen vits i å kjøre tester for nabomoduler: koden der har ikke endret seg og ingenting kan gå i stykker.

Instrumenteringstester er ikke så enkle, fordi de må være plassert i applikasjonsmodulen på toppnivå. Vi brukte heuristikk med bytekodeanalyse for å forstå hvilken modul hver test tilhører.

Å oppgradere driften av instrumenteringstestene slik at de kun tester de involverte modulene tok rundt åtte uker.

Tiltak for å fremskynde inspeksjoner har fungert vellykket. Fra 45 minutter gikk vi opp til ca 15. Det er allerede normalt å vente et kvarter på å bygge.

Men nå har utviklere begynt å klage på at de ikke forstår hvilke bygg som lanseres, hvor man kan se loggen, hvorfor bygget er rødt, hvilken test som mislyktes osv.

Evolusjon av CI i det mobile utviklingsteamet

Problemer med tilbakemelding bremser utviklingen, så vi prøvde å gi så tydelig og detaljert informasjon om hver PR og bygg som mulig. Vi startet med kommentarer i Bitbucket til PR, som indikerte hvilken build som hadde mislyktes og hvorfor, og skrev målrettede meldinger i Slack. Til slutt opprettet vi et PR-dashbord for siden med en liste over alle bygg som kjører for øyeblikket og statusen deres: i kø, kjører, krasjet eller fullført. Du kan klikke på bygget og komme til loggen.

Evolusjon av CI i det mobile utviklingsteamet

Seks uker ble brukt på detaljerte tilbakemeldinger.

Planer

La oss gå videre til nyere historie. Etter å ha løst tilbakemeldingsproblemet, nådde vi et nytt nivå - vi bestemte oss for å bygge vår egen emulatorfarm. Når det er mange tester og emulatorer, er de vanskelige å administrere. Som et resultat flyttet alle emulatorene våre til k8s-klyngen med fleksibel ressursstyring.

I tillegg er det andre planer.

  • Returner Lint (og annen statisk analyse). Vi jobber allerede i denne retningen.
  • Kjør alt på en PR-blokker ende-til-ende tester på alle SDK-versjoner.

Så vi har sporet historien til utviklingen av kontinuerlig integrasjon i Avito. Nå vil jeg gi noen råd fra en erfaren synsvinkel.

Советы

Hvis jeg bare kunne gi ett råd ville det vært dette:

Vær forsiktig med shell-skript!

Bash er et veldig fleksibelt og kraftig verktøy, det er veldig praktisk og raskt å skrive manus. Men du kan gå i en felle med den, og dessverre gikk vi i den.

Det hele startet med enkle skript som kjørte på byggemaskinene våre:

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

Men som du vet, alt utvikler seg og blir mer komplisert over tid - la oss kjøre ett skript fra et annet, la oss sende noen parametere der - til slutt måtte vi skrive en funksjon som bestemmer på hvilket nivå av bash-hekking vi er nå i orden å sette inn de nødvendige sitatene, for å få det hele i gang.

Evolusjon av CI i det mobile utviklingsteamet

Du kan forestille deg arbeidskostnadene for utviklingen av slike skript. Jeg råder deg til ikke å gå i denne fellen.

Hva kan erstattes?

  • Ethvert skriptspråk. Skrive til Python- eller Kotlin-skript mer praktisk fordi det er programmering, ikke skript.
  • Eller beskriv all byggelogikken i skjemaet Tilpassede graderte oppgaver for prosjektet ditt.

Vi bestemte oss for å velge det andre alternativet, og nå sletter vi systematisk alle bash-skript og skriver mange tilpassede gradle-oppgaver.

Tips #2: Lagre infrastruktur i kode.

Det er praktisk når Continuous Integration-innstillingen ikke er lagret i UI-grensesnittet til Jenkins eller TeamCity, etc., men i form av tekstfiler direkte i prosjektlageret. Dette gir versjonerbarhet. Det vil ikke være vanskelig å rulle tilbake eller bygge koden på en annen gren.

Skript kan lagres i et prosjekt. Hva skal man gjøre med miljøet?

Tips #3: Docker kan hjelpe med miljøet.

Det vil definitivt hjelpe Android-utviklere; iOS har ikke en ennå, dessverre.

Dette er et eksempel på en enkel docker-fil som inneholder jdk og 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

Etter å ha skrevet denne Docker-filen (jeg skal fortelle deg en hemmelighet, du trenger ikke å skrive den, men bare dra den ferdig fra GitHub) og satt sammen bildet, får du en virtuell maskin som du kan bygge applikasjonen på og kjøre Junit-tester.

De to hovedgrunnene til at dette gir mening er skalerbarhet og repeterbarhet. Ved å bruke docker kan du raskt samle et dusin byggeagenter som vil ha nøyaktig samme miljø som den forrige. Dette gjør livet til CI-ingeniører mye enklere. Det er ganske enkelt å skyve android-sdk inn i docker, men med emulatorer er det litt vanskeligere: du må jobbe litt hardere (eller laste ned den ferdige fra GitHub igjen).

Tips nr. 4: ikke glem at inspeksjoner ikke gjøres for tilsyns skyld, men for mennesker.

Rask og, viktigst av alt, tydelig tilbakemelding er veldig viktig for utviklere: hva gikk i stykker, hvilken test mislyktes, hvor kan jeg se byggeloggen.

Tips #5: Vær pragmatisk når du utvikler kontinuerlig integrasjon.

Forstå tydelig hvilke typer feil du vil forhindre, hvor mye ressurser, tid og datamaskintid du er villig til å bruke. Kontroller som tar for lang tid kan for eksempel utsettes over natten. Og de av dem som fanger ikke veldig viktige feil, bør helt forlates.

Tips #6: Bruk ferdige verktøy.

Det er mange selskaper nå som tilbyr sky-CI.

Evolusjon av CI i det mobile utviklingsteamet

Dette er en god løsning for små team. Du trenger ikke støtte noe, bare betale litt penger, bygge applikasjonen din og til og med kjøre instrumenteringstester.

Tips #7: I et stort team er interne løsninger mer lønnsomme.

Men før eller siden, ettersom teamet vokser, vil interne løsninger bli mer lønnsomme. Det er ett problem med disse avgjørelsene. Det er en lov om avtagende avkastning i økonomi: i ethvert prosjekt er hver påfølgende forbedring mer og mer vanskelig og krever mer og mer investering.

Økonomi beskriver hele livet vårt, inkludert kontinuerlig integrasjon. Jeg bygde en tidsplan for lønnskostnader for hvert trinn i utviklingen av vår kontinuerlige integrasjon.

Evolusjon av CI i det mobile utviklingsteamet

Det er tydelig at enhver forbedring blir vanskeligere og vanskeligere. Når du ser på denne grafen, kan du forstå at kontinuerlig integrasjon må utvikles i samsvar med veksten i teamstørrelsen. For et team på to personer er det en middelmådig idé å bruke 50 dager på å utvikle en intern emulatorfarm. Men på samme tid, for et stort team, er det å ikke gjøre kontinuerlig integrasjon i det hele tatt også en dårlig idé, fordi integreringsproblemer, fikse kommunikasjon osv. det vil ta enda mer tid.

Vi startet med tanken om at automatisering er nødvendig fordi folk er dyre, de gjør feil og er late. Men folk automatiserer også. Derfor gjelder alle de samme problemene for automatisering.

  • Automatisering er dyrt. Husk arbeidsplanen.
  • Når det kommer til automatisering, gjør folk feil.
  • Noen ganger er det veldig lat å automatisere, fordi alt fungerer på den måten. Hvorfor forbedre noe annet, hvorfor all denne kontinuerlige integrasjonen?

Men jeg har statistikk: feil fanges opp i 20% av samlingene. Og dette er ikke fordi utviklerne våre skriver kode dårlig. Dette er fordi utviklere er sikre på at hvis de gjør en feil, vil den ikke ende opp i utviklingen, den vil bli fanget opp av automatiserte kontroller. Følgelig kan utviklere bruke mer tid på å skrive kode og interessante ting, i stedet for å kjøre og teste noe lokalt.

Øv på kontinuerlig integrasjon. Men med måte.

Nikolai Nesterov gir forresten ikke bare flotte reportasjer selv, men er også medlem av programkomiteen AppsConf og hjelper andre med å forberede meningsfulle taler for deg. Fullstendigheten og nytten av neste konferanseprogram kan vurderes etter emner i rute. Og for detaljer, kom til Infospace 22.-23. april.

Kilde: www.habr.com

Legg til en kommentar