Evolutie van CI in het mobiele ontwikkelingsteam

Tegenwoordig worden de meeste softwareproducten in teams ontwikkeld. De voorwaarden voor succesvolle teamontwikkeling kunnen worden weergegeven in de vorm van een eenvoudig diagram.

Evolutie van CI in het mobiele ontwikkelingsteam

Nadat u uw code heeft geschreven, moet u ervoor zorgen dat deze:

  1. Работает.
  2. Er wordt niets kapot gemaakt, ook niet de code die uw collega's hebben geschreven.

Als aan beide voorwaarden is voldaan, bent u op weg naar succes. Om deze voorwaarden eenvoudig te controleren en niet af te wijken van het winstgevende pad, hebben we Continuous Integration bedacht.

CI is een workflow waarbij u uw code zo vaak mogelijk in de algehele productcode integreert. En je integreert niet alleen, maar checkt ook voortdurend of alles werkt. Omdat je veel en vaak moet controleren, is het de moeite waard om na te denken over automatisering. Je kunt alles handmatig controleren, maar dat zou niet moeten, en hier is waarom.

  • beste mensen. Een uur werk van welke programmeur dan ook is duurder dan een uur werk van welke server dan ook.
  • Mensen maken fouten. Daarom kunnen er situaties ontstaan ​​waarin tests op de verkeerde branch zijn uitgevoerd of de verkeerde commit is samengesteld voor testers.
  • Mensen zijn lui. Als ik een taak afrond, komt er af en toe de gedachte op: “Wat valt er te controleren? Ik heb twee regels geschreven - alles werkt! Ik denk dat sommigen van jullie ook wel eens zulke gedachten hebben. Maar je moet het altijd controleren.

Hoe continue integratie werd geïmplementeerd en ontwikkeld in het mobiele ontwikkelingsteam van Avito, hoe ze van 0 naar 450 builds per dag gingen, en hoe machines 200 uur per dag in elkaar werden gezet, zegt Nikolai Nesterov (nnesterov) neemt deel aan alle evolutionaire veranderingen van de CI/CD Android-applicatie.

Het verhaal is gebaseerd op het voorbeeld van een Android-opdracht, maar de meeste benaderingen zijn ook toepasbaar op iOS.


Er was eens één persoon in het Avito Android-team. Per definitie had hij niets nodig van Continuous Integration: er was niemand om mee te integreren.

Maar de applicatie groeide, er verschenen steeds meer nieuwe taken en het team groeide mee. Op een gegeven moment is het tijd om een ​​code-integratieproces formeler op te zetten. Er werd besloten om Git flow te gebruiken.

Evolutie van CI in het mobiele ontwikkelingsteam

Het concept van Git flow is bekend: een project heeft één gemeenschappelijke ontwikkelbranch, en voor elke nieuwe functie knippen ontwikkelaars een aparte branch, committeren zich eraan, pushen en wanneer ze hun code willen samenvoegen in de ontwikkelbranch, openen ze een trek verzoek. Om kennis te delen en benaderingen te bespreken, hebben we code review geïntroduceerd, dat wil zeggen dat collega’s elkaars code moeten controleren en bevestigen.

checks

Code met je ogen zien is cool, maar niet genoeg. Daarom worden er automatische controles ingevoerd.

  • Allereerst controleren wij ARK-montage.
  • Veel Junit-testen.
  • We houden rekening met codedekking, aangezien we tests uitvoeren.

Laten we, om te begrijpen hoe deze controles moeten worden uitgevoerd, eens kijken naar het ontwikkelingsproces in Avito.

