A CI fejlődése a mobilfejlesztő csapatban

Ma a legtöbb szoftverterméket csapatban fejlesztik. A sikeres csapatfejlesztés feltételeit egy egyszerű diagram formájában ábrázolhatjuk.

A CI fejlődése a mobilfejlesztő csapatban

Miután megírta a kódot, meg kell győződnie arról, hogy:

  1. Работает.
  2. Nem tör el semmit, beleértve a kollégái által írt kódot sem.

Ha mindkét feltétel teljesül, akkor a siker útján jársz. Hogy ezeket a feltételeket könnyen ellenőrizhessük, és ne térjünk le a nyereséges útról, a Continuous Integration-t találtuk ki.

A CI egy olyan munkafolyamat, amelyben a kódot a lehető leggyakrabban integrálja a teljes termékkódba. És nem csak integrál, hanem folyamatosan ellenőrzi is, hogy minden működik-e. Mivel sokat és gyakran kell ellenőrizni, érdemes elgondolkodni az automatizáláson. Manuálisan mindent ellenőrizhet, de nem szabad, és itt van az ok.

  • Kedves emberek. Bármely programozó egy óra munkája drágább, mint bármely szerver egy óra munkája.
  • Az emberek hibáznak. Emiatt előfordulhatnak olyan helyzetek, amikor a teszteket rossz ágon futtatták, vagy rossz commit-ot fordítottak le a tesztelők számára.
  • Az emberek lusták. Időnként, amikor befejezek egy feladatot, felvetődik a gondolat: „Mit kell ellenőrizni? Két sort írtam - minden működik! Azt hiszem, néhányatoknak néha ilyen gondolataik támadnak. De mindig ellenőrizni kell.

Hogyan valósították meg és fejlesztették ki a Continuous Integration szolgáltatást az Avito mobilfejlesztői csapatában, hogyan haladtak napi 0-ról 450-re, és hogy az építőipari gépek napi 200 órát szerelnek össze, mondja Nyikolaj Neszterov (nnesterov) részt vesz a CI/CD Android alkalmazás minden evolúciós változásában.

A történet egy Android parancs példáján alapul, de a legtöbb megközelítés iOS-en is alkalmazható.


Valamikor régen egy ember dolgozott az Avito Android csapatában. Értelemszerűen nem kellett neki semmi a Folyamatos Integrációból: nem volt kivel integrálódni.

De nőtt a pályázat, egyre több új feladat jelent meg, és ennek megfelelően a csapat is bővült. Egy ponton eljött az ideje, hogy formálisabban alakítsuk ki a kódintegrációs folyamatot. A Git flow használata mellett döntöttek.

A CI fejlődése a mobilfejlesztő csapatban

A Git flow koncepciója jól ismert: egy projektnek van egy közös fejlesztési ága, és minden új funkcióhoz a fejlesztők külön ágat vágnak, elkötelezik magukat, lenyomják, és amikor a kódjukat a fejlesztési ágba akarják egyesíteni, akkor nyitnak meg egy pull kérés. Az ismeretek megosztása és a megközelítések megbeszélése érdekében bevezettük a kódellenőrzést, vagyis a kollégáknak egymás kódját kell ellenőrizniük és megerősíteniük.

ellenőrzések

A kódot a szemével látni menő, de nem elég. Ezért bevezetik az automatikus ellenőrzéseket.

  • Először is ellenőrizzük ARK közgyűlés.
  • Sokat Junit tesztek.
  • A kód lefedettségét vesszük figyelembe, mivel teszteket futtatunk.

Az ellenőrzések végrehajtásának megértéséhez nézzük meg az Avito fejlesztési folyamatát.

