Evoluția CI în echipa de dezvoltare mobilă

Astăzi, majoritatea produselor software sunt dezvoltate în echipe. Condițiile pentru dezvoltarea cu succes a echipei pot fi reprezentate sub forma unei diagrame simple.

Evoluția CI în echipa de dezvoltare mobilă

După ce ați scris codul, trebuie să vă asigurați că:

  1. Funcționează.
  2. Nu rupe nimic, inclusiv codul pe care l-au scris colegii tăi.

Dacă ambele condiții sunt îndeplinite, atunci ești pe calea succesului. Pentru a verifica cu ușurință aceste condiții și a nu ne abate de la calea profitabilă, am venit cu Integrarea continuă.

CI este un flux de lucru în care vă integrați codul în codul general al produsului cât mai des posibil. Și nu doar integrezi, ci și verifici constant dacă totul funcționează. Deoarece trebuie să verificați mult și des, merită să vă gândiți la automatizare. Puteți verifica totul manual, dar nu ar trebui, și iată de ce.

  • Dragi oameni. O oră de muncă a oricărui programator este mai scumpă decât o oră de muncă a oricărui server.
  • Oamenii greșesc. Prin urmare, pot apărea situații când testele au fost executate pe ramura greșită sau a fost compilată comiterea greșită pentru testeri.
  • Oamenii sunt lenesi. Din când în când, când termin o sarcină, apare gândul: „Ce este de verificat? Am scris două rânduri - totul funcționează! Cred că unii dintre voi au și uneori astfel de gânduri. Dar ar trebui să verificați întotdeauna.

Cum a fost implementată și dezvoltată integrarea continuă în echipa de dezvoltare mobilă Avito, cum au trecut de la 0 la 450 de build-uri pe zi și că mașinile de construcție se asamblează 200 de ore pe zi, spune Nikolai Nesterov (nnesterov) este un participant la toate schimbările evolutive ale aplicației CI/CD Android.

Povestea se bazează pe exemplul unei comenzi Android, dar majoritatea abordărilor sunt aplicabile și pe iOS.


Cândva, o persoană lucra în echipa Avito Android. Prin definiție, nu avea nevoie de nimic de la Integrarea continuă: nu avea cu cine să se integreze.

Dar aplicația a crescut, au apărut tot mai multe sarcini noi, iar echipa a crescut în consecință. La un moment dat, este timpul să stabilim mai formal un proces de integrare a codului. S-a decis să se folosească Git flow.

Evoluția CI în echipa de dezvoltare mobilă

Conceptul de flux Git este bine cunoscut: un proiect are o ramură de dezvoltare comună, iar pentru fiecare caracteristică nouă, dezvoltatorii tăie o ramură separată, se angajează în aceasta, împinge și, atunci când doresc să-și îmbine codul în ramura de dezvoltare, deschid un cerere de tragere. Pentru a împărtăși cunoștințele și a discuta despre abordări, am introdus revizuirea codului, adică colegii trebuie să verifice și să confirme reciproc codul.

verificări

Să vezi codul cu ochii tăi este mișto, dar nu suficient. Prin urmare, se introduc controale automate.

  • În primul rând, verificăm Ansamblul ARK.
  • Mulți Teste Junit.
  • Luăm în considerare acoperirea codului, deoarece facem teste.

Pentru a înțelege cum ar trebui efectuate aceste verificări, să ne uităm la procesul de dezvoltare în Avito.

Poate fi reprezentat schematic astfel:

  • Un dezvoltator scrie cod pe laptopul său. Puteți executa verificări de integrare chiar aici - fie cu un commit hook, fie pur și simplu executați verificări în fundal.
  • După ce dezvoltatorul a împins codul, el deschide o cerere de extragere. Pentru ca codul său să fie inclus în ramura de dezvoltare, este necesar să treceți printr-o revizuire a codului și să colectați numărul necesar de confirmări. Puteți activa verificările și build-urile aici: până când toate build-urile au succes, cererea de extragere nu poate fi îmbinată.
  • După ce cererea de extragere este îmbinată și codul este inclus în dezvoltare, puteți alege o oră convenabilă: de exemplu, noaptea, când toate serverele sunt libere, și să efectuați câte verificări doriți.

