Evolucija CI u timu za mobilni razvoj

Danas većina softverskih proizvoda razvija se u timovima. Uslovi uspeha timskog razvoja mogu se predstaviti jednostavnom shemom.

Evolucija CI u timu za mobilni razvoj

Nakon što napišete kod, morate biti sigurni da je:

  1. Funkcionalan.
  2. Ne razbija ništa, uključujući kod koji su napisali vaši kolege.

Ako su oba uslova ispunjena, na putu ste ka uspehu. Da biste lako proveravali ove uslove i ostali na isplativom putu, uvedena je Kontinuirana Integracija.

CI je radni proces u kojem što češće integrišete svoj kod u zajednički kod proizvoda. I ne samo da integrišete, već stalno proveravate da li sve funkcioniše. Kako se mnogo i često mora proveravati, vredi razmisliti o automatizaciji. Sve možete proveravati ručno, ali ne bi trebalo, i evo zašto.

  • Ljudi su skupi. Sat rada bilo kog programera skuplji je od sata rada bilo kog servera.
  • Ljudi greše. Stoga mogu nastati situacije kada pokrenu testove na pogrešnoj grani ili sastave pogrešan commit za testere.
  • Ljudi su lenji. Povremeno, kada završavam neku zadaću, obično pomislim: "Šta treba da proveravam? Napisao sam dve linije — sigurno sve funkcioniše!" Mislim da su takve misli povremeno i vama na umu. No, uvek treba proveravati.

Kako je timu za mobilni razvoj Avita uvedena i razvijena Kontinuirana Integracija, kako je od 0 došlo do 450 buildova dnevno, i šta build-serveri sklapaju 200 sati dnevno, priča Nikolaj Nesterov (nnesterov) — učesnik svih evolucijskih promena CI/CD Android aplikacije.

Priča je zasnovana na primeru Android tima, ali većina pristupa se može primeniti i na iOS.

Pogledajte video

Davno, u Android timu Avita radio je samo jedan čovek. Po definiciji, njemu nije trebala Kontinuirana Integracija: nije imao s kim da se integriše.

Ali aplikacija je rasla, pojavljivalo se sve više i više novih zadataka, a samim tim je i tim rasla. U nekom trenutku došlo je vreme da se proces integracije koda formalizuje. Odlučeno je da se koristi Git flow.

Evolucija CI u timu za mobilni razvoj

Koncept Git flow je poznat: u projektu postoji jedna zajednička grana develop, a za svaku novu značajku programeri otvaraju posebnu granu, izvršavaju commit na nju, pushuju, i kada žele uvući svoj kod u granu develop, otvaraju pull request. Za razmjenu znanja i raspravu o pristupima uveli smo code review, što znači da kolege trebaju pregledati i potvrditi kod jedni drugima.

Provjere

Gledati kod očima — to je sjajno, ali nije dovoljno. Stoga se uvode automatske provjere.

  • Prvo provjeravamo sastavljanje ARK-a.
  • Puno Junit-testova.
  • Računamo code coverage, budući da pokrećemo testove.

Da bismo shvatili kako bi trebali pokretati ove provjere, pogledajmo proces razvoja u Avitu.

Shematski ga možemo predstaviti ovako:

  • Programer piše kod na svom laptopu. Može pokrenuti provjere integracije upravo ovdje — ili putem commit hook-a, ili jednostavno pokretanjem provjera u pozadini.
  • Nakon što je programer pushovao kod, otvara pull request. Da bi njegov kod ušao u granu develop, potrebno je proći code review i prikupiti potrebni broj potvrda. Ovdje je moguće uključiti provjere i build-ove: dok svi build-ovi nisu uspješni, pull request ne može biti spojeno.
  • Nakon što je pull request spojen i kod ušao u develop, može se odabrati pogodno vrijeme: na primjer, noću, kada su svi serveri slobodni, i pokrenuti provjere koliko god stane.

