Evoluimi i CI në ekipin e zhvillimit celular

Sot, shumica e produkteve softuerike zhvillohen në ekipe. Kushtet për zhvillimin e suksesshëm të ekipit mund të paraqiten në formën e një diagrami të thjeshtë.

Evoluimi i CI në ekipin e zhvillimit celular

Pasi të keni shkruar kodin tuaj, duhet të siguroheni që:

  1. Работает.
  2. Nuk prish asgjë, përfshirë kodin që kanë shkruar kolegët tuaj.

Nëse plotësohen të dyja kushtet, atëherë jeni në rrugën e suksesit. Për të kontrolluar lehtësisht këto kushte dhe për të mos devijuar nga rruga fitimprurëse, ne dolëm me Integrimin e Vazhdueshëm.

CI është një rrjedhë pune ku ju integroni kodin tuaj në kodin e përgjithshëm të produktit sa më shpesh që të jetë e mundur. Dhe ju jo vetëm që integroheni, por gjithashtu kontrolloni vazhdimisht që gjithçka po funksionon. Meqenëse duhet të kontrolloni shumë dhe shpesh, ia vlen të mendoni për automatizimin. Mund të kontrolloni gjithçka me dorë, por nuk duhet, dhe ja pse.

  • Njerëz të dashur. Një orë punë e çdo programuesi është më e shtrenjtë se një orë punë e çdo serveri.
  • Njerëzit bëjnë gabime. Prandaj, mund të lindin situata kur testet janë ekzekutuar në degën e gabuar ose është përpiluar kryerja e gabuar për testuesit.
  • Njerëzit janë dembelë. Herë pas here, kur mbaroj një detyrë, më lind mendimi: “Çfarë ka për të kontrolluar? Kam shkruar dy rreshta - gjithçka funksionon! Unë mendoj se disa prej jush gjithashtu ndonjëherë kanë mendime të tilla. Por gjithmonë duhet të kontrolloni.

Si u zbatua dhe u zhvillua Integrimi i vazhdueshëm në ekipin e zhvillimit celular Avito, si shkuan nga 0 në 450 ndërtime në ditë dhe se makinat e ndërtimit mblidhen 200 orë në ditë, thotë Nikolai Nesterov (nnesterov) është pjesëmarrës në të gjitha ndryshimet evolucionare të aplikacionit CI/CD Android.

Historia bazohet në shembullin e një komande Android, por shumica e qasjeve janë të zbatueshme edhe në iOS.


Një herë e një kohë, një person punonte në ekipin Avito Android. Sipas definicionit, atij nuk i duhej asgjë nga Integrimi i Vazhdueshëm: nuk kishte me kë të integrohej.

Por aplikacioni u rrit, u shfaqën gjithnjë e më shumë detyra të reja dhe ekipi u rrit në përputhje me rrethanat. Në një moment, është koha për të krijuar më zyrtarisht një proces integrimi të kodit. U vendos të përdorej Git flow.

Evoluimi i CI në ekipin e zhvillimit celular

Koncepti i Git flow është i njohur mirë: një projekt ka një degë të përbashkët të zhvillimit dhe për çdo veçori të re, zhvilluesit presin një degë të veçantë, angazhohen për të, shtyjnë dhe kur duan të bashkojnë kodin e tyre në degën e zhvillimit, hapin një kërkesë për tërheqje. Për të ndarë njohuritë dhe për të diskutuar qasjet, ne prezantuam rishikimin e kodit, domethënë, kolegët duhet të kontrollojnë dhe konfirmojnë kodin e njëri-tjetrit.

Çeqe

Të shohësh kodin me sytë e tu është e lezetshme, por jo e mjaftueshme. Prandaj, kontrollet automatike janë duke u futur.

  • Para së gjithash, ne kontrollojmë montim ARK.
  • Shumë prej tyre Testet e Junit.
  • Ne e konsiderojmë mbulimin e kodit, meqenëse jemi duke kryer teste.

Për të kuptuar se si duhet të kryhen këto kontrolle, le të shohim procesin e zhvillimit në Avito.

Mund të paraqitet skematikisht si kjo:

  • Një zhvillues shkruan kodin në laptopin e tij. Ju mund të kryeni kontrollet e integrimit pikërisht këtu - ose me një fiksim, ose thjesht ekzekutoni kontrollet në sfond.
  • Pasi zhvilluesi të ketë shtyrë kodin, ai hap një kërkesë për tërheqje. Në mënyrë që kodi i tij të përfshihet në degën e zhvillimit, është e nevojshme të kaloni një rishikim të kodit dhe të mblidhni numrin e kërkuar të konfirmimeve. Këtu mund të aktivizoni kontrollet dhe ndërtimet: derisa të gjitha ndërtimet të jenë të suksesshme, kërkesa për tërheqje nuk mund të bashkohet.
  • Pasi të bashkohet kërkesa për tërheqje dhe kodi të përfshihet në zhvillim, mund të zgjidhni një kohë të përshtatshme: për shembull, gjatë natës, kur të gjithë serverët janë të lirë dhe të kryeni sa më shumë kontrolle që dëshironi.

Askujt nuk i pëlqente të ekzekutonte skanimet në laptop. Kur një zhvillues ka përfunduar një veçori, ai dëshiron ta shtyjë shpejt atë dhe të hapë një kërkesë për tërheqje. Nëse në këtë moment nisin disa kontrolle të gjata, kjo jo vetëm që nuk është shumë e këndshme, por edhe ngadalëson zhvillimin: ndërsa laptopi po kontrollon diçka, është e pamundur të punosh normalisht në të.

Na pëlqyen shumë kontrollet gjatë natës, sepse ka shumë kohë dhe serverë, ju mund të bredhni përreth. Por, për fat të keq, kur kodi i veçorive hyn në zhvillim, zhvilluesi ka shumë më pak motivim për të rregulluar gabimet që gjeti CI. Në mënyrë periodike e kapja veten duke menduar kur shikoja të gjitha gabimet e gjetura në raportin e mëngjesit se do t'i rregulloja ato një ditë më vonë, sepse tani ka një detyrë të re fantastike në Jira që thjesht dua të filloj ta bëj.

Nëse kontrollet bllokojnë një kërkesë tërheqjeje, atëherë ka mjaft motivim, sepse derisa ndërtimet të bëhen jeshile, kodi nuk do të futet në zhvillim, që do të thotë se detyra nuk do të përfundojë.

Si rezultat, ne zgjodhëm strategjinë e mëposhtme: ne kryejmë grupin maksimal të mundshëm të kontrolleve gjatë natës dhe lëshojmë më kritikët prej tyre dhe, më e rëndësishmja, më të shpejtët në një kërkesë tërheqëse. Por ne nuk ndalemi këtu - paralelisht, ne optimizojmë shpejtësinë e kontrolleve në mënyrë që t'i transferojmë ato nga modaliteti i natës për të tërhequr kontrollet e kërkesave.

Në atë kohë, të gjitha ndërtimet tona përfunduan mjaft shpejt, kështu që ne thjesht përfshinim ndërtimin e ARK-së, testet e Junit dhe llogaritjet e mbulimit të kodit si një bllokues për kërkesën për tërheqje. Ne e ndezëm, menduam për të dhe braktisëm mbulimin e kodit sepse menduam se nuk kishim nevojë për të.

Na u deshën dy ditë për të vendosur plotësisht CI bazë (në tekstin e mëtejmë vlerësimi i kohës është i përafërt, i nevojshëm për shkallë).

Pas kësaj, filluam të mendojmë më tej - a po kontrollojmë edhe saktë? A po i ekzekutojmë saktë kërkesat për tërheqje?

Ne filluam ndërtimin në lidhjen e fundit të degës nga e cila u hap kërkesa për tërheqje. Por testet e këtij angazhimi mund të tregojnë vetëm se kodi që ka shkruar zhvilluesi funksionon. Por ata nuk vërtetojnë se ai nuk ka thyer asgjë. Në fakt, ju duhet të kontrolloni gjendjen e degës së zhvillimit pasi një veçori është bashkuar në të.

Evoluimi i CI në ekipin e zhvillimit celular

Për ta bërë këtë, ne kemi shkruar një skenar të thjeshtë bash premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Këtu të gjitha ndryshimet e fundit nga zhvillimi thjesht tërhiqen dhe shkrihen në degën aktuale. Ne shtuam skriptin premerge.sh si hapin e parë në të gjitha ndërtimet dhe filluam të kontrollonim saktësisht atë që duam, d.m.th. integrimin.

U deshën tre ditë për të lokalizuar problemin, për të gjetur një zgjidhje dhe për të shkruar këtë skenar.

Aplikacioni u zhvillua, gjithnjë e më shumë detyra u shfaqën, ekipi u rrit dhe premerge.sh ndonjëherë filloi të na zhgënjejë. Develop pati ndryshime kontradiktore që prishën ndërtimin.