Nimănui nu-i plăcea să execute scanări pe laptopul lor. Când un dezvoltator a terminat o funcție, vrea să o împingă rapid și să deschidă o cerere de extragere. Dacă în acest moment sunt lansate niște verificări lungi, acest lucru nu numai că nu este foarte plăcut, dar și încetinește dezvoltarea: în timp ce laptopul verifică ceva, este imposibil să lucrezi normal la el.

Ne-a plăcut foarte mult să facem verificări noaptea, pentru că există mult timp și servere, poți să te plimbi. Dar, din păcate, atunci când codul caracteristicilor intră în dezvoltare, dezvoltatorul are mult mai puțină motivație pentru a remedia erorile găsite de CI. M-am surprins periodic gândindu-mă când mă uitam la toate erorile găsite în raportul de dimineață că le voi remedia cândva mai târziu, pentru că acum există o sarcină nouă în Jira pe care vreau doar să încep să o fac.

Dacă verificările blochează o cerere de extragere, atunci există suficientă motivație, deoarece până când versiunile devin verde, codul nu va intra în dezvoltare, ceea ce înseamnă că sarcina nu va fi finalizată.

Drept urmare, am ales următoarea strategie: rulăm setul maxim posibil de verificări pe timp de noapte și le lansăm pe cele mai critice dintre ele și, cel mai important, pe cele mai rapide pe o cerere de tip pull. Dar nu ne oprim aici – în paralel, optimizăm viteza controalelor, astfel încât să le transferăm din modul de noapte la verificările de solicitare.

La acel moment, toate build-urile noastre au fost finalizate destul de repede, așa că am inclus pur și simplu build-ul ARK, testele Junit și calculele de acoperire a codului ca blocant pentru cererea de extragere. L-am pornit, ne-am gândit la asta și am abandonat acoperirea codului pentru că ne-am gândit că nu avem nevoie de el.

Ne-a luat două zile pentru a configura complet CI de bază (în continuare timpul estimat este aproximativ, necesar pentru scară).

După aceea, am început să ne gândim mai departe - chiar verificăm corect? Executăm corect versiunile pe solicitări de extragere?

Am început build-ul pe ultimul commit al sucursalei din care a fost deschisă cererea de extragere. Dar testele acestui commit pot arăta doar că codul pe care l-a scris dezvoltatorul funcționează. Dar ei nu dovedesc că nu a spart nimic. De fapt, trebuie să verificați starea ramurii de dezvoltare după ce o caracteristică este îmbinată în ea.

Evoluția CI în echipa de dezvoltare mobilă

Pentru a face acest lucru, am scris un script bash simplu premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Aici, toate cele mai recente modificări de la dezvoltare sunt pur și simplu extrase și fuzionate în ramura actuală. Am adăugat scriptul premerge.sh ca prim pas în toate versiunile și am început să verificăm exact ceea ce ne dorim, adică integrare.

A durat trei zile pentru a localiza problema, a găsi o soluție și a scrie acest script.

Aplicația s-a dezvoltat, au apărut tot mai multe sarcini, echipa a crescut și premerge.sh a început uneori să ne dezamăgească. Develop a avut modificări conflictuale care au rupt construcția.

Un exemplu despre cum se întâmplă acest lucru:

Evoluția CI în echipa de dezvoltare mobilă

Doi dezvoltatori încep să lucreze simultan la caracteristicile A și B. Dezvoltatorul caracteristicii A descoperă o caracteristică neutilizată în proiect answer() și, ca un boy scout bun, îl îndepărtează. În același timp, dezvoltatorul caracteristicii B adaugă un nou apel acestei funcții în ramura sa.

Dezvoltatorii își termină munca și deschid o cerere de extragere în același timp. Compilările sunt lansate, premerge.sh verifică ambele cereri de extragere cu privire la cea mai recentă stare de dezvoltare - toate verificările sunt verzi. După aceea, cererea de extragere a caracteristicii A este îmbinată, cererea de extragere a caracteristicii B este îmbinată... Boom! Se întrerupe dezvoltarea deoarece codul de dezvoltare conține un apel la o funcție inexistentă.

Evoluția CI în echipa de dezvoltare mobilă

Când nu se va dezvolta, este dezastru local. Întreaga echipă nu poate colecta nimic și îl poate trimite pentru testare.

S-a întâmplat să lucrez cel mai adesea la sarcini de infrastructură: analiză, rețea, baze de date. Adică eu am fost cel care am scris acele funcții și clase pe care le folosesc alți dezvoltatori. Din această cauză, m-am trezit foarte des în situații similare. Chiar am avut această poză agățată pentru o vreme.