Pokretanje provjera na svom laptopu nikome se nije svidjelo. Kada programer završi značajku, želi je što brže pushati i otvoriti pull request. Ako se u tom trenutku pokreću neke duge provjere, to nije samo neugodno, već također usporava razvoj: dok laptop nešto provjerava, na njemu nije moguće normalno raditi.

Pokretanje provjera noću se jako svidjelo, jer ima puno vremena i servera, može se uživati. No, nažalost, kada kod značajke uđe u develop, programer već ima mnogo manje motivacije ispraviti greške koje je CI pronašao. Povremeno sam se hvatao kako sam pomislio, kada sam ujutro pogledao izvještaj sa svim pronađenim greškama, da ću ih ispraviti nekad kasnije, jer trenutno u Jiri leži cool novi zadatak koji jednostavno želim početi raditi.

Ako provjere blokiraju pull request, motivacije je dovoljno, jer dok build-ovi ne postanu zeleni, kod neće ući u develop, a to znači da zadatak neće biti završen.

Na kraju smo odabrali strategiju: noću pokrećemo maksimalan mogući set provjera, a najkritičnije i, što je najvažnije, brze, pokrećemo na pull requestu. No, tu ne stajemo — paralelno optimiziramo brzinu prolaska provjera kako bismo ih prenijeli iz noćnog režima u provjere na pull requestu.

U to vrijeme, sve naše izrade su prolazile dovoljno brzo, pa smo jednostavno uključili blokiranje AРK građevine, Junit testove i izračun coveragea koda na pull requestu. Uključili smo, razmislili — i odustali od coveragea koda, jer smo zaključili da nam nije potreban.

Za cijelu postavku osnovnog CI-a su nam trebala dva dana (ovdje i dalje je vremenska procjena približna, potrebna za mjerilo).

Nakon toga smo počeli razmišljati dalje — provjeravamo li ispravno? Pokrećemo li ispravno izrade na pull requestu?

Pokretali smo izradu na posljednjem commit-u grane na kojoj je otvoren pull request. No provjere ovog commita mogu pokazati samo to da kod koji je napisao programer radi. No, ne dokazuju da ništa nije pokvareno. U stvarnosti trebamo provjeriti stanje grane develop nakon što se u nju uključi značajka.

Evolucija CI u timu za mobilni razvoj

Za to smo napisali jednostavan bash skript premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Ovdje se jednostavno uvlače sve najnovije promjene iz developa i prevode u trenutnu granu. Dodali smo skript premerge.sh kao prvi korak svih izrada i počeli provjeravati upravo ono što želimo, to jest integraciju.

Za lokalizaciju problema, pronalazak rješenja i pisanje ovog skripta trebalo nam je tri dana.

Aplikacija se razvijala, zadataka je bilo sve više, ekipa je rasla, a premerge.sh nas je povremeno počeo iznevjeravati. U develop su provaljivale konfliktne promjene koje su lomile izradu.

Primjer kako to izgleda:

Evolucija CI u timu za mobilni razvoj

Dva programera istovremeno započinju s radom na značajkama A i B. Programer značajke A otkriva u projektu neiskorištenu funkciju answer() i, kao dobar izviđač, briše je. Pri tome programer značajke B u svojoj grani dodaje novi poziv te funkcije.

Programeri završavaju s radom i u isto vrijeme otvaraju pull request. Pokeću se izrade, premerge.sh provjerava oba pull requesta s obzirom na svježe stanje developa — sve provjere su zelene. Nakon toga se miješa pull request značajke A, miješa se pull request značajke B… Bum! Develop se pokvari, jer u kodu developa postoji poziv nepostojeće funkcije.

Evolucija CI u timu za mobilni razvoj

Kada se develop ne gradi, to je lokalna katastrofa. Cijeli tim ne može ništa prikupiti i predati na testiranje.

Našao sam se u situaciji da sam najčešće bio zadužen za infrastrukturne zadatke: analitika, mreža, baze podataka. Drugim riječima, ja sam pisao funkcije i klase koje koriste ostali programeri. Zbog toga sam se često našao u sličnim situacijama. Imao sam čak i sliku koja je neko vrijeme visjela.

Evolucija CI u timu za mobilni razvoj