Het kan schematisch als volgt worden weergegeven:

  • Een ontwikkelaar schrijft code op zijn laptop. U kunt hier integratiecontroles uitvoeren - met een commit hook, of eenvoudigweg controles op de achtergrond uitvoeren.
  • Nadat de ontwikkelaar de code heeft gepusht, opent hij een pull-request. Om de code in de ontwikkeltak te kunnen opnemen, is het noodzakelijk om een ​​codebeoordeling te doorlopen en het vereiste aantal bevestigingen te verzamelen. U kunt hier controles en builds inschakelen: totdat alle builds succesvol zijn, kan het pull-verzoek niet worden samengevoegd.
  • Nadat het pull-verzoek is samengevoegd en de code is opgenomen in de ontwikkeling, kunt u een geschikt tijdstip kiezen: bijvoorbeeld 's nachts, wanneer alle servers vrij zijn, en zoveel controles uitvoeren als u wilt.

Niemand vond het leuk om scans op hun laptop uit te voeren. Wanneer een ontwikkelaar een feature af heeft, wil hij deze snel pushen en een pull request openen. Als er op dit moment een aantal lange controles worden uitgevoerd, is dat niet alleen niet erg prettig, maar vertraagt ​​het ook de ontwikkeling: terwijl de laptop iets controleert, is het onmogelijk om er normaal op te werken.

We vonden het erg leuk om 's nachts controles uit te voeren, omdat er veel tijd en servers zijn, je kunt ronddwalen. Maar helaas, wanneer de featurecode in ontwikkeling komt, heeft de ontwikkelaar veel minder motivatie om de fouten op te lossen die CI heeft gevonden. Ik betrapte mezelf er af en toe op dat ik, toen ik naar alle fouten in het ochtendrapport keek, dacht dat ik ze op een dag later zou herstellen, omdat er nu een coole nieuwe taak in Jira is waar ik gewoon mee wil beginnen.

Als controles een pull-verzoek blokkeren, is er voldoende motivatie, want totdat de builds groen worden, zal de code niet in ontwikkeling komen, wat betekent dat de taak niet zal worden voltooid.

Als gevolg hiervan hebben we voor de volgende strategie gekozen: we voeren 's nachts het maximale aantal controles uit en lanceren de meest kritische en vooral de snelste op basis van een pull-request. Maar daar stopt het niet. Tegelijkertijd optimaliseren we de snelheid van de controles, zodat ze van de nachtmodus overgaan naar controles met pull-requests.

Op dat moment waren al onze builds vrij snel voltooid, dus hebben we eenvoudigweg de ARK-build, Junit-tests en codedekkingsberekeningen toegevoegd als blokkering voor de pull-aanvraag. We hebben het aangezet, erover nagedacht en de codedekking opgegeven omdat we dachten dat we het niet nodig hadden.

Het kostte ons twee dagen om het basis-CI volledig in te stellen (hierna is de geschatte tijd een schatting, nodig voor schaal).

Daarna begonnen we verder na te denken: controleren we het wel correct? Voeren we builds op pull-aanvragen correct uit?

We zijn begonnen met het bouwen van de laatste commit van de branch van waaruit de pull-aanvraag werd geopend. Maar tests van deze commit kunnen alleen aantonen dat de code die de ontwikkelaar heeft geschreven werkt. Maar ze bewijzen niet dat hij niets heeft gebroken. In feite moet je de status van de ontwikkelbranch controleren nadat een feature erin is samengevoegd.

Evolutie van CI in het mobiele ontwikkelingsteam

Om dit te doen, hebben we een eenvoudig bash-script geschreven premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Hier worden alle laatste wijzigingen van de ontwikkeling eenvoudigweg opgehaald en samengevoegd in de huidige vertakking. We hebben het premerge.sh-script toegevoegd als de eerste stap in alle builds en zijn begonnen met het controleren van precies wat we willen integratie.

Het duurde drie dagen om het probleem te lokaliseren, een oplossing te vinden en dit script te schrijven.

De applicatie ontwikkelde zich, er verschenen steeds meer taken, het team groeide en premerge.sh begon ons soms in de steek te laten. Develop had tegenstrijdige veranderingen die de build kapotmaakten.

Een voorbeeld van hoe dit gebeurt:

Evolutie van CI in het mobiele ontwikkelingsteam