Evoluția CI în echipa de dezvoltare mobilă

Deoarece acest lucru nu ne convine, am început să explorăm opțiuni pentru a preveni acest lucru.

Cum să nu rupi dezvoltarea

Prima opțiune: reconstruiți toate cererile de extragere când se dezvoltă actualizarea. Dacă, în exemplul nostru, cererea de extragere cu caracteristica A este prima inclusă în dezvoltare, cererea de extragere a caracteristicii B va fi reconstruită și, în consecință, verificările vor eșua din cauza unei erori de compilare.

Pentru a înțelege cât timp va dura, luați în considerare un exemplu cu două PR. Deschidem două PR-uri: două versiuni, două serii de verificări. După ce primul PR este fuzionat în dezvoltare, al doilea trebuie reconstruit. În total, două PR necesită trei serii de verificări: 2 + 1 = 3.

În principiu, e în regulă. Dar ne-am uitat la statistici, iar situația tipică în echipa noastră a fost de 10 PR-uri deschise, iar apoi numărul de verificări este suma progresiei: 10 + 9 +... + 1 = 55. Adică să acceptăm 10 PR, trebuie să reconstruiți de 55 de ori. Și aceasta este într-o situație ideală, când toate verificările trec prima dată, când nimeni nu deschide o cerere de extragere suplimentară în timp ce aceste zeci sunt procesate.

Imaginați-vă ca un dezvoltator care trebuie să fie primul care face clic pe butonul „merge”, pentru că dacă un vecin face acest lucru, atunci va trebui să așteptați până când toate build-urile trec din nou... Nu, asta nu va funcționa , va încetini serios dezvoltarea.

Al doilea mod posibil: colectați solicitări de extragere după examinarea codului. Adică, deschideți o cerere de extragere, colectați numărul necesar de aprobări de la colegi, corectați ceea ce este necesar și apoi lansați versiunile. Dacă au succes, cererea de extragere este fuzionată în develop. În acest caz, nu există reporniri suplimentare, dar feedback-ul este foarte încetinit. În calitate de dezvoltator, când deschid o cerere de extragere, vreau imediat să văd dacă va funcționa. De exemplu, dacă un test eșuează, trebuie să îl remediați rapid. În cazul unei versiuni întârziate, feedback-ul încetinește și, prin urmare, întreaga dezvoltare. Nici asta nu ne convine.

Ca urmare, a rămas doar a treia opțiune - ciclism. Tot codul nostru, toate sursele noastre sunt stocate într-un depozit de pe serverul Bitbucket. În consecință, a trebuit să dezvoltăm un plugin pentru Bitbucket.

Evoluția CI în echipa de dezvoltare mobilă

Acest plugin suprascrie mecanismul de îmbinare a cererilor de extragere. Începutul este standard: PR-ul se deschide, toate ansamblurile sunt lansate, revizuirea codului este finalizată. Dar după ce revizuirea codului este finalizată și dezvoltatorul decide să facă clic pe „imbinare”, pluginul verifică în ce stare de dezvoltare au fost efectuate verificările. Dacă dezvoltarea a fost actualizată după versiuni, pluginul nu va permite ca o astfel de solicitare de extragere să fie îmbinată în ramura principală. Pur și simplu va reporni versiunile unei dezvoltări relativ recente.

Evoluția CI în echipa de dezvoltare mobilă

În exemplul nostru cu modificări conflictuale, astfel de versiuni vor eșua din cauza unei erori de compilare. În consecință, dezvoltatorul caracteristicii B va trebui să corecteze codul, să repornească verificările, apoi pluginul va aplica automat cererea de extragere.

Înainte de a implementa acest plugin, am avut o medie de 2,7 executări de revizuire per cerere de extragere. Cu pluginul au fost 3,6 lansări. Acest lucru ni se potrivea.

Este demn de remarcat faptul că acest plugin are un dezavantaj: repornește construcția o singură dată. Adică, există încă o mică fereastră prin care se pot dezvolta schimbări conflictuale. Dar probabilitatea acestui lucru este scăzută și am făcut acest compromis între numărul de porniri și probabilitatea de eșec. În doi ani a tras o singură dată, deci probabil că nu a fost în zadar.