Sematikusan a következőképpen ábrázolható:

  • Egy fejlesztő kódot ír a laptopjára. Itt futtathatja az integrációs ellenőrzéseket – akár véglegesítési hook segítségével, akár egyszerűen a háttérben.
  • Miután a fejlesztő lenyomta a kódot, megnyit egy lehívási kérelmet. Ahhoz, hogy a kódja bekerüljön a fejlesztési ágba, át kell menni egy kódellenőrzésen és össze kell gyűjteni a szükséges számú megerősítést. Itt engedélyezheti az ellenőrzéseket és a buildeket: amíg az összes build sikeres nem lesz, a lekérési kérelmet nem lehet egyesíteni.
  • A lehívási kérés egyesítése és a kód beépítése után kiválaszthat egy megfelelő időpontot: például éjszaka, amikor az összes szerver szabad, és annyi ellenőrzést futtathat, amennyit csak akar.

Senki sem szeretett szkennelést futtatni a laptopján. Amikor a fejlesztő befejez egy funkciót, gyorsan le akarja küldeni azt, és megnyitni egy lehívási kérelmet. Ha ebben a pillanatban elindul néhány hosszú ellenőrzés, az nemcsak nem túl kellemes, de lassítja is a fejlődést: miközben a laptop ellenőrzi valamit, nem lehet rajta normálisan dolgozni.

Nagyon szerettük az éjszakai ellenőrzéseket, mert sok az idő és a szerverek, lehet barangolni. De sajnos, amikor a funkciókód bekerül a fejlesztésbe, a fejlesztőnek sokkal kevesebb motivációja van a CI által talált hibák kijavítására. Időnként azon kaptam magam, hogy a reggeli jelentésben talált hibákat megnéztem, hogy valamikor később kijavítom őket, mert most egy klassz, új feladat van Jirában, amit csak el akarok kezdeni.

Ha a checkek blokkolnak egy pull kérést, akkor van elég motiváció, mert amíg a buildek zöldre nem váltak, addig a kód nem kerül be a fejlesztésbe, ami azt jelenti, hogy a feladat nem fejeződik be.

Ennek eredményeként a következő stratégiát választottuk: éjszaka a lehető legtöbb ellenőrzést lefuttatjuk, ezek közül a legkritikusabbakat, és ami a legfontosabb, a leggyorsabbakat indítjuk lehúzási kérésre. De nem állunk meg itt – ezzel párhuzamosan optimalizáljuk az ellenőrzések sebességét, hogy az éjszakai üzemmódból átvigyük őket a kérésellenőrzésekre.

Abban az időben az összes buildünk elég gyorsan elkészült, így egyszerűen beiktattuk az ARK buildet, a Junit teszteket és a kódlefedettség számításokat blokkolóként a pull kérelemhez. Bekapcsoltuk, gondolkodtunk rajta, és feladtuk a kódlefedettséget, mert úgy gondoltuk, hogy nincs rá szükségünk.

Két napba telt az alap CI teljes beállítása (a továbbiakban az időbecslés hozzávetőleges, a méretarányhoz szükséges).

Ezek után elkezdtünk tovább gondolkodni – egyáltalán jól ellenőrizzük? Helyesen futtatjuk a lekérési kérésekre épülő építményeket?

A felépítést annak az ágnak az utolsó véglegesítésén kezdtük meg, amelyből a lehívási kérelem megnyílt. De ennek a véglegesítésnek a tesztjei csak azt mutatják, hogy a fejlesztő által írt kód működik. De nem bizonyítják, hogy nem tört el semmit. Valójában ellenőriznie kell a fejlesztési ág állapotát, miután egy szolgáltatást egyesített benne.

A CI fejlődése a mobilfejlesztő csapatban

Ehhez írtunk egy egyszerű bash szkriptet premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Itt a fejlesztésből származó összes legutóbbi változás egyszerűen fel van húzva, és beolvasztja az aktuális ágba. Minden build első lépéseként hozzáadtuk a premerge.sh szkriptet, és elkezdtük ellenőrizni, hogy pontosan mit akarunk, azaz integráció.

Három napig tartott a probléma lokalizálása, a megoldás megtalálása és a szkript megírása.

Az alkalmazás fejlődött, egyre több feladat jelent meg, nőtt a csapat, és a premerge.sh néha cserbenhagyni kezdett minket. A Develop ellentmondó változtatásokat tartalmazott, amelyek megszakították a felépítést.

Egy példa, hogyan történik ez:

A CI fejlődése a mobilfejlesztő csapatban