Një shembull se si ndodh kjo:

Evoluimi i CI në ekipin e zhvillimit celular

Dy zhvillues fillojnë të punojnë njëkohësisht në veçoritë A dhe B. Zhvilluesi i veçorisë A zbulon një veçori të papërdorur në projekt answer() dhe, si një skaut i mirë, e heq atë. Në të njëjtën kohë, zhvilluesi i veçorisë B shton një thirrje të re në këtë funksion në degën e tij.

Zhvilluesit përfundojnë punën e tyre dhe hapin një kërkesë tërheqjeje në të njëjtën kohë. Ndërtimet janë nisur, premerge.sh kontrollon të dyja kërkesat e tërheqjes në lidhje me gjendjen e fundit të zhvillimit - të gjitha kontrollet janë të gjelbra. Pas kësaj, shkrihet kërkesa për tërheqje e veçorisë A, shkrihet kërkesa për tërheqje e veçorisë B... Boom! Zhvilloni ndërprerje sepse kodi i zhvillimit përmban një thirrje për një funksion që nuk ekziston.

Evoluimi i CI në ekipin e zhvillimit celular

Kur nuk do të zhvillohet, është fatkeqësi lokale. I gjithë ekipi nuk mund të mbledhë asgjë dhe ta dorëzojë atë për testim.

Kështu ndodhi që më shpesh punoja në detyrat e infrastrukturës: analitikë, rrjet, baza të të dhënave. Kjo do të thotë, isha unë që shkrova ato funksione dhe klasa që përdorin zhvilluesit e tjerë. Për shkak të kësaj, e gjeja veten shumë shpesh në situata të ngjashme. Madje këtë foto e kisha të varur për një kohë.

Evoluimi i CI në ekipin e zhvillimit celular

Meqenëse kjo nuk na përshtatej, filluam të shqyrtojmë opsionet se si ta parandalojmë këtë.

Si të mos thyeni zhvilloni

Opsioni i parë: rindërtoni të gjitha kërkesat për tërheqje kur zhvillohen përditësimet. Nëse, në shembullin tonë, kërkesa për tërheqje me veçorinë A është e para që përfshihet në zhvillim, kërkesa për tërheqje e veçorisë B do të rindërtohet dhe, në përputhje me rrethanat, kontrollet do të dështojnë për shkak të një gabimi përpilimi.

Për të kuptuar se sa kohë do të zgjasë kjo, merrni parasysh një shembull me dy PR. Ne hapim dy PR: dy ndërtime, dy kontrolle. Pasi PR-ja e parë të shkrihet në zhvillim, e dyta duhet të rindërtohet. Në total, dy PR kërkojnë tre kontrolle: 2 + 1 = 3.

Në parim, është mirë. Por ne shikuam statistikat dhe situata tipike në ekipin tonë ishte 10 PR të hapura, dhe më pas numri i kontrolleve është shuma e progresionit: 10 + 9 +... + 1 = 55. Kjo do të thotë, të pranosh 10 PR, ju duhet të rindërtoni 55 herë. Dhe kjo është në një situatë ideale, kur të gjitha kontrollet kalojnë herën e parë, kur askush nuk hap një kërkesë shtesë për tërheqje ndërsa këto dhjetëra janë duke u përpunuar.

Imagjinoni veten si një zhvillues që duhet të jetë i pari që do të klikojë në butonin "shkrij", sepse nëse një fqinj e bën këtë, atëherë do të duhet të prisni derisa të gjitha ndërtimet të kalojnë përsëri... Jo, kjo nuk do të funksionojë , do të ngadalësojë seriozisht zhvillimin.

Mënyra e dytë e mundshme: mbledhja e kërkesave për tërheqje pas rishikimit të kodit. Kjo do të thotë, ju hapni një kërkesë tërheqëse, mblidhni numrin e kërkuar të miratimeve nga kolegët, korrigjoni atë që nevojitet dhe më pas nisni ndërtimet. Nëse ato janë të suksesshme, kërkesa për tërheqje bashkohet në zhvillim. Në këtë rast, nuk ka rinisje shtesë, por reagimet ngadalësohen shumë. Si zhvillues, kur hap një kërkesë për tërheqje, menjëherë dua të shoh nëse do të funksionojë. Për shembull, nëse një test dështon, duhet ta rregulloni shpejt. Në rastin e një ndërtimi të vonuar, reagimet ngadalësohen, dhe për këtë arsye i gjithë zhvillimi. As kjo nuk na shkonte.

Si rezultat, mbeti vetëm opsioni i tretë - çiklizmit. I gjithë kodi ynë, të gjitha burimet tona ruhen në një depo në serverin Bitbucket. Prandaj, ne duhej të zhvillonim një shtojcë për Bitbucket.

Evoluimi i CI në ekipin e zhvillimit celular

Kjo shtojcë anashkalon mekanizmin e bashkimit të kërkesës për tërheqje. Fillimi është standard: PR hapet, të gjitha asambletë janë nisur, rishikimi i kodit ka përfunduar. Por pasi të përfundojë rishikimi i kodit dhe zhvilluesi vendos të klikojë në "bashkim", shtojca kontrollon në cilën gjendje zhvillimi janë ekzekutuar kontrollet. Nëse zhvillimi është përditësuar pas ndërtimeve, shtojca nuk do të lejojë që një kërkesë e tillë tërheqëse të shkrihet në degën kryesore. Thjesht do të rifillojë ndërtimet e një zhvillimi relativisht të fundit.

Evoluimi i CI në ekipin e zhvillimit celular

Në shembullin tonë me ndryshime kontradiktore, ndërtime të tilla do të dështojnë për shkak të një gabimi përpilimi. Prandaj, zhvilluesi i veçorisë B do të duhet të korrigjojë kodin, të rifillojë kontrollet, më pas shtojca do të aplikojë automatikisht kërkesën për tërheqje.

Përpara zbatimit të kësaj shtojce, ne kemi mesatarisht 2,7 ekzekutime rishikimi për kërkesë tërheqjeje. Me shtojcën kishte 3,6 lëshime. Kjo na përshtatej.

Vlen të përmendet se kjo shtojcë ka një pengesë: rifillon ndërtimin vetëm një herë. Kjo do të thotë, ekziston ende një dritare e vogël përmes së cilës mund të zhvillohen ndryshime kontradiktore. Por gjasat për këtë janë të ulëta, dhe ne e bëmë këtë shkëmbim midis numrit të fillimeve dhe gjasave për dështim. Në dy vjet ka qëlluar vetëm një herë, kështu që ndoshta nuk ka qenë e kotë.

Na u deshën dy javë për të shkruar versionin e parë të shtojcës Bitbucket.

Kontrolle të reja

Ndërkohë, ekipi ynë vazhdoi të rritej. Janë shtuar kontrolle të reja.

Ne menduam: pse të bëjmë gabime nëse ato mund të parandalohen? Dhe kjo është arsyeja pse ata e zbatuan analiza e kodit statik. Filluam me lint, i cili përfshihet në Android SDK. Por në atë kohë ai nuk dinte të punonte fare me kodin Kotlin dhe ne kishim tashmë 75% të aplikacionit të shkruar në Kotlin. Prandaj, ato të integruara u shtuan në garzë Kontrollet e Android Studio.

Për ta bërë këtë, na u desh të bënim shumë çoroditje: të merrnim Android Studio, ta paketoni në Docker dhe ta ekzekutoni në CI me një monitor virtual, në mënyrë që të mendonte se po funksionon në një laptop të vërtetë. Por funksionoi.

Gjithashtu gjatë kësaj kohe filluam të shkruanim shumë testet e instrumenteve dhe zbatohet testimi i pamjes së ekranit. Kjo ndodh kur krijohet një pamje referimi e ekranit për një pamje të vogël të veçantë dhe testi konsiston në marrjen e një pamjeje ekrani nga pamja dhe krahasimin e saj me standardin direkt pixel pas piksel. Nëse ka një mospërputhje, do të thotë që faqosja ka gabuar diku ose diçka nuk është në rregull në stilet.

Por testet e instrumenteve dhe testet e pamjeve të ekranit duhet të kryhen në pajisje: në emulatorë ose në pajisje reale. Duke qenë se ka shumë teste dhe kryhen shpesh, nevojitet një fermë e tërë. Fillimi i fermës tuaj kërkon shumë punë intensive, kështu që gjetëm një opsion të gatshëm - Firebase Test Lab.

Firebase Test Lab

Ai u zgjodh sepse Firebase është një produkt i Google, që do të thotë se duhet të jetë i besueshëm dhe nuk ka gjasa të vdesë ndonjëherë. Çmimet janë të arsyeshme: 5 dollarë për orë funksionimi të një pajisjeje reale, 1 dollarë për orë funksionimi i një emulatori.

U deshën rreth tre javë për të implementuar Firebase Test Lab në CI tonë.

Por ekipi vazhdoi të rritet dhe Firebase, për fat të keq, filloi të na zhgënjejë. Në atë kohë, ai nuk kishte asnjë SLA. Ndonjëherë Firebase na bënte të prisnim derisa numri i kërkuar i pajisjeve të ishte i lirë për teste dhe nuk fillonte t'i ekzekutonte ato menjëherë, siç dëshironim. Pritja në radhë zgjati deri në gjysmë ore, që është një kohë shumë e gjatë. Testet e instrumenteve u kryen në çdo PR, vonesat me të vërtetë ngadalësuan zhvillimin dhe më pas fatura mujore erdhi me një shumë të rrumbullakët. Në përgjithësi, u vendos që të braktisej Firebase dhe të punonte brenda, pasi ekipi ishte rritur mjaftueshëm.

Docker + Python + bash

Ne morëm Docker, futëm emulatorë në të, shkruam një program të thjeshtë në Python, i cili në momentin e duhur fillon numrin e kërkuar të emulatorëve në versionin e duhur dhe i ndalon ato kur është e nevojshme. Dhe, sigurisht, disa skripta bash - ku do të ishim pa to?

U deshën pesë javë për të krijuar mjedisin tonë të testimit.

Si rezultat, për çdo kërkesë tërheqjeje kishte një listë të gjerë kontrollesh të bllokimit të bashkimit:

  • montim ARK;
  • Junit teste;
  • Garzë;
  • Kontrollet e Android Studio;
  • Testet e instrumenteve;
  • Testet e pamjes së ekranit.

Kjo parandaloi shumë prishje të mundshme. Teknikisht gjithçka funksionoi, por zhvilluesit u ankuan se pritja për rezultate ishte shumë e gjatë.

Sa kohë është shumë e gjatë? Ne ngarkuam të dhëna nga Bitbucket dhe TeamCity në sistemin e analizës dhe e kuptuam këtë koha mesatare e pritjes 45 minuta. Kjo do të thotë, një zhvillues, kur hap një kërkesë për tërheqje, pret mesatarisht 45 minuta për rezultatet e ndërtimit. Sipas mendimit tim, kjo është shumë, dhe nuk mund të punosh kështu.

Sigurisht, ne vendosëm të shpejtojmë të gjitha ndërtimet tona.

Le të shpejtojmë

Duke parë që ndërtimet shpesh qëndrojnë në radhë, gjëja e parë që bëjmë është bleu më shumë pajisje — zhvillimi i gjerë është më i thjeshti. Ndërtesat pushuan së radhitur, por koha e pritjes u ul vetëm pak, sepse vetë disa kontrolle morën një kohë shumë të gjatë.

Heqja e kontrolleve që zgjasin shumë

Integrimi ynë i vazhdueshëm mund të kapë këto lloj gabimesh dhe problemesh.

  • Nuk do të. CI mund të kapë një gabim përpilimi kur diçka nuk ndërtohet për shkak të ndryshimeve kontradiktore. Siç thashë tashmë, atëherë askush nuk mund të mbledhë asgjë, zhvillimi ndalet dhe të gjithë nervozohen.
  • Bug në sjellje. Për shembull, kur aplikacioni është ndërtuar, por rrëzohet kur shtypni një buton, ose butoni nuk shtypet fare. Kjo është e keqe sepse një gabim i tillë mund të arrijë te përdoruesi.
  • Bug në paraqitjen. Për shembull, një buton është klikuar, por ka lëvizur 10 piksel në të majtë.
  • Rritja e borxhit teknik.

Pasi shikuam këtë listë, kuptuam se vetëm dy pikat e para janë kritike. Ne duam që së pari të kapim probleme të tilla. Gabimet në paraqitjen zbulohen në fazën e rishikimit të projektimit dhe mund të korrigjohen lehtësisht më pas. Ballafaqimi me borxhin teknik kërkon një proces dhe planifikim të veçantë, kështu që vendosëm të mos e testonim atë me një kërkesë tërheqëse.

Bazuar në këtë klasifikim, ne shkundëm të gjithë listën e çeqeve. Kryqëzuar Lint dhe e shtyu nisjen e tij brenda natës: vetëm që të prodhonte një raport se sa probleme kishte në projekt. Ne ramë dakord të punojmë veçmas me borxhin teknik, dhe Kontrollet e Android Studio u braktisën plotësisht. Android Studio në Docker për kryerjen e inspektimeve tingëllon interesante, por shkakton shumë probleme në mbështetje. Çdo përditësim në versionet e Android Studio do të thotë një luftë me gabime të pakuptueshme. Ishte gjithashtu e vështirë të mbështeteshin testet e pamjeve të ekranit, sepse biblioteka nuk ishte shumë e qëndrueshme dhe kishte rezultate false. Testet e pamjes së ekranit janë hequr nga lista e kontrollit.

Si rezultat, ne mbetëm me:

  • montim ARK;
  • Junit teste;
  • Testet e instrumenteve.

Gradle cache në distancë

Pa kontrolle të rënda, gjithçka u bë më mirë. Por nuk ka kufi për përsosmërinë!

Aplikacioni ynë tashmë ishte i ndarë në rreth 150 module të shkallës. Cache e largët e Gradle zakonisht funksionon mirë në këtë rast, kështu që vendosëm ta provonim.

Memoria e largët e Gradle është një shërbim që mund të ruajë objektet e ndërtimit për detyra individuale në module individuale. Gradle, në vend që të përpilojë kodin, përdor HTTP për të trokitur në cache në distancë dhe për të pyetur nëse dikush e ka kryer tashmë këtë detyrë. Nëse po, ai thjesht shkarkon rezultatin.

Ekzekutimi i cache-it në distancë të Gradle është i lehtë sepse Gradle ofron një imazh Docker. Ne arritëm ta bënim këtë për tre orë.

E tëra çfarë ju duhej të bënit ishte të nisni Docker dhe të shkruani një rresht në projekt. Por megjithëse mund të lansohet shpejt, do të duhet mjaft kohë që gjithçka të funksionojë mirë.

Më poshtë është grafiku i mungesës së cache-it.

Evoluimi i CI në ekipin e zhvillimit celular

Në fillim, përqindja e humbjeve të cache ishte rreth 65. Pas tre javësh, arritëm ta rrisim këtë vlerë në 20%. Doli se detyrat që mbledh aplikacioni Android kanë varësi të çuditshme kalimtare, për shkak të të cilave Gradle humbi cache.

Duke lidhur cache-in, ne e përshpejtuam shumë ndërtimin. Por përveç montimit, ka edhe teste instrumentale, dhe ato kërkojnë shumë kohë. Ndoshta jo të gjitha testet duhet të kryhen për çdo kërkesë tërheqjeje. Për ta zbuluar, ne përdorim analizën e ndikimit.

Analiza e ndikimit

Me një kërkesë tërheqëse, ne mbledhim git diff dhe gjejmë modulet e modifikuara Gradle.

Evoluimi i CI në ekipin e zhvillimit celular

Ka kuptim të kryhen vetëm teste instrumentesh që kontrollojnë modulet e ndryshuara dhe të gjitha modulet që varen prej tyre. Nuk ka asnjë pikë në ekzekutimin e testeve për modulet fqinje: kodi atje nuk ka ndryshuar dhe asgjë nuk mund të prishet.

Testet e instrumenteve nuk janë aq të thjeshta, sepse ato duhet të vendosen në modulin e aplikacionit të nivelit të lartë. Ne përdorëm heuristikën me analizën e bytekodit për të kuptuar se cilit modul i përket secili test.

Përmirësimi i funksionimit të testeve të instrumenteve në mënyrë që ato të testojnë vetëm modulet e përfshira zgjati rreth tetë javë.

Masat për përshpejtimin e inspektimeve kanë funksionuar me sukses. Nga 45 minuta u ngjitëm në rreth 15. Tashmë është normale të presësh një çerek ore për një ndërtim.

Por tani zhvilluesit kanë filluar të ankohen se nuk e kuptojnë se cilat ndërtime po lansohen, ku të shohin regjistrin, pse ndërtimi është i kuq, cili test dështoi, etj.

Evoluimi i CI në ekipin e zhvillimit celular

Problemet me reagimet ngadalësojnë zhvillimin, kështu që ne u përpoqëm të ofrojmë informacion sa më të qartë dhe të detajuar për çdo PR dhe ndërtim. Ne filluam me komente në Bitbucket për PR, duke treguar se cili ndërtim kishte dështuar dhe pse, dhe shkruam mesazhe të synuara në Slack. Në fund, ne krijuam një panel PR për faqen me një listë të të gjitha ndërtimeve që po ekzekutohen aktualisht dhe statusin e tyre: në radhë, në ekzekutim, të rrëzuar ose të përfunduar. Mund të klikoni mbi ndërtimin dhe të shkoni te regjistri i tij.

Evoluimi i CI në ekipin e zhvillimit celular

Gjashtë javë u shpenzuan për reagime të hollësishme.

Planet

Le të kalojmë në historinë më të re. Pasi zgjidhëm çështjen e reagimeve, arritëm në një nivel të ri - vendosëm të ndërtonim fermën tonë të emulatorëve. Kur ka shumë teste dhe emulatorë, ato janë të vështira për t'u menaxhuar. Si rezultat, të gjithë emulatorët tanë u zhvendosën në grupin k8s me menaxhim fleksibël të burimeve.

Përveç kësaj, ka plane të tjera.

  • Kthehu Lint (dhe analiza të tjera statike). Tashmë jemi duke punuar në këtë drejtim.
  • Drejtoni gjithçka në një bllokues PR teste nga fundi në fund në të gjitha versionet SDK.

Pra, ne kemi gjurmuar historinë e zhvillimit të Integrimit të Vazhdueshëm në Avito. Tani dua të jap disa këshilla nga një këndvështrim me përvojë.

Советы

Nëse do të mund të jepja vetëm një këshillë do të ishte kjo:

Ju lutemi kini kujdes me skriptet shell!

Bash është një mjet shumë fleksibël dhe i fuqishëm, është shumë i përshtatshëm dhe i shpejtë për të shkruar skripta. Por ju mund të bini në një kurth me të, dhe, për fat të keq, ne ramë në të.

Gjithçka filloi me skriptet e thjeshta që funksionuan në makinat tona të ndërtimit:

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

Por, siç e dini, gjithçka zhvillohet dhe bëhet më e ndërlikuar me kalimin e kohës - le të ekzekutojmë një skenar nga një tjetër, le të kalojmë disa parametra atje - në fund na duhej të shkruanim një funksion që përcakton se në çfarë niveli të foleve bash jemi tani në rregull për të futur thonjëzat e nevojshme, për të filluar gjithçka.

Evoluimi i CI në ekipin e zhvillimit celular

Ju mund të imagjinoni kostot e punës për zhvillimin e skenarëve të tillë. Unë ju këshilloj të mos bini në këtë kurth.

Çfarë mund të zëvendësohet?

  • Çdo gjuhë skriptimi. Shkruani në Python ose Kotlin Script më i përshtatshëm sepse është programim, jo ​​skript.
  • Ose përshkruani të gjithë logjikën e ndërtimit në formë Detyra me shkallë të personalizuar për projektin tuaj.

Ne vendosëm të zgjedhim opsionin e dytë dhe tani po fshijmë sistematikisht të gjitha skriptet bash dhe po shkruajmë shumë detyra të personalizuara të shkallës.

Këshillë #2: Ruani infrastrukturën në kod.

Është i përshtatshëm kur cilësimi i Integrimit të Vazhdueshëm nuk ruhet në ndërfaqen UI të Jenkins ose TeamCity, etj., por në formën e skedarëve të tekstit direkt në depon e projektit. Kjo jep versionueshmërinë. Nuk do të jetë e vështirë të rikthehet ose të ndërtohet kodi në një degë tjetër.

Skriptet mund të ruhen në një projekt. Çfarë duhet bërë me mjedisin?

Këshilla #3: Docker mund të ndihmojë me mjedisin.

Padyshim që do të ndihmojë zhvilluesit e Android; iOS nuk e ka ende një të tillë, për fat të keq.

Ky është një shembull i një skedari të thjeshtë docker që përmban jdk dhe 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

Pasi të keni shkruar këtë skedar Docker (do t'ju them një sekret, nuk keni pse ta shkruani, por thjesht tërhiqeni gati nga GitHub) dhe të keni montuar imazhin, ju merrni një makinë virtuale mbi të cilën mund të ndërtoni aplikacionin dhe kryeni testet e Junit.

Dy arsyet kryesore pse kjo ka kuptim janë shkallëzueshmëria dhe përsëritshmëria. Duke përdorur docker, ju mund të krijoni shpejt një duzinë agjentësh ndërtimi që do të kenë saktësisht të njëjtin mjedis si ai i mëparshmi. Kjo e bën jetën e inxhinierëve CI shumë më të lehtë. Është mjaft e lehtë për të futur android-sdk në docker, por me emulatorët është pak më e vështirë: do të duhet të punoni pak më shumë (ose të shkarkoni përsëri të përfunduarin nga GitHub).

Këshilla nr 4: mos harroni se inspektimet nuk bëhen për hir të inspektimeve, por për njerëzit.

Reagimet e shpejta dhe, më e rëndësishmja, të qarta janë shumë të rëndësishme për zhvilluesit: çfarë u prish, çfarë testi dështoi, ku mund ta shoh buildlog-in.

Këshilla #5: Jini pragmatikë kur zhvilloni Integrim të Vazhdueshëm.

Kuptoni qartë se çfarë lloj gabimesh dëshironi të parandaloni, sa burime, kohë dhe kohë kompjuteri jeni të gatshëm të shpenzoni. Kontrollet që zgjasin shumë, për shembull, mund të shtyhen brenda natës. Dhe ato prej tyre që kapin gabime jo shumë të rëndësishme duhet të braktisen plotësisht.

Këshilla # 6: Përdorni mjete të gatshme.

Tani ka shumë kompani që ofrojnë cloud CI.

Evoluimi i CI në ekipin e zhvillimit celular

Kjo është një zgjidhje e mirë për ekipet e vogla. Nuk keni nevojë të mbështesni asgjë, thjesht paguani pak para, ndërtoni aplikacionin tuaj dhe madje kryeni teste instrumentesh.

Këshilla #7: Në një ekip të madh, zgjidhjet e brendshme janë më fitimprurëse.

Por herët a vonë, ndërsa ekipi rritet, zgjidhjet e brendshme do të bëhen më fitimprurëse. Ka një problem me këto vendime. Ekziston një ligj i zvogëlimit të fitimeve në ekonomi: në çdo projekt, çdo përmirësim i mëvonshëm është gjithnjë e më i vështirë dhe kërkon gjithnjë e më shumë investime.

Ekonomia përshkruan të gjithë jetën tonë, duke përfshirë Integrimin e Vazhdueshëm. Kam ndërtuar një plan të kostove të punës për çdo fazë të zhvillimit të Integrimit tonë të Vazhdueshëm.

Evoluimi i CI në ekipin e zhvillimit celular

Është e qartë se çdo përmirësim po bëhet gjithnjë e më i vështirë. Duke parë këtë grafik, mund të kuptoni se Integrimi i Vazhdueshëm duhet të zhvillohet në përputhje me rritjen e madhësisë së ekipit. Për një ekip prej dy personash, shpenzimi i 50 ditëve për të zhvilluar një fermë të brendshme emulatorësh është një ide mediokre. Por në të njëjtën kohë, për një ekip të madh, të mos bësh fare Integrim të Vazhdueshëm është gjithashtu një ide e keqe, sepse problemet e integrimit, rregullimi i komunikimit etj. do të marrë edhe më shumë kohë.

E nisëm me idenë se nevojitet automatizimi sepse njerëzit janë të shtrenjtë, bëjnë gabime dhe dembelë. Por njerëzit gjithashtu automatizojnë. Prandaj, të gjitha të njëjtat probleme vlejnë për automatizimin.

  • Automatizimi është i shtrenjtë. Mbani mend orarin e punës.
  • Kur bëhet fjalë për automatizimin, njerëzit bëjnë gabime.
  • Ndonjëherë është shumë dembel të automatizosh, sepse gjithçka funksionon në atë mënyrë. Pse të përmirësohet diçka tjetër, pse gjithë ky Integrim i Vazhdueshëm?

Por unë kam statistika: gabimet kapen në 20% të asambleve. Dhe kjo nuk është për shkak se zhvilluesit tanë e shkruajnë kodin dobët. Kjo për shkak se zhvilluesit janë të sigurt se nëse bëjnë ndonjë gabim, ai nuk do të përfundojë në zhvillim, ai do të kapet nga kontrollet e automatizuara. Prandaj, zhvilluesit mund të shpenzojnë më shumë kohë duke shkruar kode dhe gjëra interesante, në vend që të ekzekutojnë dhe testojnë diçka në nivel lokal.

Praktikoni Integrimin e Vazhdueshëm. Por në moderim.

Nga rruga, Nikolai Nesterov jo vetëm që jep vetë raporte të shkëlqyera, por është edhe anëtar i komitetit të programit AppsConf dhe ndihmon të tjerët të përgatisin fjalime kuptimplote për ju. Plotësia dhe dobia e programit të konferencës së ardhshme mund të vlerësohet sipas temave në orarin. Dhe për detaje, ejani në Infospace në datat 22-23 Prill.

Burimi: www.habr.com

Shto një koment