Ne-a luat două săptămâni să scriem prima versiune a pluginului Bitbucket.

Noi verificări

Între timp, echipa noastră a continuat să crească. Au fost adăugate noi verificări.

Ne-am gândit: de ce să facem greșeli dacă pot fi prevenite? Și de aceea au implementat analiza codului static. Am început cu lint, care este inclus în Android SDK. Dar la acel moment nu știa deloc să lucreze cu codul Kotlin și aveam deja 75% din aplicație scrisă în Kotlin. Prin urmare, cele încorporate au fost adăugate la scame Verificări Android Studio.

Pentru a face acest lucru, a trebuit să facem multe perversări: luăm Android Studio, îl ambalăm în Docker și îl rulăm pe CI cu un monitor virtual, astfel încât să creadă că rulează pe un laptop real. Dar a funcționat.

Tot în această perioadă am început să scriem mult teste de instrumentare și implementate testarea capturii de ecran. Acesta este momentul în care o captură de ecran de referință este generată pentru o vizualizare mică separată, iar testul constă în luarea unei capturi de ecran din vizualizare și compararea acesteia cu standardul direct pixel cu pixel. Dacă există o discrepanță, înseamnă că aspectul a mers prost undeva sau ceva nu este în regulă în stiluri.

Dar testele de instrumentare și testele de capturi de ecran trebuie să fie rulate pe dispozitive: pe emulatoare sau pe dispozitive reale. Avand in vedere ca sunt multe teste si se ruleaza frecvent, este nevoie de o ferma intreaga. Înființarea propriei fermă necesită prea multă muncă, așa că am găsit o opțiune gata făcută - Firebase Test Lab.

Laboratorul de testare Firebase

A fost ales deoarece Firebase este un produs Google, ceea ce înseamnă că ar trebui să fie de încredere și puțin probabil să moară vreodată. Prețurile sunt rezonabile: 5 USD pe oră de funcționare a unui dispozitiv real, 1 USD pe oră de funcționare a unui emulator.

A durat aproximativ trei săptămâni pentru a implementa Firebase Test Lab în CI.

Dar echipa a continuat să crească, iar Firebase, din păcate, a început să ne dezamăgească. La acel moment, el nu avea niciun SLA. Uneori, Firebase ne-a făcut să așteptăm până când numărul necesar de dispozitive a fost liber pentru teste și nu a început să le executăm imediat, așa cum ne-am dorit. Așteptarea la coadă a durat până la jumătate de oră, ceea ce este un timp foarte lung. Testele de instrumentare au fost efectuate la fiecare PR, întârzierile au încetinit cu adevărat dezvoltarea, iar apoi factura lunară a venit cu o sumă rotundă. În general, s-a decis să se abandoneze Firebase și să se lucreze în interior, deoarece echipa crescuse suficient.

Docker + Python + bash

Am luat Docker, am introdus emulatori în el, am scris un program simplu în Python, care la momentul potrivit aduce numărul necesar de emulatori în versiunea necesară și îi oprește atunci când este necesar. Și, desigur, câteva scripturi bash - unde am fi noi fără ele?

A fost nevoie de cinci săptămâni pentru a ne crea propriul mediu de testare.

Ca rezultat, pentru fiecare cerere de extragere a existat o listă extinsă de verificări de blocare a îmbinării:

  • ansamblu ARK;
  • teste Junit;
  • Puf;
  • verificări Android Studio;
  • Teste de instrumentare;
  • Teste capturi de ecran.

Acest lucru a prevenit multe posibile defecțiuni. Din punct de vedere tehnic, totul a funcționat, dar dezvoltatorii s-au plâns că așteptarea rezultatelor a fost prea lungă.

Cât timp este prea lung? Am încărcat date de la Bitbucket și TeamCity în sistemul de analiză și am realizat asta timp mediu de așteptare 45 de minute. Adică, un dezvoltator, când deschide o cerere de extragere, așteaptă în medie 45 de minute pentru rezultatele construirii. După părerea mea, asta este mult și nu poți lucra așa.

Desigur, am decis să ne grăbim toate construcțiile.

Să grăbim

Văzând că build-urile stau adesea la coadă, primul lucru pe care îl facem este a cumparat mai mult hardware — dezvoltarea extinsă este cea mai simplă. Build-urile au încetat să mai stea la coadă, dar timpul de așteptare a scăzut doar puțin, deoarece unele verificări în sine au durat foarte mult.