Két fejlesztő egyszerre kezd el dolgozni az A és B szolgáltatáson. Az A szolgáltatás fejlesztője egy nem használt funkciót fedez fel a projektben answer() és mint egy jó cserkész, eltávolítja. Ezzel egyidejűleg a B szolgáltatás fejlesztője egy új hívást ad ehhez a függvényhez az ágában.

A fejlesztők befejezik munkájukat, és egyidejűleg megnyitnak egy lehívási kérelmet. A buildek elindulnak, a premerge.sh mindkét lekérést ellenőrzi a legújabb fejlesztési állapotra vonatkozóan – minden ellenőrzés zöld. Ezt követően az A jellemző lehívási kérelme összevonva, a B jellemző lehívási kérelme összevonva... Bumm! A Develop megszakad, mert a fejlesztési kód egy nem létező függvény hívását tartalmazza.

A CI fejlődése a mobilfejlesztő csapatban

Amikor nem fejlődik, akkor igen helyi katasztrófa. Az egész csapat nem gyűjthet be semmit és nem küldhet be tesztelésre.

Így esett, hogy legtöbbször infrastrukturális feladatokon dolgoztam: analitika, hálózat, adatbázisok. Vagyis én írtam azokat a függvényeket és osztályokat, amelyeket más fejlesztők használnak. Emiatt nagyon gyakran kerültem hasonló helyzetekbe. Még lógott is ez a kép egy darabig.

A CI fejlődése a mobilfejlesztő csapatban

Mivel ez nem felelt meg nekünk, elkezdtük feltárni a lehetőségeket ennek megakadályozására.

Hogyan ne törje meg fejlődni

Az első lehetőség: minden lehívási kérés újraépítése a fejlesztés frissítése során. Ha példánkban az A jellemzővel rendelkező lekérési kérés kerül először a fejlesztésbe, akkor a B jellemző lekérése újraépül, és ennek megfelelően az ellenőrzések fordítási hiba miatt meghiúsulnak.

Annak megértéséhez, hogy ez mennyi ideig tart, nézzen meg egy példát két PR-vel. Két PR-t nyitunk meg: két buildet, két ellenőrzést. Miután az első PR-t összevontuk a fejlesztéssel, a másodikat újra kell építeni. Összesen két PR-hez három ellenőrzési ciklus szükséges: 2 + 1 = 3.

Elvileg rendben van. De megnéztük a statisztikát, és a tipikus helyzet a mi csapatunkban 10 nyitott PR volt, majd az ellenőrzések száma a progresszió összege: 10 + 9 +... + 1 = 55. Vagyis 10-et elfogadni. PRs, 55-ször kell újjáépíteni. És ez egy ideális helyzetben, amikor minden ellenőrzés első alkalommal átmegy, amikor senki sem nyit meg egy további lehívási kérelmet, miközben ez a tucat folyamatban van.

Képzelje el magát fejlesztőként, akinek elsőként kell rákattintania az „egyesítés” gombra, mert ha a szomszéd ezt teszi, akkor meg kell várnia, amíg az összes build újra átmegy... Nem, ez nem fog működni , ez komolyan lelassítja a fejlődést.

Második lehetséges út: gyűjtse össze a lehívási kérelmeket a kód áttekintése után. Vagyis megnyit egy lehívási kérelmet, begyűjti a szükséges számú jóváhagyást a kollégáktól, kijavítja a szükségeseket, majd elindítja a buildeket. Ha ezek sikeresek, a lehívási kérés összevonódik a fejlesztésbe. Ebben az esetben nincs további újraindítás, de a visszacsatolás jelentősen lelassul. Fejlesztőként, amikor megnyitok egy lehívási kérelmet, azonnal látni akarom, hogy működni fog-e. Például, ha egy teszt sikertelen, gyorsan meg kell javítania. Késleltetett felépítés esetén lelassul a visszacsatolás, így a teljes fejlesztés. Ez nekünk sem jött be.

Ennek eredményeként csak a harmadik lehetőség maradt - bicikli. Minden kódunk, minden forrásunk a Bitbucket szerver lerakatában van tárolva. Ennek megfelelően egy plugint kellett fejlesztenünk a Bitbuckethez.

A CI fejlődése a mobilfejlesztő csapatban

Ez a beépülő modul felülírja a lekérési kérelmek egyesítési mechanizmusát. A kezdet szabványos: megnyílik a PR, minden összeállítás elindul, a kód felülvizsgálata befejeződött. Ám miután a kód áttekintése befejeződött, és a fejlesztő úgy dönt, hogy rákattint az „egyesítésre”, a beépülő modul ellenőrzi, hogy melyik fejlesztési állapot szerint futottak az ellenőrzések. Ha a fejlesztést a buildek után frissítették, akkor a beépülő modul nem engedi, hogy egy ilyen lehívási kérést egyesítsen a fő ágba. Egyszerűen újraindítja egy viszonylag friss fejlesztés buildjeit.

A CI fejlődése a mobilfejlesztő csapatban

Az ütköző változtatásokat tartalmazó példánkban az ilyen buildek fordítási hiba miatt meghiúsulnak. Ennek megfelelően a B funkció fejlesztőjének ki kell javítania a kódot, újra kell indítania az ellenőrzéseket, majd a plugin automatikusan alkalmazza a lehívási kérést.

A beépülő modul bevezetése előtt átlagosan 2,7 ellenőrzési futtatást végeztünk lekérésenként. A bővítménnyel 3,6 indítás volt. Ez nekünk megfelelt.

Érdemes megjegyezni, hogy ennek a bővítménynek van egy hátránya: csak egyszer indítja újra a buildet. Vagyis még mindig van egy kis ablak, amelyen keresztül egymásnak ellentmondó változások jöhetnek létre. De ennek kicsi a valószínűsége, és kompromisszumot kötöttünk az indítások száma és a kudarc valószínűsége között. Két év alatt csak egyszer sütött, tehát valószínűleg nem volt hiábavaló.

Két hétbe telt, mire megírtuk a Bitbucket bővítmény első verzióját.

Új csekkek

Eközben csapatunk tovább gyarapodott. Új csekkeket adtunk hozzá.

Arra gondoltunk: miért hibázunk, ha azok megelőzhetők? És ezért valósították meg statikus kódelemzés. A linttel kezdtük, amely az Android SDK-ban található. De akkoriban egyáltalán nem tudta, hogyan kell Kotlin kóddal dolgozni, és már az alkalmazás 75%-a Kotlin nyelven íródott. Ezért a szöszhöz beépítetteket adtak Az Android Studio ellenőrzi.

Ehhez sok perverzitást kellett tennünk: vegyük az Android Studio-t, csomagoljuk be Dockerbe, és futtassuk CI-n virtuális monitorral úgy, hogy azt higgye, hogy valódi laptopon fut. De sikerült.

Ez idő alatt kezdtünk el sokat írni is műszeres vizsgálatok és végrehajtották képernyőkép tesztelése. Ekkor egy referencia képernyőképet generálunk egy külön kis nézethez, és a teszt abból áll, hogy a nézetből készítünk egy képernyőképet, és pixelről pixelre hasonlítjuk össze a szabványos képpel. Ha eltérés van, az azt jelenti, hogy valahol elromlott az elrendezés, vagy valami nincs rendben a stílusokban.

De a műszeres teszteket és a képernyőkép-teszteket eszközökön kell futtatni: emulátorokon vagy valódi eszközökön. Tekintettel arra, hogy sok teszt van, és gyakran futnak, egy egész gazdaságra van szükség. A saját gazdaság indítása túlságosan munkaigényes, ezért találtunk egy kész lehetőséget - a Firebase Test Labot.

Firebase tesztlabor

Azért esett rá a választás, mert a Firebase egy Google-termék, vagyis megbízhatónak kell lennie, és nem valószínű, hogy valaha is elpusztul. Az árak ésszerűek: 5 dollár egy valódi eszköz működési órája, egy emulátor 1 dollár.

Körülbelül három hétbe telt, amíg a Firebase tesztlabort a CI-nkbe beültettük.

De a csapat tovább növekedett, és a Firebase sajnos kezdett cserbenhagyni minket. Akkoriban nem volt SLA-ja. Előfordult, hogy a Firebase megvárta, amíg a szükséges számú eszköz szabaddá válik a tesztekhez, és nem kezdték el azonnal a végrehajtást, ahogy szerettük volna. A sorban állás akár fél órát is igénybe vett, ami nagyon hosszú idő. Minden PR-on lefutottak a műszertesztek, a késések nagyon lelassították a fejlesztést, majd kerek összeggel jött a havi számla. Általában úgy döntöttek, hogy elhagyják a Firebase-t, és házon belül dolgoznak, mivel a csapat eléggé kinőtt.

Docker + Python + bash

Fogtuk a Dockert, emulátorokat töltöttünk bele, Pythonban írtunk egy egyszerű programot, ami a megfelelő pillanatban előhozza a szükséges számú emulátort a kívánt verzióban, és szükség esetén leállítja azokat. És persze néhány bash szkript – hol lennénk ezek nélkül?

Öt hétbe telt saját tesztkörnyezetünk létrehozása.

Ennek eredményeként minden lehívási kérelemhez kiterjedt egyesítést blokkoló ellenőrzési lista volt:

  • ARK közgyűlés;
  • Junit tesztek;
  • Szösz;
  • Android Studio ellenőrzi;
  • Műszeres vizsgálatok;
  • Képernyőképes tesztek.

Ezzel sok lehetséges meghibásodást megelőztünk. Technikailag minden működött, de a fejlesztők panaszkodtak, hogy túl sokáig kellett várni az eredményekre.

Meddig túl hosszú? A Bitbucket és a TeamCity adatait feltöltöttük az elemző rendszerbe, és erre rájöttünk átlagos várakozási idő 45 perc. Ez azt jelenti, hogy egy fejlesztő a lehívási kérelem megnyitásakor átlagosan 45 percet vár az összeállítási eredményekre. Véleményem szerint ez sok, és így nem lehet dolgozni.

Természetesen úgy döntöttünk, hogy felgyorsítjuk az összes építkezésünket.

Gyorsítsunk

Látva, hogy az építmények gyakran sorban állnak, az első dolgunk az vásárolt több hardvert — az extenzív fejlesztés a legegyszerűbb. Az építmények leállították a sorban állást, de a várakozási idő csak kis mértékben csökkent, mert egyes ellenőrzések maguk is nagyon sokáig tartottak.

A túl sokáig tartó ellenőrzések eltávolítása

Folyamatos integrációnk képes elkapni az ilyen típusú hibákat és problémákat.

  • Nem fog. A CI fordítási hibát észlelhet, ha valami nem épül fel egymásnak ellentmondó változtatások miatt. Ahogy már mondtam, akkor senki nem tud összeszerelni semmit, leáll a fejlesztés, és mindenki ideges lesz.
  • Hiba a viselkedésben. Például, ha az alkalmazás elkészült, de összeomlik, amikor megnyom egy gombot, vagy a gombot egyáltalán nem nyomják meg. Ez rossz, mert egy ilyen hiba elérheti a felhasználót.
  • Hiba az elrendezésben. Például egy gombra kattintottak, de az 10 képponttal balra mozdult el.
  • Technikai adósságállomány növekedése.

Miután megnéztük ezt a listát, rájöttünk, hogy csak az első két pont kritikus. Először az ilyen problémákat szeretnénk elkapni. Az elrendezési hibákat a tervezés-ellenőrzési szakaszban fedezik fel, és akkor könnyen kijavíthatók. A technikai tartozás kezelése külön folyamatot és tervezést igényel, ezért úgy döntöttünk, hogy nem húzókérésre teszteljük.

Ezen besorolás alapján a teljes csekklistát felráztuk. Lint áthúzva és egyik napról a másikra elhalasztotta az indulást: csak azért, hogy jelentést készítsen arról, mennyi probléma volt a projektben. Megállapodtunk, hogy a műszaki tartozással külön dolgozunk, ill Az Android Studio ellenőrzéseit teljesen elhagyták. Az Android Studio a Dockerben az ellenőrzések futtatásához érdekesen hangzik, de sok gondot okoz a támogatásban. Az Android Studio verzióinak bármilyen frissítése az érthetetlen hibákkal való küzdelmet jelenti. Nehéz volt támogatni a screenshot teszteket is, mert a könyvtár nem volt túl stabil, és voltak hamis pozitív eredmények. A képernyőképes teszteket eltávolítottuk az ellenőrző listáról.

Ennek eredményeként a következők maradtak:

  • ARK közgyűlés;
  • Junit tesztek;
  • Műszeres tesztek.

Gradle távoli gyorsítótár

Komoly ellenőrzések nélkül minden jobb lett. De a tökéletességnek nincs határa!

Alkalmazásunk már körülbelül 150 fokozatú modulra volt felosztva. A Gradle távoli gyorsítótár általában jól működik ebben az esetben, ezért úgy döntöttünk, hogy kipróbáljuk.

A Gradle távoli gyorsítótár egy olyan szolgáltatás, amely gyorsítótárazhatja az egyes modulok egyes feladataihoz szükséges összetevőket. A Gradle ahelyett, hogy ténylegesen lefordítaná a kódot, HTTP használatával kopogtat a távoli gyorsítótáron, és megkérdezi, hogy valaki végrehajtotta-e már ezt a feladatot. Ha igen, akkor egyszerűen letölti az eredményt.

A Gradle távoli gyorsítótár futtatása egyszerű, mert a Gradle Docker-képet biztosít. Ezt három óra alatt sikerült megcsinálnunk.

Mindössze annyit kellett tennie, hogy elindítja a Dockert, és be kell írnia egy sort a projektbe. De bár gyorsan elindítható, elég sok időbe telik, hogy minden jól működjön.

Az alábbiakban látható a gyorsítótár kihagyások grafikonja.

A CI fejlődése a mobilfejlesztő csapatban

Kezdetben a gyorsítótár kihagyások aránya körülbelül 65 volt. Három hét után sikerült ezt az értéket 20%-ra növelni. Kiderült, hogy az Android alkalmazás által összegyűjtött feladatoknak furcsa tranzitív függőségei vannak, ami miatt a Gradle kihagyta a gyorsítótárat.

A gyorsítótár csatlakoztatásával nagymértékben felgyorsítottuk a felépítést. De az összeszerelés mellett vannak műszervizsgálatok is, és ezek sokáig tartanak. Talán nem kell minden tesztet lefuttatni minden lehívási kérelemhez. Ennek kiderítésére hatáselemzést alkalmazunk.

Hatástanulmány

Lehívási kérésre összegyűjtjük a git diff-et, és megkeressük a módosított Gradle modulokat.

A CI fejlődése a mobilfejlesztő csapatban

Célszerű csak olyan műszerteszteket futtatni, amelyek ellenőrzik a megváltozott modulokat és az összes tőlük függő modult. Nincs értelme tesztelni a szomszédos modulokat: a kód ott nem változott, és semmi sem törhet el.

A műszerteszteknél nem minden olyan egyszerű, mert ezeknek a legfelső szintű Alkalmazás modulban kell elhelyezkedniük. Heurisztikát használtunk bájtkód elemzéssel, hogy megértsük, melyik modulhoz tartoznak az egyes tesztek.

A műszertesztek működésének korszerűsítése, hogy csak az érintett modulokat teszteljék, körülbelül nyolc hétig tartott.

Az ellenőrzések felgyorsítását célzó intézkedések sikeresen működtek. 45 percről felmentünk kb 15-re. Az már normális, hogy negyed órát várunk egy építkezésre.

De most a fejlesztők panaszkodni kezdtek, hogy nem értik, mely buildek indulnak el, hol lehet látni a naplót, miért piros a build, melyik teszt sikertelen stb.

A CI fejlődése a mobilfejlesztő csapatban

A visszacsatolási problémák lelassítják a fejlesztést, ezért igyekeztünk a lehető legvilágosabb és részletesebb tájékoztatást adni az egyes PR-okról és buildekről. A Bitbucketben a PR-hoz fűzött megjegyzésekkel kezdtük, jelezve, hogy melyik build hibásodott meg és miért, és célzott üzeneteket írtunk a Slackben. Végül létrehoztunk egy PR-irányítópultot az oldalhoz, amely tartalmazza az összes jelenleg futó buildet és azok állapotát: sorban állás, futó, összeomlott vagy befejezett. Kattintson a buildre, és elérheti a naplóját.

A CI fejlődése a mobilfejlesztő csapatban

Hat hét telt el a részletes visszajelzésekkel.

Tervek

Térjünk át a közelmúlt történelmére. A visszajelzési probléma megoldása után új szintet értünk el - úgy döntöttünk, hogy saját emulátorfarmot építünk. Ha sok teszt és emulátor van, nehéz őket kezelni. Ennek eredményeként az összes emulátorunk a k8s-fürtbe költözött rugalmas erőforrás-kezeléssel.

Ezen kívül vannak más tervek is.

  • Vissza Lint (és egyéb statikus elemzések). Már dolgozunk ebbe az irányba.
  • Futtasson mindent PR-blokkolóval végpontok közötti tesztek az összes SDK-verzión.

Tehát nyomon követtük a Folyamatos Integráció fejlődésének történetét Avitóban. Most egy tapasztalt szemszögből szeretnék tanácsot adni.

Советы

Ha csak egy tanácsot adhatnék, az a következő lenne:

Kérjük, legyen óvatos a shell szkriptekkel!

A Bash egy nagyon rugalmas és hatékony eszköz, nagyon kényelmes és gyors a szkriptek írása. De csapdába eshetsz vele, és sajnos mi is beleestünk.

Az egész egyszerű szkriptekkel kezdődött, amelyek az építőgépeinken futottak:

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

De mint tudod, idővel minden fejlődik és bonyolultabbá válik - futtassuk le egyik szkriptet a másikból, adjunk át néhány paramétert - végül egy függvényt kellett írnunk, ami meghatározza, hogy most milyen szinten vagyunk rendben beszúrni a szükséges idézőjeleket, és elkezdeni mindent.

A CI fejlődése a mobilfejlesztő csapatban

Elképzelheti az ilyen szkriptek fejlesztésének munkaerőköltségét. Azt tanácsolom, hogy ne ess ebbe a csapdába.

Mit lehet cserélni?

  • Bármilyen szkriptnyelv. Írj neki Python vagy Kotlin Script kényelmesebb, mert programozásról van szó, nem szkriptekről.
  • Vagy írja le az összes építési logikát az űrlapon Egyedi gradle feladatok a projektjéhez.

Úgy döntöttünk, hogy a második lehetőséget választjuk, és most szisztematikusan töröljük az összes bash szkriptet, és sok egyéni gradle feladatot írunk.

2. tipp: Tárolja az infrastruktúrát kódban.

Kényelmes, ha a Continuous Integration beállítást nem a Jenkins vagy a TeamCity stb. felhasználói felületén tárolják, hanem szöveges fájlok formájában közvetlenül a projekttárban. Ez változatosságot biztosít. Nem lesz nehéz visszaállítani vagy egy másik ágra felépíteni a kódot.

A szkriptek tárolhatók egy projektben. Mit kezdjünk a környezettel?

3. tipp: A Docker segíthet a környezetvédelemben.

Határozottan segíteni fog az Android fejlesztőknek; iOS-en sajnos még nincs ilyen.

Ez egy példa egy egyszerű docker-fájlra, amely tartalmazza a jdk-t és az android-sdk-t:

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

Miután megírta ezt a Docker fájlt (elárulok egy titkot, nem kell megírni, hanem csak készen kell kihúzni a GitHubból) és összeállította a képet, kap egy virtuális gépet, amelyre az alkalmazást építheti. és futtasson Junit teszteket.

Ennek a két fő oka a méretezhetőség és az ismételhetőség. A docker használatával gyorsan létrehozhat egy tucat összeállítási ügynököt, amelyeknek pontosan ugyanaz a környezete lesz, mint az előzőnek. Ez nagyban megkönnyíti a CI-mérnökök életét. Az android-sdk-t elég könnyű benyomni a dockerbe, de az emulátorokkal kicsit nehezebb: kicsit keményebben kell dolgozni (vagy újra le kell tölteni a készet a GitHubról).

4. tipp: ne felejtsük el, hogy az ellenőrzéseket nem az ellenőrzések miatt végzik, hanem az emberekért.

A fejlesztők számára nagyon fontos a gyors és, ami a legfontosabb, az egyértelmű visszajelzés: mi tört el, milyen teszt nem sikerült, hol láthatom a buildlogot.

5. tipp: Legyen pragmatikus a folyamatos integráció fejlesztésekor.

Világosan tudja meg, hogy milyen típusú hibákat szeretne megelőzni, mennyi erőforrást, időt és számítógépes időt hajlandó rászánni. A túl sokáig tartó ellenőrzések például egyik napról a másikra elhalaszthatók. És azokat, amelyek nem túl fontos hibákat észlelnek, teljesen el kell hagyni.

6. tipp: Használjon kész eszközöket.

Jelenleg számos vállalat kínál felhőalapú CI-t.

A CI fejlődése a mobilfejlesztő csapatban

Ez egy jó megoldás kis csapatok számára. Nem kell támogatnia semmit, csak fizessen egy kis pénzt, készítse el az alkalmazást, és még műszerteszteket is futtasson.

7. tipp: Nagy csapatban a házon belüli megoldások jövedelmezőbbek.

De előbb-utóbb, ahogy a csapat növekszik, a házon belüli megoldások jövedelmezőbbé válnak. Egy probléma van ezekkel a döntésekkel. A közgazdaságtanban létezik a csökkenő megtérülés törvénye: minden projektben minden további fejlesztés egyre nehezebb, és egyre több befektetést igényel.

A közgazdaságtan leírja egész életünket, beleértve a folyamatos integrációt is. A Folyamatos Integráció fejlesztési szakaszaihoz elkészítettem a munkaerőköltségek ütemezését.

A CI fejlődése a mobilfejlesztő csapatban

Nyilvánvaló, hogy minden fejlesztés egyre nehezebb. Ezt a grafikont tekintve megértheti, hogy a folyamatos integrációt a csapatlétszám növekedésével összhangban kell fejleszteni. Egy kétfős csapat számára átlagos ötlet 50 napot eltölteni egy belső emulátorfarm fejlesztésével. De ugyanakkor egy nagy csapatnál a Folyamatos Integráció egyáltalán nem csinálása is rossz ötlet, mert integrációs problémák, kommunikáció javítása stb. még több időbe telik.

Abból indultunk ki, hogy az automatizálásra azért van szükség, mert az emberek drágák, hibáznak és lusták. De az emberek automatizálnak is. Ezért ugyanazok a problémák vonatkoznak az automatizálásra is.

  • Az automatizálás drága. Emlékezzen a munkarendre.
  • Ha automatizálásról van szó, az emberek hibáznak.
  • Néha nagyon lusta automatizálni, mert minden így működik. Miért kellene bármi mást javítani, miért ez a folyamatos integráció?

De vannak statisztikáim: a hibákat az összeállítások 20%-ában észlelik. És ez nem azért van, mert a fejlesztőink rosszul írnak kódot. A fejlesztők ugyanis abban bíznak, hogy ha hibáznak, az nem a fejlesztésbe kerül, hanem az automatizált ellenőrzések fogják el. Ennek megfelelően a fejlesztők több időt tölthetnek kódok és érdekes dolgok írásával, ahelyett, hogy helyben futnának és tesztelnének valamit.

Folyamatos integráció gyakorlása. De mértékkel.

Nyikolaj Neszterov egyébként nemcsak maga ad remek riportokat, hanem a programbizottság tagja is AppsConf és segít másoknak tartalmas beszédeket készíteni neked. A következő konferencia program teljessége és hasznossága témakörök szerint értékelhető menetrend. A részletekért pedig gyere az Infospace-be április 22-23-án.

Forrás: will.com

Hozzászólás