Twee ontwikkelaars beginnen tegelijkertijd aan features A en B te werken. De ontwikkelaar van feature A ontdekt een ongebruikte feature in het project answer() en verwijdert het, net als een goede padvinder. Tegelijkertijd voegt de ontwikkelaar van feature B een nieuwe aanroep toe aan deze functie in zijn branch.

Ontwikkelaars voltooien hun werk en openen tegelijkertijd een pull-request. De builds worden gelanceerd, premerge.sh controleert beide pull-aanvragen met betrekking tot de nieuwste ontwikkelingsstatus - alle controles zijn groen. Daarna wordt het pull-verzoek van feature A samengevoegd, het pull-verzoek van feature B wordt samengevoegd... Boem! Ontwikkelonderbrekingen omdat de ontwikkelcode een aanroep naar een niet-bestaande functie bevat.

Evolutie van CI in het mobiele ontwikkelingsteam

Als het zich niet gaat ontwikkelen, dan wel plaatselijke ramp. Het hele team kan niets verzamelen en ter test indienen.

Het gebeurde zo dat ik het vaakst werkte aan infrastructuurtaken: analyses, netwerken, databases. Dat wil zeggen, ik was het die die functies en klassen schreef die andere ontwikkelaars gebruiken. Hierdoor kwam ik heel vaak in soortgelijke situaties terecht. Ik heb deze foto zelfs een tijdje laten hangen.

Evolutie van CI in het mobiele ontwikkelingsteam

Omdat dit ons niet beviel, zijn we gaan onderzoeken hoe we dit kunnen voorkomen.

Hoe je de ontwikkeling niet moet breken

De eerste optie: bouw alle pull-aanvragen opnieuw op bij het updaten van Develop. Als in ons voorbeeld het pull-verzoek met feature A als eerste wordt opgenomen in de ontwikkeling, zal het pull-verzoek van feature B opnieuw worden opgebouwd, en dienovereenkomstig zullen de controles mislukken vanwege een compilatiefout.

Om te begrijpen hoe lang dit zal duren, overweeg een voorbeeld met twee PR's. We openen twee PR's: twee builds, twee controles. Nadat de eerste PR is samengevoegd in ontwikkeling, moet de tweede opnieuw worden opgebouwd. In totaal vereisen twee PR's drie controles: 2 + 1 = 3.

In principe is het prima. Maar we keken naar de statistieken, en de typische situatie in ons team was 10 open PR's, en dan is het aantal controles de som van de progressie: 10 + 9 +... + 1 = 55. Dat wil zeggen, om 10 te accepteren PR's, je moet 55 keer herbouwen. En dit is in een ideale situatie, wanneer alle controles de eerste keer slagen, wanneer niemand een extra pull-verzoek opent terwijl deze tientallen worden verwerkt.

Stel je voor dat je als ontwikkelaar als eerste op de knop “samenvoegen” moet klikken, want als een buurman dit doet, dan zul je moeten wachten tot alle builds weer doorlopen zijn... Nee, dat gaat niet werken zal het de ontwikkeling ernstig vertragen.

Tweede mogelijke manier: verzamel pull-aanvragen na codebeoordeling. Dat wil zeggen dat u een pull-request opent, het vereiste aantal goedkeuringen van collega's verzamelt, corrigeert wat nodig is en vervolgens de builds lanceert. Als ze succesvol zijn, wordt het pull-verzoek samengevoegd met Develop. In dit geval zijn er geen extra herstarts, maar wordt de feedback aanzienlijk vertraagd. Als ik als ontwikkelaar een pull request open, wil ik meteen kijken of het gaat werken. Als een test bijvoorbeeld mislukt, moet je deze snel repareren. Bij een vertraagde build vertraagt ​​de feedback en daarmee de hele ontwikkeling. Dit beviel ons ook niet.

Als gevolg hiervan bleef alleen de derde optie over: fiets. Al onze code, al onze bronnen worden opgeslagen in een repository op de Bitbucket-server. Daarom moesten we een plug-in voor Bitbucket ontwikkelen.

Evolutie van CI in het mobiele ontwikkelingsteam

Deze plug-in overschrijft het samenvoegingsmechanisme van pull-aanvragen. Het begin is standaard: de PR gaat open, alle assemblages worden gelanceerd, de codebeoordeling is voltooid. Maar nadat de codebeoordeling is voltooid en de ontwikkelaar besluit op ‘samenvoegen’ te klikken, controleert de plug-in op welke ontwikkelingsstatus de controles zijn uitgevoerd. Als Develop na de builds is bijgewerkt, staat de plug-in niet toe dat een dergelijk pull-verzoek wordt samengevoegd in de hoofdvertakking. Het zal eenvoudigweg de builds van een relatief recente ontwikkeling opnieuw starten.

Evolutie van CI in het mobiele ontwikkelingsteam

In ons voorbeeld met conflicterende wijzigingen zullen dergelijke builds mislukken vanwege een compilatiefout. Dienovereenkomstig zal de ontwikkelaar van functie B de code moeten corrigeren, de controles opnieuw moeten starten, waarna de plug-in automatisch het pull-verzoek zal toepassen.

Voordat we deze plug-in implementeerden, hadden we gemiddeld 2,7 beoordelingsruns per pull-verzoek. Met de plug-in waren er 3,6 lanceringen. Dit beviel ons.

Het is vermeldenswaard dat deze plug-in een nadeel heeft: hij herstart de build slechts één keer. Dat wil zeggen dat er nog steeds een klein venster is waarbinnen conflicterende veranderingen zich kunnen ontwikkelen. Maar de kans hierop is klein en we hebben een afweging gemaakt tussen het aantal starts en de kans op mislukking. In twee jaar tijd heeft hij slechts één keer geschoten, dus waarschijnlijk niet voor niets.

Het kostte ons twee weken om de eerste versie van de Bitbucket-plug-in te schrijven.

Nieuwe cheques

Ondertussen bleef ons team groeien. Er zijn nieuwe cheques toegevoegd.

Wij dachten: waarom fouten maken als ze voorkomen kunnen worden? En daarom hebben ze het geïmplementeerd statische codeanalyse. We zijn begonnen met lint, dat is opgenomen in de Android SDK. Maar op dat moment wist hij helemaal niet hoe hij met Kotlin-code moest werken, en we hadden al 75% van de applicatie in Kotlin geschreven. Daarom werden ingebouwde pluisjes toegevoegd Android Studio-controles.

Om dit te doen moesten we veel perverteren: we namen Android Studio, verpakten het in Docker en draaiden het op CI met een virtuele monitor, zodat het denkt dat het op een echte laptop draait. Maar het werkte.

Het was ook in deze tijd dat we veel begonnen te schrijven instrumentatie testen en geïmplementeerd screenshot testen. Dit is wanneer een referentie-screenshot wordt gegenereerd voor een afzonderlijke kleine weergave, en de test bestaat uit het nemen van een screenshot van de weergave en deze direct pixel voor pixel vergelijken met de standaard. Als er een discrepantie is, betekent dit dat de lay-out ergens fout is gegaan of dat er iets mis is in de stijlen.

Maar instrumentatietests en screenshot-tests moeten op apparaten worden uitgevoerd: op emulators of op echte apparaten. Aangezien er veel tests zijn en deze regelmatig worden uitgevoerd, is een heel landbouwbedrijf nodig. Het starten van een eigen boerderij is te arbeidsintensief, dus hebben we een kant-en-klare optie gevonden: Firebase Test Lab.

Firebase-testlab

Er is voor gekozen omdat Firebase een Google-product is, wat betekent dat het betrouwbaar moet zijn en waarschijnlijk nooit zal sterven. De prijzen zijn redelijk: $ 5 per werkingsuur van een echt apparaat, 1 $ per werkingsuur van een emulator.

Het duurde ongeveer drie weken om Firebase Test Lab in ons CI te implementeren.

Maar het team bleef groeien en Firebase begon ons helaas in de steek te laten. Op dat moment had hij geen SLA. Soms liet Firebase ons wachten tot het vereiste aantal apparaten vrij was voor tests, en begon deze niet meteen uit te voeren, zoals we wilden. Wachten in de rij duurde maximaal een half uur, wat erg lang is. Bij elke PR werden instrumentatietests uitgevoerd, vertragingen vertraagden de ontwikkeling enorm, en vervolgens kwam de maandelijkse rekening met een rond bedrag. Over het algemeen werd besloten Firebase te verlaten en intern te gaan werken, omdat het team voldoende was gegroeid.

Docker + Python + bash

We namen Docker, stopten er emulators in, schreven een eenvoudig programma in Python, dat op het juiste moment het benodigde aantal emulators in de juiste versie start en stopt wanneer dat nodig is. En natuurlijk een paar bash-scripts - waar zouden we zijn zonder hen?

Het duurde vijf weken om onze eigen testomgeving te creëren.

Als gevolg hiervan was er voor elke pull-aanvraag een uitgebreide samenvoeg-blokkeerlijst met controles:

  • ARK-montage;
  • Junit-testen;
  • Pluisjes;
  • Android Studio-controles;
  • Instrumentatietests;
  • Screenshot-tests.

Dit heeft veel mogelijke storingen voorkomen. Technisch werkte alles, maar de ontwikkelaars klaagden dat het wachten op resultaten te lang duurde.

Hoe lang is te lang? We hebben data van Bitbucket en TeamCity geüpload naar het analysesysteem en dat hebben we gerealiseerd gemiddelde wachttijd 45 minuten. Dat wil zeggen dat een ontwikkelaar bij het openen van een pull-verzoek gemiddeld 45 minuten wacht op de build-resultaten. Naar mijn mening is dit veel, en zo kun je niet werken.

Natuurlijk hebben we besloten om al onze builds te versnellen.

Laten we versnellen

Omdat builds vaak in de rij staan, is het eerste wat we doen: meer hardware gekocht — uitgebreide ontwikkeling is het eenvoudigst. Er stonden geen wachtrijen meer voor builds, maar de wachttijd nam slechts licht af, omdat sommige controles zelf erg lang duurden.

Het verwijderen van cheques die te lang duren

Onze Continuous Integration kan dit soort fouten en problemen opvangen.

  • Ik ga het niet doen. CI kan een compilatiefout opvangen wanneer iets niet wordt opgebouwd vanwege conflicterende wijzigingen. Zoals ik al zei, kan niemand iets in elkaar zetten, stopt de ontwikkeling en wordt iedereen nerveus.
  • Fout in gedrag. Bijvoorbeeld als de applicatie wel is gebouwd, maar crasht als je op een knop drukt, of als de knop helemaal niet wordt ingedrukt. Dit is slecht omdat een dergelijke bug de gebruiker kan bereiken.
  • Fout in de lay-out. Er is bijvoorbeeld op een knop geklikt, maar deze is 10 pixels naar links verschoven.
  • Toename van de technische schulden.

Nadat we deze lijst hadden bekeken, realiseerden we ons dat alleen de eerste twee punten van cruciaal belang zijn. Dergelijke problemen willen wij eerst aanpakken. Fouten in de lay-out worden ontdekt tijdens de ontwerpbeoordelingsfase en kunnen vervolgens eenvoudig worden gecorrigeerd. Het omgaan met technische schulden vereist een apart proces en aparte planning, dus hebben we besloten om het niet te testen op basis van een pull-request.

Op basis van deze classificatie hebben we de hele lijst met controles door elkaar geschud. Lint doorgestreept en stelde de lancering van de ene op de andere dag uit: alleen maar zodat het een rapport zou kunnen produceren over hoeveel problemen er in het project waren. We hebben afgesproken om afzonderlijk te gaan werken met de technische schulden, en Android Studio-controles werden volledig verlaten. Android Studio in Docker voor het uitvoeren van inspecties klinkt interessant, maar zorgt voor veel problemen bij de ondersteuning. Elke update van Android Studio-versies is een gevecht met onbegrijpelijke bugs. Het was ook moeilijk om screenshot-tests te ondersteunen, omdat de bibliotheek niet erg stabiel was en er valse positieven waren. Screenshottests zijn verwijderd uit de checklist.

Het resultaat was dat we het volgende overhielden:

  • ARK-montage;
  • Junit-testen;
  • Instrumentatie testen.

Gradle externe cache

Zonder zware controles werd alles beter. Maar er is geen limiet aan perfectie!

Onze applicatie was al opgesplitst in ongeveer 150 geleidelijke modules. Gradle externe cache werkt in dit geval meestal goed, dus we besloten het te proberen.

Gradle externe cache is een service die build-artefacten voor individuele taken in individuele modules in de cache kan opslaan. Gradle gebruikt, in plaats van de code daadwerkelijk te compileren, HTTP om op de externe cache aan te kloppen en te vragen of iemand deze taak al heeft uitgevoerd. Zo ja, dan wordt eenvoudigweg het resultaat gedownload.

Het uitvoeren van de externe cache van Gradle is eenvoudig omdat Gradle een Docker-image biedt. Het is ons gelukt om dit in drie uur te doen.

Het enige wat u hoefde te doen was Docker starten en één regel in het project schrijven. Maar hoewel het snel gelanceerd kan worden, zal het behoorlijk wat tijd kosten voordat alles goed werkt.

Hieronder ziet u de grafiek met cache-missers.

Evolutie van CI in het mobiele ontwikkelingsteam

Helemaal aan het begin was het percentage cachemissers ongeveer 65. Na drie weken zijn we erin geslaagd deze waarde te verhogen naar 20%. Het bleek dat de taken die de Android-applicatie verzamelt vreemde transitieve afhankelijkheden hebben, waardoor Gradle de cache miste.

Door de cache aan te sluiten, hebben we de bouw enorm versneld. Maar naast de montage zijn er ook instrumentatietesten, en die duren lang. Mogelijk hoeven niet alle tests voor elk pull-verzoek te worden uitgevoerd. Om daar achter te komen maken we gebruik van impactanalyse.

Impactanalyse

Op een pull-verzoek verzamelen we git diff en vinden de gewijzigde Gradle-modules.

Evolutie van CI in het mobiele ontwikkelingsteam

Het is zinvol om alleen instrumentatietests uit te voeren die de gewijzigde modules en alle modules die daarvan afhankelijk zijn, controleren. Het heeft geen zin om tests uit te voeren voor aangrenzende modules: de code daar is niet veranderd en er kan niets kapot gaan.

Instrumentatietests zijn niet zo eenvoudig, omdat ze zich in de applicatiemodule op het hoogste niveau moeten bevinden. We hebben heuristieken met bytecode-analyse gebruikt om te begrijpen tot welke module elke test behoort.

Het opwaarderen van de werking van de instrumentatietesten, zodat alleen de betrokken modules worden getest, duurde ongeveer acht weken.

Maatregelen om de inspecties te versnellen hebben succesvol gewerkt. Van 45 minuten gingen we naar ongeveer 15 minuten. Het is al normaal om een ​​kwartier te wachten op een build.

Maar nu beginnen ontwikkelaars te klagen dat ze niet begrijpen welke builds worden gelanceerd, waar ze het logboek kunnen zien, waarom de build rood is, welke test is mislukt, enz.

Evolutie van CI in het mobiele ontwikkelingsteam

Problemen met feedback vertragen de ontwikkeling, dus we probeerden zo duidelijke en gedetailleerde informatie over elke PR en build te geven. We begonnen met commentaar in Bitbucket aan de PR, waarin we aangaven welke build mislukt was en waarom, en schreven gerichte berichten in Slack. Uiteindelijk hebben we een PR-dashboard voor de pagina gemaakt met een lijst van alle builds die momenteel actief zijn en hun status: in de wachtrij, actief, gecrasht of voltooid. U kunt op de build klikken en naar het logboek gaan.

Evolutie van CI in het mobiele ontwikkelingsteam

Er werden zes weken besteed aan gedetailleerde feedback.

Plannen

Laten we verder gaan met de recente geschiedenis. Nadat we het feedbackprobleem hadden opgelost, bereikten we een nieuw niveau: we besloten onze eigen emulatorfarm te bouwen. Als er veel tests en emulators zijn, zijn ze moeilijk te beheren. Als gevolg hiervan zijn al onze emulators verhuisd naar het k8s-cluster met flexibel resourcebeheer.

Daarnaast zijn er nog andere plannen.

  • Retour Lint (en andere statische analyses). Wij werken al in deze richting.
  • Voer alles uit op een PR-blocker end-to-end testen op alle SDK-versies.

We hebben dus de geschiedenis van de ontwikkeling van continue integratie in Avito gevolgd. Nu wil ik wat advies geven vanuit een ervaren perspectief.

Советы

Als ik maar één advies mag geven, zou het dit zijn:

Wees voorzichtig met shellscripts!

Bash is een zeer flexibel en krachtig hulpmiddel, het is erg handig en snel om scripts te schrijven. Maar je kunt er mee in de val lopen, en helaas zijn wij erin gelopen.

Het begon allemaal met eenvoudige scripts die op onze bouwmachines draaiden:

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

Maar zoals je weet, ontwikkelt alles zich en wordt het in de loop van de tijd ingewikkelder - laten we het ene script van het andere uitvoeren, laten we daar enkele parameters doorgeven - uiteindelijk moesten we een functie schrijven die bepaalt op welk niveau van bash-nesten we ons nu bevinden om de nodige aanhalingstekens in te voegen, om alles op gang te krijgen.

Evolutie van CI in het mobiele ontwikkelingsteam

Je kunt je de arbeidskosten voor de ontwikkeling van dergelijke scripts voorstellen. Ik raad je aan om niet in deze val te trappen.

Wat kan er vervangen worden?

  • Elke scripttaal. Schrijven aan Python- of Kotlin-script handiger omdat het programmeren is en geen scripts.
  • Of beschrijf alle bouwlogica in het formulier Aangepaste geleidelijke taken voor uw project.

We hebben besloten om voor de tweede optie te kiezen, en nu verwijderen we systematisch alle bash-scripts en schrijven we veel aangepaste gradle-taken.

Tip #2: Sla infrastructuur op in code.

Het is handig wanneer de instelling voor continue integratie niet wordt opgeslagen in de UI-interface van Jenkins of TeamCity, enz., maar in de vorm van tekstbestanden rechtstreeks in de projectrepository. Dit geeft versiebaarheid. Het zal niet moeilijk zijn om de code terug te draaien of op een andere branch te bouwen.

Scripts kunnen in een project worden opgeslagen. Wat te doen met het milieu?

Tip #3: Docker kan helpen met het milieu.

Het zal Android-ontwikkelaars zeker helpen; iOS heeft er helaas nog geen.

Dit is een voorbeeld van een eenvoudig dockerbestand dat jdk en android-sdk bevat:

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

Nadat je dit Docker-bestand hebt geschreven (ik zal je een geheim vertellen, je hoeft het niet te schrijven, maar het gewoon kant-en-klaar uit GitHub haalt) en de afbeelding hebt samengesteld, krijg je een virtuele machine waarop je de applicatie kunt bouwen en voer Junit-tests uit.

De twee belangrijkste redenen waarom dit zinvol is, zijn schaalbaarheid en herhaalbaarheid. Met docker kun je snel een tiental build-agents samenstellen die precies dezelfde omgeving hebben als de vorige. Dit maakt het leven van CI-ingenieurs een stuk eenvoudiger. Het is vrij eenvoudig om de Android-SDK in Docker te duwen, maar met emulators is het iets moeilijker: je zult wat harder moeten werken (of de voltooide SDK opnieuw moeten downloaden van GitHub).

Tip nr. 4: vergeet niet dat inspecties niet worden gedaan omwille van de inspecties, maar voor mensen.

Snelle en vooral duidelijke feedback is erg belangrijk voor ontwikkelaars: wat is er kapot gegaan, welke test is mislukt, waar kan ik de buildlog zien.

Tip #5: Wees pragmatisch bij het ontwikkelen van continue integratie.

Begrijp duidelijk welke soorten fouten u wilt voorkomen en hoeveel middelen, tijd en computertijd u bereid bent te besteden. Controles die te lang duren, kunnen bijvoorbeeld van de ene op de andere dag worden uitgesteld. En degenen onder hen die niet erg belangrijke fouten ontdekken, moeten volledig in de steek worden gelaten.

Tip #6: Gebruik kant-en-klaar gereedschap.

Er zijn nu veel bedrijven die cloud-CI aanbieden.

Evolutie van CI in het mobiele ontwikkelingsteam

Voor kleine teams is dit een goede oplossing. U hoeft niets te ondersteunen, u hoeft alleen maar een beetje geld te betalen, uw applicatie te bouwen en zelfs instrumentatietests uit te voeren.

Tip #7: In een groot team zijn interne oplossingen winstgevender.

Maar vroeg of laat, naarmate het team groeit, zullen interne oplossingen winstgevender worden. Er is één probleem met deze beslissingen. Er bestaat in de economie een wet van afnemende opbrengsten: bij elk project wordt elke volgende verbetering steeds moeilijker en vereist steeds meer investeringen.

Economie beschrijft ons hele leven, inclusief continue integratie. Ik heb een schema met arbeidskosten opgesteld voor elke ontwikkelingsfase van onze continue integratie.

Evolutie van CI in het mobiele ontwikkelingsteam

Het is duidelijk dat elke verbetering steeds moeilijker wordt. Als u naar deze grafiek kijkt, begrijpt u dat continue integratie moet worden ontwikkeld in overeenstemming met de groei van de teamgrootte. Voor een team van twee personen is het een middelmatig idee om 50 dagen te besteden aan het ontwikkelen van een interne emulatorfarm. Maar tegelijkertijd is het voor een groot team helemaal niet doen aan Continuous Integration ook een slecht idee, omdat integratieproblemen, het oplossen van communicatie, enz. het zal nog meer tijd kosten.

We zijn begonnen met het idee dat automatisering nodig is omdat mensen duur zijn, fouten maken en lui zijn. Maar mensen automatiseren ook. Daarom zijn dezelfde problemen van toepassing op automatisering.

  • Automatisering is duur. Denk aan het arbeidsschema.
  • Als het om automatisering gaat, maken mensen fouten.
  • Soms is het erg lui om te automatiseren, omdat alles zo werkt. Waarom iets anders verbeteren, waarom al deze continue integratie?

Maar ik heb statistieken: fouten worden in 20% van de assemblages opgemerkt. En dit komt niet omdat onze ontwikkelaars slecht code schrijven. Dit komt omdat ontwikkelaars erop vertrouwen dat als ze een fout maken, deze niet in de ontwikkeling terecht zal komen, maar door geautomatiseerde controles zal worden opgemerkt. Dienovereenkomstig kunnen ontwikkelaars meer tijd besteden aan het schrijven van code en interessante dingen, in plaats van iets lokaal uit te voeren en te testen.

Oefen met continue integratie. Maar met mate.

Nikolai Nesterov geeft overigens niet alleen zelf mooie reportages, maar is ook lid van de programmacommissie AppsConf en helpt anderen betekenisvolle toespraken voor u voor te bereiden. De volledigheid en bruikbaarheid van het volgende conferentieprogramma kunnen worden beoordeeld aan de hand van de onderwerpen in schema. En kom voor meer informatie naar Infospace op 22 en 23 april.

Bron: www.habr.com

Voeg een reactie