Eliminarea controalelor care durează prea mult

Integrarea noastră continuă ar putea surprinde aceste tipuri de erori și probleme.

  • Nu intenționez să. CI poate detecta o eroare de compilare atunci când ceva nu se construiește din cauza unor modificări conflictuale. După cum am spus deja, atunci nimeni nu poate asambla nimic, dezvoltarea se oprește și toată lumea devine nervoasă.
  • Bug în comportament. De exemplu, când aplicația este construită, dar se blochează când apăsați un buton sau butonul nu este apăsat deloc. Acest lucru este rău, deoarece o astfel de eroare poate ajunge la utilizator.
  • Eroare în aspect. De exemplu, se face clic pe un buton, dar s-a mutat cu 10 pixeli la stânga.
  • Creșterea datoriei tehnice.

După ce ne-am uitat la această listă, ne-am dat seama că doar primele două puncte sunt critice. Vrem să surprindem astfel de probleme mai întâi. Bug-urile din aspect sunt descoperite în etapa de revizuire a designului și pot fi corectate cu ușurință atunci. Abordarea datoriilor tehnice necesită un proces și o planificare separată, așa că am decis să nu o testăm la cerere.

Pe baza acestei clasificări, am zguduit întreaga listă de verificări. Lint tăiat și și-a amânat lansarea peste noapte: doar ca să facă un raport despre câte probleme au fost în proiect. Am fost de acord să lucrăm separat cu datoria tehnică și Verificările Android Studio au fost complet abandonate. Android Studio în Docker pentru rularea inspecțiilor sună interesant, dar provoacă multe probleme în suport. Orice actualizare a versiunilor Android Studio înseamnă o luptă cu erori de neînțeles. De asemenea, a fost dificil să suportăm testele de capturi de ecran, deoarece biblioteca nu era foarte stabilă și au existat fals pozitive. Testele capturii de ecran au fost eliminate din lista de verificare.

Drept urmare, am rămas cu:

  • ansamblu ARK;
  • teste Junit;
  • Teste de instrumentare.

Gradle cache la distanță

Fără verificări grele, totul a devenit mai bine. Dar nu există limită pentru perfecțiune!

Aplicația noastră a fost deja împărțită în aproximativ 150 de module gradle. Cache la distanță Gradle funcționează de obicei bine în acest caz, așa că am decis să încercăm.

Cache la distanță Gradle este un serviciu care poate stoca în cache artefacte de construcție pentru sarcini individuale în module individuale. Gradle, în loc să compile efectiv codul, folosește HTTP pentru a bate memoria cache la distanță și pentru a întreba dacă cineva a efectuat deja această sarcină. Dacă da, pur și simplu descarcă rezultatul.

Rularea cache la distanță Gradle este ușoară, deoarece Gradle oferă o imagine Docker. Am reușit să facem asta în trei ore.

Tot ce trebuia să faceți era să lansați Docker și să scrieți o linie în proiect. Dar, deși poate fi lansat rapid, va dura destul de mult timp pentru ca totul să funcționeze bine.

Mai jos este graficul ratelor din cache.

Evoluția CI în echipa de dezvoltare mobilă

La început, procentul ratelor de cache era de aproximativ 65. După trei săptămâni, am reușit să creștem această valoare la 20%. S-a dovedit că sarcinile pe care le colectează aplicația Android au dependențe tranzitive ciudate, din cauza cărora Gradle a ratat memoria cache.

Conectând memoria cache, am accelerat foarte mult construirea. Dar, pe lângă asamblare, există și teste de instrumentare și durează mult. Poate că nu toate testele trebuie să fie executate pentru fiecare cerere de extragere. Pentru a afla, folosim analiza de impact.

Analiza impactului

La o cerere de extragere, colectăm git diff și găsim modulele Gradle modificate.

Evoluția CI în echipa de dezvoltare mobilă

Este logic să rulați doar teste de instrumentare care verifică modulele modificate și toate modulele care depind de acestea. Nu are rost să rulezi teste pentru modulele vecine: codul de acolo nu s-a schimbat și nimic nu se poate rupe.

Testele de instrumentare nu sunt atât de simple, deoarece trebuie să fie amplasate în modulul Aplicație de nivel superior. Am folosit euristica cu analiza bytecode pentru a înțelege cărui modul îi aparține fiecare test.

Actualizarea funcționării testelor de instrumentare astfel încât acestea să testeze doar modulele implicate a durat aproximativ opt săptămâni.

Măsurile de accelerare a inspecțiilor au funcționat cu succes. De la 45 de minute am urcat la vreo 15. E deja normal să așteptăm un sfert de oră pentru o construcție.

Dar acum dezvoltatorii au început să se plângă că nu înțeleg ce build-uri sunt lansate, unde să vadă jurnalul, de ce build-ul este roșu, ce test a eșuat etc.

Evoluția CI în echipa de dezvoltare mobilă

Problemele legate de feedback încetinesc dezvoltarea, așa că am încercat să furnizăm informații cât mai clare și detaliate despre fiecare PR și cât mai mult posibil. Am început cu comentarii în Bitbucket către PR, indicând ce versiune a eșuat și de ce, și am scris mesaje direcționate în Slack. În cele din urmă, am creat un tablou de bord PR pentru pagină cu o listă cu toate versiunile care rulează în prezent și starea lor: în coadă, în execuție, blocate sau finalizate. Puteți face clic pe build și puteți ajunge la jurnalul acesteia.

Evoluția CI în echipa de dezvoltare mobilă

S-au petrecut șase săptămâni pentru feedback detaliat.

Planuri

Să trecem la istoria recentă. După ce am rezolvat problema de feedback, am atins un nou nivel - am decis să ne construim propria fermă de emulatori. Când există multe teste și emulatori, acestea sunt dificil de gestionat. Ca rezultat, toți emulatorii noștri s-au mutat în cluster-ul k8s cu management flexibil al resurselor.

În plus, există și alte planuri.

  • Întoarce Lint (și alte analize statice). Lucrăm deja în această direcție.
  • Rulați totul pe un blocator de PR teste end-to-end pe toate versiunile SDK.

Deci, am urmărit istoria dezvoltării integrării continue în Avito. Acum vreau să dau câteva sfaturi din punct de vedere experimentat.

Советы

Daca as putea da un singur sfat ar fi acesta:

Vă rugăm să aveți grijă cu scripturile shell!

Bash este un instrument foarte flexibil și puternic, este foarte convenabil și rapid pentru a scrie scripturi. Dar poți cădea într-o capcană cu ea și, din păcate, noi am căzut în ea.

Totul a început cu scripturi simple care rulau pe mașinile noastre de construcție:

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

Dar, după cum știți, totul se dezvoltă și devine mai complicat în timp - să rulăm un script din altul, să trecem niște parametri acolo - până la urmă a trebuit să scriem o funcție care să determină la ce nivel de imbricare bash suntem acum în ordine. pentru a introduce ghilimele necesare, pentru a începe totul.

Evoluția CI în echipa de dezvoltare mobilă

Vă puteți imagina costurile cu forța de muncă pentru dezvoltarea unor astfel de scripturi. Te sfătuiesc să nu cazi în această capcană.

Ce poate fi înlocuit?

  • Orice limbaj de scripting. Scrie la Script Python sau Kotlin mai convenabil pentru că este programare, nu scripturi.
  • Sau descrieți toată logica de construcție în formular Sarcini personalizate gradle pentru proiectul dvs.

Am decis să alegem a doua opțiune, iar acum ștergem sistematic toate scripturile bash și scriem o mulțime de sarcini gradle personalizate.

Sfat #2: stocați infrastructura în cod.

Este convenabil când setarea Integrare continuă este stocată nu în interfața UI a lui Jenkins sau TeamCity etc., ci sub formă de fișiere text direct în depozitul de proiect. Acest lucru oferă versiuneabilitatea. Nu va fi dificil să derulați înapoi sau să construiți codul pe altă ramură.

Scripturile pot fi stocate într-un proiect. Ce să faci cu mediul?

Sfatul #3: Docker poate ajuta cu mediul înconjurător.

Cu siguranță îi va ajuta pe dezvoltatorii Android; iOS nu are încă unul, din păcate.

Acesta este un exemplu de fișier docker simplu care conține 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

# 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

După ce ați scris acest fișier Docker (vă spun un secret, nu trebuie să îl scrieți, ci doar să îl trageți gata făcut din GitHub) și asamblat imaginea, obțineți o mașină virtuală pe care puteți construi aplicația și rulați teste Junit.

Cele două motive principale pentru care acest lucru are sens sunt scalabilitatea și repetabilitatea. Folosind docker, puteți crea rapid o duzină de agenți de construcție care vor avea exact același mediu ca cel anterior. Acest lucru face viața inginerilor CI mult mai ușoară. Este destul de ușor să împingeți Android-sdk-ul în docker, dar cu emulatoare este puțin mai dificil: va trebui să munciți puțin mai mult (sau să descărcați din nou pe cel terminat de pe GitHub).

Sfatul nr. 4: nu uitați că inspecțiile nu se fac de dragul inspecțiilor, ci pentru oameni.

Un feedback rapid și, cel mai important, clar este foarte important pentru dezvoltatori: ce s-a stricat, ce test a eșuat, unde pot vedea jurnalul de construcție.

Sfatul #5: Fiți pragmatici atunci când dezvoltați integrarea continuă.

Înțelegeți clar ce tipuri de erori doriți să preveniți, cât de multe resurse, timp și timp pe computer sunteți dispus să petreceți. Verificările care durează prea mult pot fi, de exemplu, amânate peste noapte. Și cei dintre ei care prind erori nu foarte importante ar trebui să fie complet abandonați.

Sfat #6: Folosiți instrumente gata făcute.

Acum există multe companii care oferă cloud CI.

Evoluția CI în echipa de dezvoltare mobilă

Aceasta este o soluție bună pentru echipele mici. Nu trebuie să susțineți nimic, doar să plătiți puțini bani, să vă construiți aplicația și chiar să rulați teste de instrumentare.

Sfatul #7: Într-o echipă mare, soluțiile interne sunt mai profitabile.

Dar, mai devreme sau mai târziu, pe măsură ce echipa crește, soluțiile interne vor deveni mai profitabile. Există o problemă cu aceste decizii. Există o lege a rentabilității descrescătoare în economie: în orice proiect, fiecare îmbunătățire ulterioară este din ce în ce mai dificilă și necesită din ce în ce mai multe investiții.

Economia descrie întreaga noastră viață, inclusiv integrarea continuă. Am construit un grafic al costurilor cu forța de muncă pentru fiecare etapă de dezvoltare a integrării noastre continue.

Evoluția CI în echipa de dezvoltare mobilă

Este clar că orice îmbunătățire devine din ce în ce mai dificilă. Privind acest grafic, puteți înțelege că integrarea continuă trebuie dezvoltată în conformitate cu creșterea dimensiunii echipei. Pentru o echipă de două persoane, a petrece 50 de zile pentru a dezvolta o fermă de emulator intern este o idee mediocră. Dar, în același timp, pentru o echipă mare, a nu face Integrare Continuă deloc este și o idee proastă, deoarece probleme de integrare, remedierea comunicării etc. va dura și mai mult timp.

Am plecat de la ideea că automatizarea este necesară pentru că oamenii sunt scumpi, greșesc și sunt leneși. Dar oamenii automatizează și. Prin urmare, toate aceleași probleme se aplică automatizării.

  • Automatizarea este scumpă. Amintiți-vă programul de muncă.
  • Când vine vorba de automatizare, oamenii fac greșeli.
  • Uneori este foarte leneș să automatizezi, pentru că totul funcționează așa. De ce să îmbunătățim altceva, de ce toată această Integrare continuă?

Dar am statistici: erorile sunt prinse în 20% din ansambluri. Și acest lucru nu se datorează faptului că dezvoltatorii noștri scriu codul prost. Acest lucru se datorează faptului că dezvoltatorii sunt încrezători că, dacă fac vreo greșeală, aceasta nu va ajunge în dezvoltare, va fi prins de verificări automate. În consecință, dezvoltatorii pot petrece mai mult timp scriind cod și lucruri interesante, în loc să ruleze și să testeze ceva la nivel local.

Practicați integrarea continuă. Dar cu moderație.

Apropo, Nikolai Nesterov nu numai că dă el însuși rapoarte grozave, ci este și membru al comitetului de program AppsConf și îi ajută pe alții să pregătească discursuri semnificative pentru tine. Completitudinea și utilitatea programului următoarei conferințe pot fi evaluate prin subiecte în programa. Și pentru detalii, vino la Infospace în perioada 22-23 aprilie.

Sursa: www.habr.com

Adauga un comentariu