Budući da to nije odgovaralo, počeli smo razmatrati opcije kako to spriječiti.

Kako ne slomiti develop

Prva opcija: ponovno sastaviti sve pull requestove prilikom ažuriranja developa. Ako u našem primjeru pull request s funkcionalnošću A prvi uđe u develop, pull request funkcionalnosti B će se ponovno sastaviti, a time će testovi propasti zbog greške u kompilaciji.

Da bismo shvatili koliko će to vremena oduzeti, razmotrimo primjer s dva PR. Otvorimo dva PR: dva builda, dva pokretanja testova. Nakon što prvi PR uđe u develop, drugi se mora ponovno sastaviti. Dakle, za dva PR potrebna su tri pokretanja testova: 2 + 1 = 3.

U principu, to nije loše. No, pogledali smo statistiku, i tipična situacija u našem timu bila je 10 otvorenih PR, a tada je broj testova zbroj progresije: 10 + 9 +… + 1 = 55. Dakle, da bismo prihvatili 10 PR, morali bismo se ponovno sastaviti 55 puta. I to u idealnoj situaciji, kada svi testovi prolaze iz prve, kada nitko ne otvara dodatni pull request dok se obrađuje ovih deset.

Zamislite sebe kao programera kojem je potrebno brže pritisnuti gumb "merge", jer ako to učini kolega, morat će čekati dok svi buildovi ponovo prođu… Ne, to ne ide, ozbiljno će usporiti razvoj.

Druga moguća opcija: sastavljati pull request nakon code review. To jest, otvorite pull request, sakupite potrebno odobrenje od kolega, ispravite što treba, a nakon toga pokrenite buildove. Ako su uspješni, pull request se spaja s developom. U ovom slučaju nema dodatnih ponovnih pokretanja, ali se povratna informacija značajno usporava. Kao programer, kada otvorim pull request, odmah želim vidjeti hoće li se sastaviti. Na primjer, ako je neki test pao, potrebno ga je brzo popraviti. U slučaju odgođenog sastavljanja usporava se povratna informacija, a time i cijeli razvoj. To nam također nije odgovaralo.

Na kraju je ostala samo treća opcija — voziti biciklSav naš kod, sve naše izvorne datoteke pohranjeni su u repozitoriju na Bitbucket poslužitelju. Stoga smo morali razviti dodatak za Bitbucket.

Evolucija CI u timu za mobilni razvoj

Ovaj dodatak prepravlja mehanizam spajanja pull requestova. Početak je standardan: otvara se PR, pokreću se svi gradnje, prolazi se kroz pregled koda. No nakon što je pregled koda završen i programer odluči pritisnuti «merge», dodatak provjerava u kojem je stanju develop vršen testiranje. Ako se develop ažurirao nakon gradnji, dodatak neće dopustiti spajanje takvog pull requesta u glavnu granu. On jednostavno ponovo pokreće gradnje u odnosu na svježi develop.

Evolucija CI u timu za mobilni razvoj

U našem primjeru s konfliktima takve gradnje neće proći zbog pogreške pri kompilaciji. Stoga će programer značajke B morati ispraviti kod, ponovo pokrenuti provjere, a tada će dodatak automatski primijeniti pull request.

Prije implementacije ovog dodatka, u prosjeku smo imali 2,7 pokretanja provjere po pull requestu. S dodatkom, to je sada 3,6 pokretanja. To nam se svidjelo.

Važno je napomenuti da ovaj dodatak ima nedostatak: ponovo pokreće gradnju samo jedanput. To znači da i dalje postoji malo vremensko okno kroz koje mogu proći konfliktne promjene u develop. No vjerojatnost za to nije visoka, i zato smo se odlučili na ovaj kompromis između broja pokretanja i vjerojatnosti kvara. U proteklih dvije godine to se dogodilo samo jednom, pa vjerojatno nije bilo uzalud.

Za razvoj prve verzije dodatka za Bitbucket potrebna su nam bila dva tjedna.

Nove provjere

U međuvremenu, naš tim je nastavio rasti. Uvode se nove provjere.

Pomislili smo: zašto ispraviti pogreške kada ih možemo spriječiti? I zato smo uveli statističku analizu koda. Počeli smo s lintom, koji dolazi s Android SDK-om. No tada nije mogao raditi s Kotlin kodom, a već je 75% naše aplikacije bilo napisano na Kotlinu. Stoga smo lintu dodali ugrađene Android Studio provjere.

Za to je bilo potrebno puno izmisliti: uzeti Android Studio, pakirati je u Docker i pokrenuti na CI s virtualnim monitorom kako bi mislila da je pokrenuta na pravom laptopu. No to je radilo.

Također, u to vrijeme smo počeli pisati mnogo instrumentacijski testova i uveli testiranje zaslona. Ovo je kada se generira referentni screenshot za malu vizualizaciju, a test se sastoji od snimanja screenshot-a s vizualizacije i usporedbe s referencom piksel po piksel. Ako postoji razlika, to znači da je negdje došlo do problema s rasporedom ili u stilovima nešto nije u redu.

No, instrumentation testove i screenshot testove treba pokretati na uređajima: na emulatorima ili na pravim uređajima. S obzirom na to da ima puno testova i često se pokreću, potrebna je cijela farma. Osnivanje vlastite farme je previše naporno, pa smo našli gotovu opciju — Firebase Test Lab.

Firebase Test Lab

Odabran je jer je Firebase proizvod Google-a, što znači da bi trebao biti pouzdan i malo je vjerojatno da će ikada nestati. Cijene su pristupačne: 5 USD po satu rada stvarnog uređaja, 1 USD po satu rada emulatora.

Implementacija Firebase Test Lab-a u naš CI trajala je otprilike tri tjedna.

No, tim je nastavio rasti, i Firebase nas, nažalost, počeo je razočaravati. U to vrijeme nije imao nikakvu SLA. Ponekad je Firebase zahtijevao da čekamo dok se ne oslobodi potrebno broj uređaja za testove, a ne da ih odmah započne, kao što smo to željeli. Čekanje u redu trajalo je do pola sata, a to je jako dugo. Instrumentation testovi su rađeni na svakom PR-u, a kašnjenja su jako usporila razvoj, a zatim je došao i račun za mjesec s okruglom svotom. Ukratko, odlučili smo se odricati Firebase-a i raditi interno, budući da je tim bio dovoljno velik.

Docker + Python + bash

Uzmemo Docker, smjestimo u njega emulate i napišemo jednostavan program na Python-u koji u pravom trenutku pokreće potrebnu količinu emulatora u pravoj verziji, a kada je potrebno, zaustavlja ih. I, naravno, nekoliko bash skripti — bez njih ne može.

Kreiranje vlastitog testnog okruženja trajalo je pet tjedana.

Kao rezultat, svaki pull request imao je opširan, blokirajući popis provjera:

  • Build ARK;
  • Junit testovi;
  • Lint;
  • Android Studio provjere;
  • Instrumentation testovi;
  • Screenshot testovi.

To je sprječavalo mnogo mogućih kvarova. Tehnički je sve radilo, ali su se programeri žalili da predugo čekaju rezultate.

Predugo — to koliko? Izvukli smo podatke iz Bitbucket-a i TeamCity-a u sustav analize i shvatili da prosječno vrijeme čekanja iznosi 45 minuta. Tako da programer, kada otvori pull request, u prosjeku čeka rezultate builda 45 minuta. Po mom mišljenju, to je jako puno, i nije u redu raditi tako.

Naravno, odlučili smo ubrzati sve naše gradnje.

Ubrzavamo

Kad smo vidjeli da često gradnje stoje u redu, prvo smo kupili dodatnu opremu — ekstenzivni razvoj je najjednostavniji. Gradnje više ne stoje u redu, ali vrijeme čekanja se smanjilo samo malo, jer se neka provjere same po sebi dugo izvode.

Uklanjamo preduge provjere

Naš Continuous Integration mogao je uhvatiti takve tipove grešaka i problema.

  • Ne gradi se. CI može uhvatiti grešku kompilacije kada zbog konfliktnih promjena nešto ne može biti sagrađeno. Kao što sam već spomenuo, tada nitko ništa ne može graditi, razvoj staje, a svi su nervozni.
  • Greška u ponašanju. Na primjer, kada se aplikacija gradi, ali se ruši kada pritisnete dugme, ili dugme uopšte ne reagira. To je loše, jer takva greška može doći do korisnika.
  • Greška u dizajnu. Na primjer, dugme reagira, ali je pomjereno 10 piksela lijevo.
  • Povećanje tehničkog duga.

Pogledavši ovu listu, shvatili smo da su kritične samo prve dvije stavke. Takve probleme želimo uhvatiti u prvom redu. Greške u dizajnu se otkrivaju u fazi revizije dizajna i tada se lako ispravljaju. Rad na tehničkom dugu zahtijeva poseban proces i planiranje, pa smo odlučili ne provjeravati ga na pull request-u.

Na osnovu ove klasifikacije, preispitali smo cijeli popis provjera. Isključili smo Lint i prebacili njegovo pokretanje na noć: samo da bi isporučio izvještaj o broju problema u projektu. S tehničkim dugom smo se dogovorili raditi posebno, a od Android Studio provjera smo potpuno odustali. Android Studio u Docker-u za pokretanje inspekcija zvuči zanimljivo, ali donosi mnogo neugodnosti u podršci. Svaka nadogradnja verzije Android Studio je borba s nejasnim greškama. Također je bilo teško održavati screenshot testove, jer je biblioteka radila nesigurno, bilo je lažnih alarma. Screenshot testove smo uklonili iz popisa provjera.

Na kraju smo ostavili:

  • Build ARK;
  • Junit testovi;
  • Instrumentation testove.

Gradle remote cache

Bez teških provjera sve je postalo bolje. Ali nema kraja savršenstvu!

Naša aplikacija već je bila razbijena na otprilike 150 gradle modula. Obično u takvim slučajevima dobro funkcionira Gradle remote cache, pa smo odlučili to isprobati.

Gradle remote cache je usluga koja može keširati artefakte gradnje za pojedinačne zadatke u pojedinim modulima. Umjesto da stvarno kompajlira kod, Gradle putem HTTP-a provjerava remote cache i pita je li netko već izvršio taj zadatak. Ako jest, jednostavno preuzima rezultat.

Pokrenuti Gradle remote cache je lako, jer Gradle pruža Docker sliku. Uspjeli smo to napraviti za tri sata.

Sve što je trebalo bilo je pokrenuti Docker i dodati jednu liniju u projekt. No iako ga je lako pokrenuti, da bi sve dobro funkcioniralo, bit će potrebno dosta vremena.

Ispod je grafikon promašaja keša.

Evolucija CI u timu za mobilni razvoj

Na početku je postotak promašaja keša bio oko 65. Tijekom tri tjedna uspjeli smo smanjiti tu vrijednost na 20%. Ispostavilo se da zadaci koje gradi Android aplikacija imaju čudne tranzitivne ovisnosti, zbog kojih je Gradle promašivao keš.

Povezivanjem keša značajno smo ubrzali gradnju. No osim gradnje, izvršavaju se i instrumentation testovi, a oni se izvršavaju dugo. Možda nije potrebno izvršavati sve testove za svaku pull request. Da bismo to utvrdili, koristimo analizu utjecaja.

Analiza utjecaja

Na pull requestu prikupljamo git diff i pronalazimo promijenjene Gradle module.

Evolucija CI u timu za mobilni razvoj

Ima smisla pokretati samo one instrumentation testove koji provjeravaju promijenjene module i sve module koji ovise o njima. Nema smisla pokretati testove za susjedne module: tamo se kod nije promijenio i ništa ne može pokvariti.

S instrumentation testovima nije sve tako jednostavno, jer moraju biti u najvišem modulu aplikacije. Primijenili smo heuristiku analize bytecode-a kako bismo shvatili kojem modulu svaki test pripada.

Modernizacija rada instrumentation testova, kako bi provjeravali samo uključene module, trajala je oko osam tjedana.

Mjere za ubrzanje provjera uspješno su djelovale. S 45 minuta smanjili smo na otprilike 15. Četvrt sata čekati gradnju sada je već normalno.

No sada su se programeri počeli žaliti da im nije jasno koje se gradnje pokreću, gdje pogledati log, zašto je gradnja crvena, koji test je pao itd.

Evolucija CI u timu za mobilni razvoj

Problemi s povratnom informacijom usporavaju razvoj, stoga smo se potrudili osigurati što jasnije i detaljnije informacije o svakoj PR i gradnji. Počeli smo s komentarima u Bitbucketu na PR-u koji označavaju koja je gradnja pala i zašto, slali smo ciljane poruke u Slack. Na kraju smo napravili stranicu PR nadzorne ploče sa popisom svih gradnji koje su trenutno pokrenute i njihovim stanjem: u redu, u tijeku, pala ili završena. Možete kliknuti na gradnju i doći do njezina loga.

Evolucija CI u timu za mobilni razvoj

Na detaljnu povratnu informaciju potrošeno je šest tjedana.

Planovi

Prelazimo na najnoviju povijest. Rješavajući problem povratne informacije, prešli smo na novu razinu — odlučili smo izgraditi svoju farmu emulatora. Kada je testova i emulatora mnogo, teško ih je upravljati. Na kraju su svi naši emulatori prebačeni u k8s klaster s fleksibilnim upravljanjem resursima.

Osim toga, postoje i drugi planovi.

  • Vratiti Lint (i druge statičke analize). Već radimo na tom području.
  • Pokretati sve na PR-u kao blokator end-to-end testove na svim verzijama SDK-a.

Dakle, pratili smo razvoj Continuous Integration-a u Avitu. Sada želim dati nekoliko savjeta iz perspektive iskusnog.

Savjeti

Da mogu dati samo jedan savjet, to bi bio ovaj:

Molim vas, budite oprezniji s shell skriptama!

Bash je vrlo fleksibilan i snažan alat, vrlo je praktično i brzo pisati skripte na njemu. No može vas upecati, i nažalost, mi smo se upecali.

Sve je počelo s jednostavnim skriptama koje su se pokretale na našim build mašinama:

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

No, kako se inače zna, sve se s vremenom razvija i komplikuje — ajmo pokrenuti jednu skriptu iz druge, ajmo proslijediti neke parametre — na kraju je bilo potrebno napisati funkciju koja određuje na kojoj razini ugniježdenosti se trenutno nalazimo, kako bismo umetnuli potrebne navodnike da bi to sve proradilo.

Evolucija CI u timu za mobilni razvoj

Možete zamisliti radne napore u razvoju takvih skripti. Preporučujem da ne upadnete u ovu zamku.

Čime to može zamijeniti?

  • Bilo kojim skriptnim jezikom. Pisanje na Pythonu ili Kotlin Scriptu je praktičnije, jer je to programiranje, a ne skripte.
  • Ili opisati svu logiku gradnji u obliku Custom gradle tasks za vaš projekt.

Odlučili smo se za drugu opciju i sada postupno brišemo sve bash skripte i pišemo mnogo prilagođenih gradle taskova.

Savjet br. 2: pohraniti infrastrukturu u kodu.

Praktično je kada se postavke Continuous Integration ne čuvaju u UI sučelju Jenkins-a ili TeamCity-a i slično, već kao tekstualne datoteke direktno u repozitoriju projekta. To omogućuje verzioniranje. Neće biti teško vratiti se ili prikupiti kod na drugoj grani.

Skripte se mogu čuvati u projektu. A što učiniti s okruženjem?

Savjet br. 3: Docker može pomoći s okruženjem.

Android programerima sigurno će pomoći, dok iOS ne, nažalost.

Ovo je primjer jednostavnog docker fajla koji sadrži jdk i 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

# Preuzmi 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

# Instaliraj Android Build Tool i knjižnice
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

Napisao sam ovaj docker fajl (rekao bih u tajnosti, ne morate ga pisati, možete preuzeti gotov s GitHub-a) i sastavljenjem slike dobijate virtuelnu mašinu na kojoj možete sastaviti aplikaciju i pokrenuti Junit testove.

Dva glavna argumenta zašto to ima smisla: skalabilnost i ponovljivost. Pomoću dockera možete brzo pokrenuti desetak build agenata koji će imati identično okruženje kao i prethodni. To značajno olakšava život CI inženjerima. Uključivanje android-sdk u docker je prilično jednostavno, dok s emulatorima malo teže: potrebno je malo se potruditi (ili ponovo preuzeti gotovo s GitHub-a).

Savjet br. 4: ne zaboravite da se provjere ne rade samo radi provjera, već za ljude.

Razvojiteljima je jako važna brza i, što je najbitnije, jasna povratna informacija: što im se pokvarilo, koji je test pao, gdje pogledati build log.

Savjet br. 5: budite pragmatični pri razvoju Continuous Integration.

Jasno razumite koje tipove grešaka želite spriječiti, koliko ste spremni potrošiti resursa, vremena, računarskog vremena. Preduga provjeravanja možete, na primjer, odgoditi za noć. A od onih koja hvataju manje važne greške, potpuno se odricati.

Savjet br. 6: koristite gotove alate.

Trenutno postoji mnogo kompanija koje nude cloud CI.

Evolucija CI u timu za mobilni razvoj

Za male timove ovo je dobro rješenje. Ne morate ništa održavati, samo platite malo novca, okupite svoju aplikaciju i čak pokrenite instrumentacijske teste.

Savjet br. 7: u velikom timu isplativije su in-house rješenja.

No, prije ili kasnije, s rastom tima isplativija će postati in-house rješenja. Postoji jedan aspekt ovih rješenja. U ekonomiji postoji zakon opadajućih prihoda: u svakom projektu svako sljedeće poboljšanje dolazi sve teže, zahtijeva sve više i više investicija.

Ekonomija opisuje cijeli naš život, uključujući Continuous Integration. Izradio sam grafikon troškova rada u svakoj fazi razvoja našeg Continuous Integration.

Evolucija CI u timu za mobilni razvoj

Može se vidjeti da svako poboljšanje postaje sve teže i teže. Gledajući ovaj grafikon, može se razumjeti da se razvoj Continuous Integration treba uskladiti s rastom veličine tima. Za tim od dvoje ljudi utrošiti 50 dana na razvoj interne farme emulatore — nije najbolja ideja. No, isto tako, za veliki tim potpuno ignorirati Continuous Integration — također je loša ideja, jer će na probleme s integracijom, popravke komunikacije i slično otići još više vremena.

Započeli smo s idejom da je automatizacija potrebna, jer su ljudi skupi, griješe i često su lijeni. No automatiziraju također ljudi. Stoga se svi ti problemi odnose i na automatizaciju.

  • Automatizacija je skupa. Sjetite se grafikona troškova rada.
  • Prilikom automatizacije ljudi griješe.
  • Ponekad je vrlo nezgodno automatizirati, jer i ovako sve radi. Zašto još poboljšavati, zašto cijeli taj Continuous Integration?

No, imam statistiku: u 20% izrada dolaze greške. I to se ne događa zato što naši programeri loše pišu kod. To je zato što su programeri sigurni da, ako naprave neku grešku, ona neće ući u develop, uhvatit će je automatizirani testovi. Stoga programeri mogu trošiti više vremena na pisanje koda i zanimljive stvari, umjesto da lokalno nešto provode i provjeravaju.

Bavite se Continuous Integration. Ali umjereno.

Usput, Nikolaj Nesterov ne samo da sam radi odlične prezentacije, već je i član programskog odbora AppsConf i pomaže drugima da pripreme sadržajne nastupe za vas. Puninu i korisnost programa nadolazeće konferencije možete procijeniti prema temama u rasporedu. A za više informacija dođite 22-23. travnja u InfoProstor.

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster