A CI fejlődése a mobilfejlesztő csapatban

Ma a legtöbb szoftverterméket csapatokban fejlesztenek. A csapatmunkás fejlesztés sikerének feltételeit egy egyszerű sémában lehet ábrázolni.

A CI fejlődése a mobilfejlesztő csapatban

A kód megírása után meg kell győződni arról, hogy:

  1. Működik.
  2. Nem tör el semmit, beleértve a kollégák által írt kódot is.

Ha mindkét feltétel teljesül, akkor úton vagy a siker felé. Ahhoz, hogy ezeket a feltételeket könnyen ellenőrizhessük és ne térjünk le a kedvező útról, kitalálták a folyamatos integrációt.

A CI egy olyan munkafolyamat, amely során a lehető leggyakrabban integrálod a kódot a termék közös kódjába. Ráadásul nemcsak integrálod, hanem folyamatosan ellenőrzöd is, hogy minden működik. Mivel sok mindent kell gyakran ellenőrizni, érdemes elgondolkodni az automatizáláson. Minden tesztet lehet manuálisan is végezni, de nem érdemes, és itt van, miért.

  • Az emberek drágák. Bármely programozó óradíja drágább, mint bármely szerver óradíja.
  • Az emberek hibáznak. Ezért előfordulhat, hogy olyan ágon futtatnak teszteket, ami nem a megfelelő ág, vagy nem a megfelelő commitot gyűjtötték össze a tesztelőknek.
  • Az emberek lusták. Időnként, amikor befejezek egy feladatot, az jut eszembe: 'De hát mit kell itt ellenőrizni? Két sort írtam — biztos, hogy minden működik!' Gondolom, hogy néhányotoknak is időnként hasonló gondolatai akadnak. De mindig ellenőrizni kell.

Hogyan vezettük be és fejlesztettük a folyamatos integrációt a Avito mobilfejlesztő csapatában, hogyan jutottunk el a napi 450 buildig, és hogy a build gépek naponta 200 órát gyűjtenek, arról Nikolai Nesterov (nnesterov) beszél, aki részt vett a CI/CD Android alkalmazás evolúciós változásaiban.

A beszámoló az Android csapat példáján alapul, de a legtöbb megközelítés az iOS-re is alkalmazható.

Videó lejátszása

Réges-régen az Avito Android csapatában egyetlen ember dolgozott. Neki alapvetően semmire sem volt szüksége a folyamatos integrációhoz: nem volt kivel integrálni.

De az alkalmazás nőtt, egyre több új feladat jelentkezett, ennek megfelelően a csapat is bővült. Egy idő után eljött az idő, hogy formálisan rendbe tegyük a kódintegrálási folyamatot. Úgy döntöttek, hogy a Git flow-t fogják használni.

A CI fejlődése a mobilfejlesztő csapatban

A Git flow concept is well-known: in a project, there is a single common branch develop, and for each new feature, developers create a separate branch, commit to it, push, and when they want to merge their code into the develop branch, they open a pull request. To facilitate knowledge sharing and discuss approaches, we introduced code reviews, meaning colleagues must check and approve each other's code.

Ellenőrzések

A kódot más szemszögből nézni nagyszerű, de nem elég. Ezért automatikus ellenőrzéseket vezetünk be.

  • Első lépésként ellenőrizzük az ARC-összeállítást.
  • Sok Junit-teszt.
  • Számítjuk a code coverage-t, hiszen futtatjuk a teszteket.

Ahhoz, hogy megértsük, hogyan kellene futtatni ezeket az ellenőrzéseket, nézzük meg a fejlesztési folyamatot az Avitonál.

Sémájában ezt így lehet ábrázolni:

  • A fejlesztő a saját laptopján írja a kódot. Itt is futtathatók az integrációs ellenőrzések – vagy commit hook-kal, vagy egyszerűen a háttérben.
  • Miután a fejlesztő feltöltötte a kódot, megnyit egy pull request-t. Ahhoz, hogy a kódja bekerüljön a develop ágba, el kell végezni a code review-t és meg kell szerezni a szükséges mennyiségű megerősítést. Itt is lehetőség van az ellenőrzések és build-ek aktiválására: amíg az összes build nem sikeres, a pull request nem olvadhat be.
  • Miután a pull request beolvadt és a kód bekerült a develop-ba, el lehet választani egy megfelelő időpontot: például éjjel, amikor minden szerver szabad, és futtathatók az ellenőrzések, amennyiben szükséges.

A saját laptopon végzett ellenőrzéseket senki sem szerette. Amikor a fejlesztő befejezi a funkciót, gyorsan szeretné feltölteni és megnyitni a pull request-t. Ha ebben a pillanatban hosszabb ellenőrzések indulnak, az nemcsak kellemetlen, hanem lelassítja a fejlesztést is: míg a laptop valamit ellenőriz, nem lehet normálisan dolgozni rajta.

Nagyon tetszett az ellenőrzések éjszaki futtatása, mert sok idő és szerver áll rendelkezésre, úgyhogy teret adhatunk magunknak. De sajnos, amikor a funkció kódja bekerült a develop-ba, a fejlesztőnek már sokkal kevesebb motivációja van kijavítani azokat a hibákat, amelyeket a CI talált. Időnként észrevettem magamon, amikor a reggeli jelentésben a megtalált hibákra néztem, hogy később javítom meg őket, mert most a Jirában van egy szuper új feladat, amit nagyon szeretnék elkezdeni.

Ha az ellenőrzések blokkolják a pull request-et, akkor elegendő a motiváció, mert amíg a build-ek nem zöldülnek, a kód nem kerül be a develop-ba, így a feladat nem fejeződik be.

Végül egy olyan stratégiát választottunk, hogy éjjel a lehető legnagyobb ellenőrzéscsomagot futtatjuk, a legkritikusabb és leggyorsabb teszteket pedig a pull requestre indítjuk. De ezzel nem állunk meg — párhuzamosan optimalizáljuk az ellenőrzések átfutási sebességét, hogy át tudjuk vinni azokat az éjszakai üzemmódból a pull requestes ellenőrzésekbe.

Abban az időben minden buildünk viszonylag gyorsan ment, ezért egyszerűen csak aktiváltuk a pull request blokkolójaként az ARC buildet, a Junit-teszteket és a code coverage-t. Aktiváltuk, gondoltunk egyet — és lemondtunk a code coverage-ről, mert azt gondoltuk, hogy nincs rá szükségünk.

A alap CI beállítására két napot szántunk (itt és a továbbiakban az időbeli értékelés körülbelül, a léptékhez szükséges).

Ezután elkezdtünk tovább gondolkodni — vajon helyesen ellenőrizzük-e? Helyesen indítjuk-e a buildet pull requestnél?

A legutolsó commiton indítottuk a buildet arról a ágról, amelyből a pull request készült. De ennek a commitnak az ellenőrzése csak azt mutatja, hogy a fejlesztő által írt kód működik. De ez nem bizonyítja, hogy nem történt kár. Valójában a develop ág állapotát kell ellenőrizni azután, hogy a funkció be lett olvasztva.

A CI fejlődése a mobilfejlesztő csapatban

Ehhez írtunk egy egyszerű bash-skriptet premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Itt egyszerűen lehúzzuk a legfrissebb változtatásokat a develop-ból, és beolvasztjuk az aktuális ágba. Az összes build első lépéseként hozzáadtuk a premerge.sh skriptet, és elkezdtük ellenőrizni pontosan azt, amit szeretnénk, nevezetesen a integrációt.

A problémák lokalizálására, a megoldás keresésére és a skript megírására három napunk ment rá.

Az alkalmazás fejlődött, egyre több feladat jelentkezett, a csapat nőtt, és a premerge.sh néha kezdett minket cserben hagyni. A develop-ba konfliktáló változtatások kerültek be, amelyek összetörték a buildet.

Példa arra, hogyan történik ez:

A CI fejlődése a mobilfejlesztő csapatban

Két fejlesztő egyszerre elkezd dolgozni A és B funkciókon. Az A funkció fejlesztője felfedez egy nem használt funkciót a projektben, answer() és, mint jó cserkész, törli azt. Közben a B funkció fejlesztője az ő ágában új hívást ad hozzá ehhez a funkcióhoz.

A fejlesztők befejezik a munkát, és egyszerre indítják el a pull requestet. A build elindul, a premerge.sh ellenőrzi mindkét pull requestet a legfrissebb develop állapotához képest — minden ellenőrzés zöld. Ezt követően az A funkció pull requestje beolvad, majd a B funkció pull requestje is… Bumm! A develop összetörik, mert a develop kódban van egy nem létező funkcióhívás.

A CI fejlődése a mobilfejlesztő csapatban

Amikor a develop nem épül, az helyi katasztrófa. Az egész csapat nem tud semmit összeállítani és tesztelésre átadni.

Úgy alakult, hogy én főleg infrastrukturális feladatokkal foglalkoztam: analitika, hálózat, adatbázisok. Vagyis én írtam azokat a funkciókat és osztályokat, amelyeket más fejlesztők használnak. Emiatt nagyon gyakran kerültem hasonló helyzetekbe. Volt idő, amikor egy ilyen kép lógott a képernyőmön.

A CI fejlődése a mobilfejlesztő csapatban

Mivel ez nekünk nem volt megfelelő, elkezdtük kidolgozni a lehetőségeket, hogyan lehet ezt megelőzni.

Hogyan ne törjük össze a develop-ot

Az első lehetőség: újra kell építeni az összes pull requestet a develop frissítésekor. Ha a mi példánkban az A funkció pull requestje először kerül a develop-ra, akkor a B funkció pull requestje újraépül, és ennek megfelelően a tesztek nem fognak átmenni a fordítási hibák miatt.

Ahhoz, hogy megértsük, mennyi időt vesz ez igénybe, vegyünk egy példát két PR-ra. Megnyitunk két PR-t: két build, két tesztfuttatás. Miután az első PR-t beolvasztották a develop-ba, a másodikat újra kell építeni. Összességében két PR miatt háromszor futnak a tesztek: 2 + 1 = 3.

Alapvetően rendben van. De megnéztük a statisztikát, és a csapatunk tipikus helyzete 10 nyitott PR volt, akkor a tesztek száma a sorozatok összege: 10 + 9 + ... + 1 = 55. Tehát ahhoz, hogy 10 PR-t elfogadjunk, 55 alkalommal kell újraépíteni. És ez ideális helyzetben van, amikor minden teszt először átmegy, amikor senki sem nyit meg további pull requestet, míg ez a tíz feldolgozásra vár.

Képzelje el, hogy Ön egy fejlesztő, aki igyekszik elsőként rákattintani a „merge” gombra, mert ha ezt a szomszéd csinálja, akkor meg kell várni, amíg az összes építés újra átmegy... Nem, ez így nem megy, ez komolyan lelassítja a fejlesztést.

A második lehetséges mód: a pull requesteket a kódellenőrzés után építjük. Tehát megnyit egy pull requestet, összegyűjti a szükséges számú jóváhagyást a kollégáktól, javítja, amire szükséges, majd elindítja a build-eket. Ha azok sikeresek, a pull request összeolvad a develop-val. Ebben az esetben nincs további újraindítás, de jelentősen lelassul a visszajelzés. Fejlesztőként, amikor megnyitok egy pull requestet, azonnal látni szeretném, hogy összeáll-e. Például, ha egy teszt megbukik, azt gyorsan meg kell javítani. A halogatott építéssel lassul a visszajelzés, így az egész fejlesztés is.

Ennek eredményeként csak a harmadik lehetőség maradt — kerekíteniAz összes kódunk, minden forrásunk a Bitbucket szerveren tárolódik. Ennek megfelelően fejlesztenünk kellett egy plugint a Bitbuckethez.

A CI fejlődése a mobilfejlesztő csapatban

Ez a plugin átírja a pull requestek egyesítési mechanizmusát. A kezdeti lépések standardok: megnyílik a PR, elindulnak az összes build, és várja a kódellenőrzést. De miután a kódellenőrzés megtörtént, és a fejlesztő úgy dönt, hogy rákattint a "merge" gombra, a plugin ellenőrzi, hogy a vizsgálatokat milyen állapotú develop alapján futtatták. Ha a build után a develop frissült, a plugin nem engedi összevonni a pull requestet a fő ággal. Csak újraindítja a buildet a friss develop alapján.

A CI fejlődése a mobilfejlesztő csapatban

A konfliktusos változásokkal kapcsolatos példánkban az ilyen buildek nem fognak sikerülni a fordítási hiba miatt. Ennek megfelelően a B funkció fejlesztőjének ki kell javítania a kódot, újra kell indítania a vizsgálatokat, akkor a plugin automatikusan alkalmazni fogja a pull requestet.

A plugin bevezetése előtt átlagosan 2,7 vizsgálati indításunk volt egy pull requestre. A pluginnal 3,6 lett. Ez kielégítő volt számunkra.

Érdemes megjegyezni, hogy ennek a pluginnek van egy hátránya: csak egyszer indítja újra a buildet. Tehát még mindig van egy kis ablak, amin keresztül konfliktusos változások kerülhetnek a developba. De ennek a valószínűsége alacsony, és mi ezt a kompromisszumot kötöttük a futások számának és a hibásodás valószínűségének csökkentése érdekében. Két év alatt csak egyszer fordult elő, tehát valószínűleg nem hiába.

Az első verzió megírása a Bitbucket plugin számára két hétig tartott.

Új ellenőrzések

Közben a csapatunk folyamatosan nőtt. Új ellenőrzések kerültek bevezetésre.

Arra gondoltunk: miért javítsuk ki a hibákat, ha megelőzni is lehet őket? Ezért bevezettük a kód statikus elemzését. A lint használatával kezdtük, amely az Android SDK része. De akkoriban egyáltalán nem tudott működni a Kotlin kóddal, és a mi alkalmazásunk 75%-át már Kotlin nyelven írták. Ezért a linthez hozzáadtuk az integrált Android Studio ellenőrzéseit.

Ehhez eléggé kreatívnak kellett lennünk: az Android Studiót Dockerbe kellett csomagolnunk, és CI környezetben virtuális monitorral kellett futtatnunk, hogy azt higgye, hogy egy valódi laptopon fut. De működött.

Ezen a héten elkezdtünk sok instrumentációs tesztet írni, és bevezettük a képernyőkép tesztelést.. Ez az, amikor egy referencia képernyőképet generálnak egy külön kis nézethez, és a teszt abban áll, hogy a nézetről képernyőképet készítenek, és pixelről pixelre összehasonlítják a referenciával. Ha eltérés van, az azt jelenti, hogy valahol elcsúszott a layout vagy valami nem stimmel a stílusokkal.

De az instrumentation és képernyőképes teszteket eszközökön kell futtatni: emulátorokon vagy valódi eszközökön. Mivel sok teszt van, és gyakran futtatják őket, egész farmra van szükség. Saját farmot létrehozni túl munkaigényes, ezért találtunk egy kész megoldást - a Firebase Test Labot.

Firebase Test Lab

A Firebase-t választottuk, mert ez a Google terméke, tehát megbízhatónak kell lennie, és valószínűleg sosem szűnik meg. Az árak kedvezőek: 5 $ egy óra valódi eszköz használatért, 1 $ egy óra emulátor használatért.

A Firebase Test Lab integrálására a CI-nkben körülbelül három hét ment el.

De a csapat tovább nőtt, és sajnos a Firebase elkezdett minket cserbenhagyni. Akkoriban nem volt semmilyen SLA. Néha a Firebase megkövetelte, hogy várjunk, amíg felszabadul a szükséges számú eszköz a tesztekhez, és nem kezdte el azokat azonnal, ahogy azt szerettük volna. A várakozás akár fél óráig is eltartott, ami nagyon hosszú. Az instrumentation tesztek minden PR-nél futottak, a késlekedések nagyon lelassították a fejlesztést, aztán meg jött a havi számla egy kerek összeggel. Végül úgy döntöttünk, hogy lemondunk a Firebase-ről, és in-house fejlesztünk, mivel a csapat elég nagyra nőtt.

Docker + Python + bash

Docker-t használtunk, beletettük az emulátorokat, írtunk egy egyszerű programot Python-ban, ami a megfelelő időpontban elindítja a szükséges számú emulátort a megfelelő verzióban, amikor pedig le kell állítani őket. És persze, pár bash-script - hová is mennénk nélkülük?

A saját tesztkörnyezet létrehozása öt hetet vett igénybe.

Ennek eredményeként minden pull request-hez egy átfogó, az egyesülést blokkoló ellenőrzési lista tartozott:

  • ARK építés;
  • Junit-tesztek;
  • Lint;
  • Android Studio ellenőrzések;
  • Instrumentation tesztek;
  • Képernyőképes tesztek.

Ez sok lehetséges hiba megelőzését tette lehetővé. Technikailag minden jól működött, de a fejlesztők panaszkodtak, hogy túl hosszú ideig kell várniuk az eredményekre.

Túl hosszú - ez mennyi? Kibányásztuk az adatokat a Bitbucketből és a TeamCityből egy elemző rendszerbe, és rájöttünk, hogy az átlagos várakozási idő 45 perc. Vagyis a fejlesztő, amikor megnyit egy pull request-et, átlagosan 45 percet vár az építkezési eredményekre. Véleményem szerint ez nagyon sok, és így nem lehet dolgozni.

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

Gyorsítunk

Látva, hogy gyakran a buildjeink várakozási sorban állnak, először is bővítettük a hardverünket — az extenzív fejlesztés a legegyszerűbb. A buildjeink többé nem állnak a sorban, de a várakozási idő csak egy kicsit csökkent, mert egyes ellenőrzések maguk is nagyon hosszú ideig tartanak.

Eltávolítjuk a túl hosszú ellenőrzéseket

A Continuous Integration rendszerünk képes lenne észlelni az ilyen típusú hibákat és problémákat.

  • Nem épül fel. A CI észlelheti a fordítási hibát, amikor a konfliktusos módosítások miatt valami nem épül fel. Ahogy már mondtam, ilyenkor senki sem tud semmit összerakni, a fejlesztés megáll, és mindenki idegeskedik.
  • Hiba a viselkedésben. Például, amikor az alkalmazás felépül, de egy gomb megnyomásakor összeomlik, vagy a gomb egyáltalán nem működik. Ez rossz, mert egy ilyen hiba eljuthat a felhasználóhoz.
  • Hiba a dizájnban. Például, a gomb működik, de 10 pixelre elmozdult balra.
  • Növekvő technikai adósság.

Ezt a listát nézve rájöttünk, hogy az első két pont kritikus. Az ilyen problémákat szeretnénk elsőként észlelni. A dizájn-ellenőrzés során észlelt hibák könnyen javíthatók. A technikai adóssággal való munka külön folyamatot és tervezést igényel, ezért úgy döntöttünk, hogy nem ellenőrizzük a pull requestben.

Ebből a klasszifikációból kiindulva átnéztük az összes ellenőrzést. Kihúztuk a Lintrt és áthelyeztük az éjszakai futásra: csak hogy jelentést adjon arról, hány probléma van a projektben. A technikai adóssággal külön foglalkozunk, és az Android Studio ellenőrzéseiről teljesen lemondtunk. Az Android Studio Dockerben történő használata az ellenőrzésekhez érdekesnek tűnik, de sok kellemetlenséget okoz a támogatásban. Bármilyen frissítés az Android Studio verziójából egy harc a megmagyarázhatatlan hibákkal. Ugyanakkor a képernyőképes tesztek támogatása is nehézkes volt, mert a könyvtár nem működött túl stabilan, előfordultak hamis riasztások. A képernyőképes teszteket eltávolítottuk az ellenőrzések listájából.

Végül maradt nekünk:

  • ARK építés;
  • Junit-tesztek;
  • Instrumentation tesztek.

Gradle távoli gyorsítótár

Súlyos 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 gradle modulra volt bontva. Ilyen esetben a Gradle távoli gyorsítótár általában jól működik, és úgy döntöttünk, hogy kipróbáljuk.

A Gradle távoli gyorsítótár egy olyan szolgáltatás, amely képes tárolni a build-artifaktumokat különböző feladatokhoz különböző modulokban. A Gradle ahelyett, hogy valóban lefordítaná a kódot, HTTP-n keresztül megkeresi a távoli gyorsítótárat, és megkérdezi, hogy valaki már végrehajtotta-e ezt a feladatot. Ha igen, egyszerűen letölti az eredményt.

A Gradle távoli gyorsítótár elindítása könnyű, mert a Gradle Docker képet biztosít. Sikerült ezt megvalósítanunk három óra alatt.

Csak annyit kellett tennünk, hogy elindítjuk a Dockert, és beírunk egy sort a projektbe. De bár gyorsan elindítható, ahhoz, hogy jól működjön, elég sok időre van szükség.

Alább a cache hiányzásainak grafikonja.

A CI fejlődése a mobilfejlesztő csapatban

A legelső hónapban a cache hiányzások aránya körülbelül 65% volt. Három hét alatt ezt az értéket 20%-ra sikerült csökkenteni. Kiderült, hogy az Android alkalmazás által összegyűjtött feladatok furcsa tranzitív függőségekkel rendelkeznek, amelyek miatt a Gradle elszalasztotta a gyorsítótárt.

A gyorsítótár csatlakoztatásával nagymértékben felgyorsítottuk a buildet. De a build mellett még futnak az instrumentációs tesztek is, amelyek hosszú időt vesznek igénybe. Lehet, hogy nem kell minden tesztet futtatni minden egyes pull request során. Ennek a kiderítésére hatásvizsgálatot alkalmazunk.

Hatásvizsgálat

A pull requesten csinálunk egy git diff-et, és megtaláljuk a megváltozott Gradle modulokat.

A CI fejlődése a mobilfejlesztő csapatban

Csak azokat az instrumentációs teszteket érdemes futtatni, amelyek a megváltozott modulokat ellenőrzik, és minden olyan modult, amelytől függenek. A szomszédos modulok tesztjeit nem érdemes futtatni: ott a kód nem változott, és semmi sem tud elromlani.

Az instrumentációs tesztekkel nem olyan egyszerű a helyzet, mert ezeknek a legfelső modulban, az Application modulban kell lenniük. Heurisztikát alkalmaztunk a bytecode elemzésével, hogy megértsük, melyik modulhoz tartozik minden teszt.

Az instrumentációs tesztek munkájának modernizálása, hogy csak a használt modulokat ellenőrizzék, körülbelül nyolc hétig tartott.

A tesztellenőrzések felgyorsítása érdekében tett intézkedések sikeresen működtek. 45 percről körülbelül 15 percre csökkentettük az időt. Negyed óra várakozás már elfogadható a build során.

De most a fejlesztők elkezdtek panaszkodni, hogy nem világos számukra, mely build-ek futnak, hol nézhetik meg a logokat, miért piros a build, melyik teszt bukott el stb.

A CI fejlődése a mobilfejlesztő csapatban

A visszajelzési problémák lassítják a fejlesztést, ezért igyekeztünk a lehető legérthetőbb és részletesebb információt biztosítani minden PR-ről és buildről. Elkezdődött a Bitbucket PR kommentjeivel, amelyekben jeleztük, hogy melyik build hibázott és miért, és címzett üzeneteket írtunk a Slack-en. Végül létrehoztunk egy PR dashboardot, ahol minden aktuálisan futó build listája és azok állapota: várakozik, fut, hibás vagy befejeződött. Kattintható a build, és megnyithatók a naplói.

A CI fejlődése a mobilfejlesztő csapatban

A részletes visszajelzés elkészítésére hat hétig volt szükség.

Tervek

Térjünk át a legújabb történésekre. A visszajelzések rendezésével új szintre léptünk — úgy döntöttünk, hogy építünk egy emulator farmot. Amikor sok teszt és emulator van, nehéz őket kezelni. Végül minden emulatorunk k8s klaszterre költözött, rugalmas erőforrás-kezeléssel.

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

  • Lint visszaállítása (és más statikus elemzés). Már dolgozunk ebben az irányban.
  • Minden PR blokkoló alatt futtassuk az összes end-to-end tesztet az SDK minden verzióján.

Tehát nyomon követtük a folyamatos integráció fejlődését az Avito-nál. Most pedig szeretnék néhány tanácsot adni a tapasztalataink alapján.

Tanácsok

Ha csak egy tanácsot adhatnék, az ez lenne:

Kérlek, légy óvatos a shell szkriptekkel!

A Bash egy nagyon rugalmas és hatékony eszköz, amellyel nagyon gyorsan és kényelmesen lehet szkripteket írni. De csapdába lehet esni vele, és sajnos mi is beleestünk.

Minden egyszerű szkripttel kezdődött, amelyeket a build gépeinken futtattunk:

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

De mint tudjuk, minden idővel fejlődik és bonyolódik — indítsunk egy szkriptet a másikból, adjunk át valamilyen paramétert — végül meg kellett írni egy olyan funkciót, amely meghatározza, hogy milyen szintű a bash-beágyazás, ahol jelenleg tartunk, hogy a megfelelő idézőjeleket betehessük, hogy mindez elinduljon.

A CI fejlődése a mobilfejlesztő csapatban

El tudod képzelni az ilyen szkriptek fejlesztéséhez szükséges erőforrást. Azt tanácsolom, ne ess ebbe a csapdába.

Mivel lehet helyettesíteni?

  • Bármely szkriptnyelvvel. A Python vagy Kotlin Script használata kényelmesebb, mert ez programozás, nem szkriptek.
  • Vagy az összes build logikáját leírhatod Custom gradle tasks a projekted számára.

A második lehetőséget választottuk, és most fokozatosan eltávolítjuk az összes bash szkriptet, sok egyedi gradle feladatot írunk.

Tanács №2: tartsd az infrastruktúrát kód formájában.

Kényelmes, amikor a folyamatos integráció beállítása nem a Jenkins vagy TeamCity UI-jában, hanem szöveges fájlok formájában van a projekt tárolójában. Ez lehetővé teszi a verziókezelést. Nem nehéz visszagörgetni vagy kódot fordítani egy másik ágon.

A szkriptek a projektben tárolhatók. De mi legyen a környezettel?

3. tanács: a Docker segíthet a környezettel.

Az Android fejlesztőknek biztosan segít, az iOS esetében sajnos még nem.

Ez egy példa egy egyszerű docker fájlra, amely tartalmaz egy jdk-t és 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

# Töltse le az Android SDK-t
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

# Telepítse az Android Build Tool-t és könyvtárakat
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

Megírtam ezt a docker fájlt (titokban mondom, nem is muszáj megírni, elég, ha letölt egy kész verziót GitHub-ról), és a kép elkészítésével egy virtuális gépet kapsz, amelyen képes leszel az alkalmazás fordítására és Junit tesztek futtatására.

Két fő érv, amiért érdemes ezt megtenni: skálázhatóság és megismételhetőség. A docker használatával gyorsan felemelhetsz egy tucat építési ügynököt, amelyek pontosan ugyanazt a környezetet fogják birtokolni, mint korábban. Ez nagyon megkönnyíti a CI mérnökök életét. Az android-sdk dockerbe helyezése igazán egyszerű, az emulátorok viszont kicsit bonyolultabbak: kissé meg kell izzadni (vagy megint letöltheted a kész verziót GitHub-ról).

4. tanács: ne feledd, hogy a ellenőrzések nem a tesztek miatt történnek, hanem az emberekért.

A fejlesztőknek nagyon fontos a gyors és, ami a legfontosabb, világos visszajelzés: mi romlott el, melyik teszt bukott meg, hol nézhetik meg a build logot.

5. tanács: legyél pragmatikus a folyamatos integráció fejlesztésében.

Értsd meg világosan, milyen típusú hibákat szeretnél megelőzni, mennyit vagy kész költeni forrásokban, időben, gépi időben. A túl hosszú ellenőrzéseket például éjszakára pontosan el lehet halasztani. Az olyanoktól, amelyek nem igazán fontos hibákat észlelnek, pedig teljesen el lehet tekinteni.

6. tanács: használj kész eszközöket.

Jelenleg sok cég kínál felhő alapú CI-t.

A CI fejlődése a mobilfejlesztő csapatban

Kis csapatok számára ez egy jó megoldás. Nincs szükség semmilyen karbantartásra, csak fizess egy kicsit, építsd meg az alkalmazásodat és még futtathatsz teljesítményteszteket is.

7. tipp: nagyobb csapatnál érdemesebb házon belüli megoldásokat választani.

De előbb-utóbb, a csapat növekedésével, a házon belüli megoldások lesznek a kedvezőbbek. E megoldásokhoz viszont van egy megfontolandó tényező. A gazdaságban létezik a csökkenő megtérülés törvénye: bármely projekt esetében minden újabb fejlesztés egyre nehezebb, egyre nagyobb befektetést igényel.

A gazdaság minden életünket leírja, beleértve a Folyamatos Integrációt is. Készítettem egy grafikont a munkaerőigényről a Folyamatos Integráció fejlődésének minden szakaszában.

A CI fejlődése a mobilfejlesztő csapatban

Látható, hogy bármilyen fejlesztés egyre nehezebbé válik. E grafikon alapján könnyen megérthető, hogy a Folyamatos Integrációt a csapat méretének növekedésével összhangban kell fejleszteni. Két főből álló csapatnak körülbelül 50 napot eltölteni egy belső emulátor farm fejlesztésével – nem túl jó ötlet. De a nagy csapat számára sem jó megoldás, ha nem foglalkoznak a Folyamatos Integrációval, mert az integrációs problémákra, a kommunikáció javítására és egyebekre még több időt emészt fel.

Az automatizálásra azért volt szükség, mert az emberek drágák, hibáznak és lusták. De az automatizálást is emberek végzik. Ezért ugyanezek a problémák az automatizálásra is vonatkoznak.

  • Az automatizálás költséges. Emlékezz vissza a munkaerőigény grafikonra.
  • Automatizáláskor az emberek hibáznak.
  • Néha nagyon lusta az automatizálás, mert amúgy is jól működik minden. Miért kellene tovább javítani, miért mindez a Folyamatos Integráció?

De van egy statisztikám: a buildjeink 20%-ában hibák ütnek fel. Ez nem azért történik, mert a fejlesztőink rosszul írják a kódot. Azért történik, mert a fejlesztők biztosak abban, hogy ha hibát követnek el, az nem kerül a develop-ba, hanem az automatizált ellenőrzések elkapják. Ennek megfelelően a fejlesztők több időt tölthetnek a kód írásával és érdekes dolgokkal, nem pedig azzal, hogy helyben futtassanak valamit és ellenőrizzék.

Foglalkozz a Folyamatos Integrációval. De mértékkel.

Egyébként Nyikoláj Nyeztyerov nemcsak remek előadásokat tart, hanem a programbizottság tagja is, AppsConf és segít másoknak tartalmas előadásokat készíteni neked. A legutóbbi konferencia programjának teljességét és hasznosságát a menetrendben. A részletekért gyere el április 22-23-án az Infoprótérbe.

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster