Evoluo de CI en la movebla evolua teamo

Hodiaŭ, la plej multaj softvaraĵoj estas evoluigitaj en teamoj. La kondiĉoj por sukcesa teama evoluo povas esti reprezentitaj en la formo de simpla diagramo.

Evoluo de CI en la movebla evolua teamo

Post kiam vi skribis vian kodon, vi devas certigi ĝin:

  1. Verkoj.
  2. Ĝi ne rompas ion ajn, inkluzive de la kodo kiun viaj kolegoj skribis.

Se ambaŭ kondiĉoj estas plenumitaj, tiam vi estas sur la vojo al sukceso. Por facile kontroli ĉi tiujn kondiĉojn kaj ne devii de la profita vojo, ni elpensis Daŭran Integriĝon.

CI estas laborfluo, kie vi integras vian kodon en la ĝeneralan produktokodon kiel eble plej ofte. Kaj vi ne nur integriĝas, sed ankaŭ konstante kontrolas, ke ĉio funkcias. Ĉar vi devas kontroli multe kaj ofte, indas pensi pri aŭtomatigo. Vi povas kontroli ĉion permane, sed vi ne devus, kaj jen kial.

  • Karaj homoj. Horo da laboro de iu ajn programisto estas pli multekosta ol horo da laboro de iu ajn servilo.
  • Homoj faras erarojn. Tial, situacioj povas ekesti kiam testoj estis rulitaj sur la malĝusta branĉo aŭ la malĝusta kommit estis kompilita por testistoj.
  • Homoj estas maldiligentaj. De tempo al tempo, kiam mi finas taskon, ekestas la penso: “Kion estas por kontroli? Mi skribis du liniojn - ĉio funkcias! Mi pensas, ke kelkaj el vi ankaŭ foje havas tiajn pensojn. Sed vi ĉiam devus kontroli.

Kiel Daŭra Integriĝo estis efektivigita kaj evoluigita en la Avito movebla evoluiga teamo, kiel ili iris de 0 al 450 konstruoj tage, kaj tiuj konstrumaŝinoj kunvenas 200 horojn tage, diras Nikolai Nesterov (nnesterov) estas partoprenanto en ĉiuj evoluaj ŝanĝoj de la CI/CD Android-aplikaĵo.

La rakonto baziĝas sur la ekzemplo de Android-komando, sed la plej multaj el la aliroj aplikeblas ankaŭ en iOS.


Iam unu persono laboris en la Avito Android-teamo. Laŭdifine, li ne bezonis ion de Kontinua Integriĝo: estis neniu kun kiu integri.

Sed la aplikaĵo kreskis, pli kaj pli da novaj taskoj aperis, kaj la teamo kreskis laŭe. En iu momento, estas tempo pli formale establi kodan integrigan procezon. Estis decidite uzi Git-fluon.

Evoluo de CI en la movebla evolua teamo

La koncepto de Git-fluo estas konata: projekto havas unu komunan evolubranĉon, kaj por ĉiu nova funkcio, programistoj tranĉas apartan branĉon, engaĝiĝas al ĝi, puŝas, kaj kiam ili volas kunfandi sian kodon en la evolubranĉon, malfermas tiri peton. Por kunhavigi scion kaj diskuti alirojn, ni enkondukis kodan revizion, tio estas, kolegoj devas kontroli kaj konfirmi reciproke la kodon.

Ĉekoj

Vidi kodon per viaj okuloj estas mojose, sed ne sufiĉas. Tial, aŭtomataj kontroloj estas enkondukitaj.

  • Unue ni kontrolas ARK-asembleo.
  • Multe Junit-testoj.
  • Ni konsideras kodan kovradon, ĉar ni faras testojn.

Por kompreni kiel ĉi tiuj kontroloj devus esti rulitaj, ni rigardu la disvolvan procezon en Avito.

Ĝi povas esti reprezentita skeme tiel:

  • Programisto skribas kodon sur sia tekkomputilo. Vi povas fari integrigajn kontrolojn ĝuste ĉi tie - aŭ per kommithoko, aŭ simple fari kontrolojn en la fono.
  • Post kiam la programisto puŝis la kodon, li malfermas tirpeton. Por ke ĝia kodo estu inkluzivita en la evolubranĉo, necesas trapasi kodan revizion kaj kolekti la bezonatan nombron da konfirmoj. Vi povas ebligi kontrolojn kaj konstruojn ĉi tie: ĝis ĉiuj konstruoj estas sukcesaj, la tirpeto ne povas esti kunfandita.
  • Post kiam la tirpeto estas kunfandita kaj la kodo estas inkluzivita en disvolvi, vi povas elekti oportunan tempon: ekzemple nokte, kiam ĉiuj serviloj estas liberaj, kaj fari tiom da kontroloj kiom vi volas.

Neniu ŝatis ruli skanaĵojn sur sia tekokomputilo. Kiam programisto finis funkcion, li volas rapide puŝi ĝin kaj malfermi tiran peton. Se en ĉi tiu momento kelkaj longaj kontroloj estas lanĉitaj, tio ne nur estas ne tre agrabla, sed ankaŭ malrapidigas evoluon: dum la tekkomputilo kontrolas ion, estas neeble normale labori pri ĝi.

Ni tre ŝatis fari ĉekojn nokte, ĉar estas multe da tempo kaj serviloj, vi povas vagi ĉirkaŭe. Sed, bedaŭrinde, kiam la funkciokodo disvolvas, la programisto havas multe malpli da motivado ripari la erarojn kiujn CI trovis. Mi periode kaptis min pensante, kiam mi rigardis ĉiujn erarojn trovitajn en la matena raporto, ke mi korektos ilin iam poste, ĉar nun estas bonega nova tasko en Jira, kiun mi nur volas komenci fari.

Se ĉekoj blokas tiran peton, tiam estas sufiĉe da instigo, ĉar ĝis la konstruaĵoj verdiĝos, la kodo ne eniĝos disvolvi, kio signifas, ke la tasko ne estos finita.

Kiel rezulto, ni elektis la sekvan strategion: ni kuras la maksimuman eblan aron da ĉekoj nokte, kaj lanĉas la plej kritikajn el ili kaj, plej grave, la plej rapidajn je tira peto. Sed ni ne ĉesas tie — paralele, ni optimumigas la rapidecon de ĉekoj por translokigi ilin de nokta reĝimo por tiri petajn ĉekojn.

Tiutempe, ĉiuj niaj konstruoj estis kompletigitaj sufiĉe rapide, do ni simple inkluzivis la ARK-konstruon, Junit-testojn kaj kodajn kalkulojn kiel blokilon por la tirpeto. Ni ŝaltis ĝin, pensis pri ĝi kaj forlasis kodan kovradon ĉar ni pensis, ke ni ne bezonas ĝin.

Ni bezonis du tagojn por tute agordi la bazan CI (ĉi-poste la temptakso estas proksimuma, necesa por skalo).

Post tio, ni ekpensis plu - ĉu ni eĉ kontrolas ĝuste? Ĉu ni ĝuste rulas konstruojn sur tirpetoj?

Ni komencis la konstruon sur la lasta komito de la branĉo de kiu la tirpeto estis malfermita. Sed provoj de ĉi tiu kommit nur povas montri, ke la kodo, kiun la programisto skribis, funkcias. Sed ili ne pruvas, ke li nenion rompis. Fakte, vi devas kontroli la staton de la evolua branĉo post kiam funkcio estas kunfandita en ĝi.

Evoluo de CI en la movebla evolua teamo

Por fari tion, ni skribis simplan bash-skripton premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Ĉi tie ĉiuj lastaj ŝanĝoj de evolu estas simple tiritaj kaj kunfanditaj en la nunan branĉon. Ni aldonis la skripton premerge.sh kiel la unuan paŝon en ĉiuj konstruoj kaj komencis kontroli ĝuste kion ni volas, tio estas integriĝo.

Necesis tri tagoj por lokalizi la problemon, trovi solvon kaj skribi ĉi tiun skripton.

La aplikaĵo disvolviĝis, pli kaj pli da taskoj aperis, la teamo kreskis, kaj premerge.sh foje komencis lasi nin. Develop havis konfliktajn ŝanĝojn kiuj rompis la konstruon.

Ekzemplo de kiel tio okazas:

Evoluo de CI en la movebla evolua teamo

Du programistoj samtempe komencas labori pri funkcioj A kaj B. La programisto de trajto A malkovras neuzatan funkcion en la projekto answer() kaj, kiel bona skolto, forigas ĝin. Samtempe, la programisto de trajto B aldonas novan vokon al ĉi tiu funkcio en sia branĉo.

Programistoj finas sian laboron kaj malfermas tiran peton samtempe. La konstruaĵoj estas lanĉitaj, premerge.sh kontrolas ambaŭ tirajn petojn koncerne la plej novan evoluan staton - ĉiuj kontroloj estas verdaj. Post tio, la tirpeto de trajto A estas kunfandita, la tirpeto de trajto B estas kunfandita... Bum! Disvolvi paŭzoj ĉar la evolukodo enhavas alvokon al neekzistanta funkcio.

Evoluo de CI en la movebla evolua teamo

Kiam ĝi ne evoluos, ĝi estas loka katastrofo. La tuta teamo ne povas kolekti ion ajn kaj sendi ĝin por testado.

Okazis, ke mi plej ofte laboris pri infrastrukturaj taskoj: analizo, reto, datumbazoj. Tio estas, estis mi, kiu skribis tiujn funkciojn kaj klasojn, kiujn aliaj programistoj uzas. Pro tio mi tre ofte trovis min en similaj situacioj. Mi eĉ havis ĉi tiun bildon pendanta dum iom da tempo.

Evoluo de CI en la movebla evolua teamo

Ĉar ĉi tio ne konvenis al ni, ni komencis esplori eblojn pri kiel malhelpi tion.

Kiel ne rompi disvolvi

Unua opcio: rekonstrui ĉiujn tirpetojn kiam ĝisdatigo evoluas. Se, en nia ekzemplo, la tirpeto kun trajto A estas la unua inkludita en evolui, la tirpeto de trajto B estos rekonstruita, kaj, sekve, la ĉekoj malsukcesos pro kompila eraro.

Por kompreni kiom da tempo ĉi tio daŭros, konsideru ekzemplon kun du PR-oj. Ni malfermas du PR-ojn: du konstruojn, du ĉekojn. Post kiam la unua PR estas kunfandita en evolui, la dua devas esti rekonstruita. Entute, du PR postulas tri kontrolojn: 2 + 1 = 3.

Principe estas bone. Sed ni rigardis la statistikon, kaj la tipa situacio en nia teamo estis 10 malfermitaj PR-oj, kaj tiam la nombro da ĉekoj estas la sumo de la progresado: 10 + 9 +... + 1 = 55. Tio estas, akcepti 10. PRoj, vi devas rekonstrui 55 fojojn. Kaj ĉi tio estas en ideala situacio, kiam ĉiuj kontroloj pasas la unuan fojon, kiam neniu malfermas plian tiran peton dum ĉi tiuj dekduoj estas procesitaj.

Imagu vin kiel programisto, kiu devas esti la unua alklaki la butonon "kunfandi", ĉar se najbaro faras tion, tiam vi devos atendi ĝis ĉiuj konstruoj denove trapasos... Ne, tio ne funkcios. , ĝi serioze malrapidigos evoluon.

Dua ebla maniero: kolekti tirpetojn post koda revizio. Tio estas, vi malfermas tiran peton, kolektas la bezonatan nombron da aproboj de kolegoj, korektas tion, kion necesas, kaj poste lanĉas la konstruojn. Se ili sukcesas, la tirpeto estas kunfandita en evolui. En ĉi tiu kazo, ne estas aldonaj rekomencoj, sed la sugestoj tre malrapidiĝas. Kiel programisto, kiam mi malfermas tiran peton, mi tuj volas vidi ĉu ĝi funkcios. Ekzemple, se provo malsukcesas, vi devas rapide ripari ĝin. En la kazo de prokrastita konstruo, reagoj malrapidiĝas, kaj tial la tuta evoluo. Ankaŭ ĉi tio ne konvenis al ni.

Kiel rezulto, nur la tria opcio restis - biciklo. Nia tuta kodo, ĉiuj niaj fontoj estas konservitaj en deponejo sur la Bitbucket-servilo. Sekve, ni devis evoluigi kromprogramon por Bitbucket.

Evoluo de CI en la movebla evolua teamo

Ĉi tiu kromaĵo superregas la mekanismon por kunfandi tirpetojn. La komenco estas norma: la PR malfermiĝas, ĉiuj asembleoj estas lanĉitaj, koda revizio estas finita. Sed post kiam la koda revizio estas finita kaj la programisto decidas alklaki "kunfandi", la kromaĵo kontrolas kontraŭ kiu evolua stato la kontroloj estis rulitaj. Se disvolvi estis ĝisdatigita post la konstruoj, la kromaĵo ne permesos al tia tira peto esti kunfandita en la ĉefan branĉon. Ĝi simple rekomencos la konstruojn de relative lastatempa evoluado.

Evoluo de CI en la movebla evolua teamo

En nia ekzemplo kun konfliktantaj ŝanĝoj, tiaj konstruoj malsukcesos pro kompila eraro. Sekve, la programisto de funkcio B devos korekti la kodon, rekomenci la kontrolojn, tiam la kromaĵo aŭtomate aplikos la tiran peton.

Antaŭ ol efektivigi ĉi tiun kromprogramon, ni averaĝis 2,7 reviziajn kurojn per tira peto. Kun la kromaĵo estis 3,6 lanĉoj. Ĉi tio konvenis al ni.

Indas noti, ke ĉi tiu kromaĵo havas malavantaĝon: ĝi nur rekomencas la konstruon unufoje. Tio estas, ankoraŭ ekzistas malgranda fenestro tra kiu konfliktantaj ŝanĝoj povas eniri disvolviĝi. Sed la verŝajneco de ĉi tio estas malalta, kaj ni faris ĉi tiun kompromison inter la nombro da komencoj kaj la verŝajneco de fiasko. En du jaroj ĝi pafis nur unufoje, do verŝajne ne vane.

Ni bezonis du semajnojn por skribi la unuan version de la kromaĵo Bitbucket.

Novaj ĉekoj

Dume nia teamo daŭre kreskis. Novaj ĉekoj estis aldonitaj.

Ni pensis: kial fari erarojn, se oni povas ilin malhelpi? Kaj tial ili efektivigis statika kodanalizo. Ni komencis kun lint, kiu estas inkluzivita en la Android SDK. Sed tiutempe li tute ne sciis kiel labori kun Kotlin-kodo, kaj ni jam havis 75% de la aplikaĵo skribita en Kotlin. Tial, enkonstruitaj oni aldonis al lint Android Studio kontrolas.

Por fari tion, ni devis fari multajn perversajn: preni Android Studion, paki ĝin en Docker kaj ruli ĝin sur CI per virtuala monitoro, por ke ĝi pensu, ke ĝi funkcias sur vera tekokomputilo. Sed ĝi funkciis.

Estis ankaŭ dum ĉi tiu tempo ke ni komencis verki multe instrumentaj provoj kaj efektivigita provado de ekrankopio. Jen kiam referenca ekrankopio estas generita por aparta malgranda vido, kaj la testo konsistas el preni ekrankopio de la vido kaj kompari ĝin kun la norma rekte pikselo post pikselo. Se estas diferenco, tio signifas, ke la aranĝo ie misfunkciis aŭ io misas en la stiloj.

Sed instrumentaj testoj kaj ekrankopaj testoj devas esti rulitaj sur aparatoj: sur emuliloj aŭ sur realaj aparatoj. Konsiderante, ke estas multaj testoj kaj ili estas oftaj, necesas tuta bieno. Lanĉi vian propran bienon estas tro laborforta, do ni trovis pretan opcion - Firebase Test Lab.

Firebase Testa Laboratorio

Ĝi estis elektita ĉar Firebase estas Guglo-produkto, kio signifas, ke ĝi devus esti fidinda kaj neverŝajna iam morti. La prezoj estas raciaj: $5 por horo de funkciado de vera aparato, 1 $ je horo de funkciado de emulilo.

Necesis proksimume tri semajnoj por efektivigi Firebase Test Lab en nian CI.

Sed la teamo daŭre kreskis, kaj Firebase, bedaŭrinde, komencis lasi nin. En tiu tempo, li ne havis ajnan SLA. Kelkfoje Firebase igis nin atendi ĝis la bezonata nombro da aparatoj estis liberaj por provoj, kaj ne komencis ekzekuti ilin tuj, kiel ni volis. Vico atendado daŭris ĝis duonhoro, kio estas tre longa tempo. Instrumentaj testoj estis kuritaj sur ĉiu PR, prokrastoj vere malrapidigis la evoluon, kaj tiam la monata fakturo venis kun ronda sumo. Ĝenerale, oni decidis forlasi Firebase kaj labori interne, ĉar la teamo sufiĉe kreskis.

Docker + Python + bash

Ni prenis Docker, plenigis emulilojn en ĝin, skribis simplan programon en Python, kiu en la ĝusta tempo startas la bezonatan nombron da emuliloj en la ĝusta versio kaj haltigas ilin kiam necese. Kaj, kompreneble, kelkaj bash-skriptoj - kie ni estus sen ili?

Necesis kvin semajnoj por krei nian propran testan medion.

Kiel rezulto, por ĉiu tirpeto ekzistis ampleksa kunfand-bloka listo de ĉekoj:

  • ARK asembleo;
  • Junit-testoj;
  • Lint;
  • Android Studio kontrolas;
  • Testoj pri instrumentado;
  • Ekrankopaj provoj.

Ĉi tio malhelpis multajn eblajn paneojn. Teknike ĉio funkciis, sed la programistoj plendis, ke la atendado de rezultoj estas tro longa.

Kiom longe estas tro longa? Ni alŝutis datumojn de Bitbucket kaj TeamCity en la analizan sistemon kaj rimarkis tion averaĝa atendotempo 45 minutoj. Tio estas, programisto, kiam malfermas tirpeton, atendas averaĝe 45 minutojn por la konstrurezultoj. Laŭ mi, ĉi tio estas multe, kaj vi ne povas labori tiel.

Kompreneble, ni decidis akceli ĉiujn niajn konstruojn.

Ni rapidu

Vidante, ke konstruaĵoj ofte staras en atendovico, la unua afero, kiun ni faras, estas aĉetis pli da aparataro — vasta evoluo estas la plej simpla. Konstruaĵoj ĉesis vici, sed la atendotempo malpliiĝis nur iomete, ĉar iuj kontroloj mem daŭris tre longan tempon.

Forigante ĉekojn kiuj daŭras tro longajn

Nia Daŭra Integriĝo povus kapti ĉi tiujn specojn de eraroj kaj problemoj.

  • Ne tuj. CI povas kapti kompilan eraron kiam io ne konstruas pro konfliktantaj ŝanĝoj. Kiel mi jam diris, tiam neniu povas kunveni ion ajn, disvolviĝo ĉesas, kaj ĉiuj nervoziĝas.
  • Cimo en konduto. Ekzemple, kiam la aplikaĵo estas konstruita, sed kraŝas kiam vi premas butonon, aŭ la butonon tute ne estas premata. Ĉi tio estas malbona ĉar tia cimo povas atingi la uzanton.
  • Cimo en aranĝo. Ekzemple, butono estas klakita, sed movis 10 pikselojn maldekstren.
  • Pliiĝo de teknika ŝuldo.

Rigardante ĉi tiun liston, ni rimarkis, ke nur la unuaj du punktoj estas kritikaj. Ni volas unue kapti tiajn problemojn. Cimoj en la aranĝo estas malkovritaj ĉe la dezajno-revizia etapo kaj povas esti facile korektitaj tiam. Trakti teknikan ŝuldon postulas apartan procezon kaj planadon, do ni decidis ne testi ĝin laŭ tira peto.

Surbaze de ĉi tiu klasifiko, ni skuis la tutan liston de ĉekoj. Forstrekita Lint kaj prokrastis ĝian lanĉon subite: nur por ke ĝi ellaboru raporton pri kiom da problemoj estis en la projekto. Ni konsentis labori aparte kun la teknika ŝuldo, kaj Android Studio-kontroloj estis tute forlasitaj. Android Studio en Docker por fari inspektadojn sonas interese, sed kaŭzas multajn problemojn en subteno. Ĉiu ĝisdatigo al Android Studio-versioj signifas lukton kun nekompreneblaj cimoj. Ankaŭ estis malfacile subteni ekrankopiajn testojn, ĉar la biblioteko ne estis tre stabila kaj estis falsaj pozitivoj. Ekrankopaj testoj estis forigitaj de la kontrollisto.

Kiel rezulto, ni restis kun:

  • ARK asembleo;
  • Junit-testoj;
  • Testoj pri instrumentado.

Gradle fora kaŝmemoro

Sen pezaj kontroloj, ĉio pliboniĝis. Sed ne estas limo al perfekteco!

Nia aplikaĵo jam estis dividita en ĉirkaŭ 150 gradle-modulojn. Gradle fora kaŝmemoro kutime bone funkcias en ĉi tiu kazo, do ni decidis provi ĝin.

Gradle fora kaŝmemoro estas servo kiu povas konservi konstruajn artefaktojn por individuaj taskoj en individuaj moduloj. Gradle, anstataŭ vere kompili la kodon, uzas HTTP por frapi la foran kaŝmemoron kaj demandi ĉu iu jam plenumis ĉi tiun taskon. Se jes, ĝi simple elŝutas la rezulton.

Ruli Gradle fora kaŝmemoro estas facila ĉar Gradle provizas Docker-bildon. Ni sukcesis fari tion en tri horoj.

Vi nur devis lanĉi Docker kaj skribi unu linion en la projekto. Sed kvankam ĝi povas esti lanĉita rapide, ĝi bezonos sufiĉe da tempo por ĉio bone funkcii.

Malsupre estas la kaŝmemoro miss-grafo.

Evoluo de CI en la movebla evolua teamo

Ĉe la komenco, la procento de kaŝmemoro maltrafas estis ĉirkaŭ 65. Post tri semajnoj, ni sukcesis pliigi ĉi tiun valoron al 20%. Montriĝis, ke la taskoj, kiujn kolektas la Android-apliko, havas strangajn transitivajn dependecojn, pro kiuj Gradle maltrafis la kaŝmemoron.

Konektante la kaŝmemoron, ni multe akcelis la konstruon. Sed krom muntado, ekzistas ankaŭ instrumentaj provoj, kaj ili daŭras longan tempon. Eble ne ĉiuj testoj devas esti rulitaj por ĉiu tira peto. Por ekscii, ni uzas efikan analizon.

Analizo de efiko

Je tira peto, ni kolektas git diff kaj trovas la modifitajn Gradle-modulojn.

Evoluo de CI en la movebla evolua teamo

Estas senco nur ruli instrumentajn testojn, kiuj kontrolas la ŝanĝitajn modulojn kaj ĉiujn modulojn kiuj dependas de ili. Ne utilas fari testojn por najbaraj moduloj: la kodo tie ne ŝanĝiĝis kaj nenio povas rompiĝi.

Instrumentaj testoj ne estas tiel simplaj, ĉar ili devas troviĝi en la plej alta nivela Aplika modulo. Ni uzis heŭristikojn kun bajtkoda analizo por kompreni al kiu modulo apartenas ĉiu testo.

Ĝisdatigi la operacion de la instrumentaj testoj tiel ke ili nur testas la modulojn engaĝitajn daŭris proksimume ok semajnojn.

Rimedoj por akceli inspektadojn sukcese funkciis. De 45 minutoj ni supreniris al ĉirkaŭ 15. Jam estas normale atendi kvaronhoron por konstruo.

Sed nun programistoj komencis plendi, ke ili ne komprenas, kiuj konstruoj estas lanĉitaj, kie vidi la protokolon, kial la konstruo estas ruĝa, kiu testo malsukcesis, ktp.

Evoluo de CI en la movebla evolua teamo

Problemoj kun sugestoj bremsas disvolviĝon, do ni provis provizi kiel eble plej klarajn kaj detalajn informojn pri ĉiu PR kaj konstrui kiel eble. Ni komencis per komentoj en Bitbucket al la PR, indikante kiu konstruo malsukcesis kaj kial, kaj skribis celitajn mesaĝojn en Slack. Al la fino, ni kreis PR-panelon por la paĝo kun listo de ĉiuj konstruaĵoj, kiuj nun funkcias kaj ilia stato: envico, kurante, kraŝis aŭ finitaj. Vi povas alklaki la konstruon kaj atingi ĝian protokolon.

Evoluo de CI en la movebla evolua teamo

Ses semajnoj estis pasigitaj por detalaj sugestoj.

Planoj

Ni transiru al lastatempa historio. Solvinte la reagon-problemon, ni atingis novan nivelon - ni decidis konstrui nian propran emulan bienon. Kiam estas multaj testoj kaj emuliloj, ili estas malfacile administreblaj. Kiel rezulto, ĉiuj niaj emuliloj translokiĝis al la k8s-grupo kun fleksebla administrado de rimedoj.

Krome, estas aliaj planoj.

  • Revenu Lint (kaj alia statika analizo). Ni jam laboras en ĉi tiu direkto.
  • Kuru ĉion sur PR-blokilo fin-al-finaj provoj en ĉiuj SDK-versioj.

Do, ni spuris la historion de la evoluo de Kontinua Integriĝo en Avito. Nun mi volas doni kelkajn konsilojn el sperta vidpunkto.

Konsiletoj

Se mi povus doni nur unu konsilon, tio estus:

Bonvolu esti singarda kun ŝelaj skriptoj!

Bash estas tre fleksebla kaj potenca ilo, ĝi estas tre oportuna kaj rapida por skribi skriptojn. Sed vi povas fali en kaptilon kun ĝi, kaj, bedaŭrinde, ni falis en ĝin.

Ĉio komenciĝis per simplaj skriptoj, kiuj funkciis per niaj konstrumaŝinoj:

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

Sed, kiel vi scias, ĉio evoluas kaj fariĝas pli komplika kun la tempo - ni rulu unu skripton de alia, ni pasigu tien kelkajn parametrojn - finfine ni devis skribi funkcion, kiu determinas je kia nivelo de bash-nestado ni nun estas en ordo. por enmeti la necesajn citaĵojn, por komenci ĉion.

Evoluo de CI en la movebla evolua teamo

Vi povas imagi la laborkostojn por la disvolviĝo de tiaj skriptoj. Mi konsilas al vi ne fali en ĉi tiun kaptilon.

Kion oni povas anstataŭigi?

  • Ajna skriptlingvo. Skribu al Python aŭ Kotlin Script pli oportune ĉar ĝi estas programado, ne skriptoj.
  • Aŭ priskribu la tutan konstrulogikon en la formo Propraj gradle taskoj por via projekto.

Ni decidis elekti la duan opcion, kaj nun ni sisteme forigas ĉiujn bash-skriptojn kaj verkas multajn kutimajn gradle-taskojn.

Konsilo #2: Konservu infrastrukturon en kodo.

Estas oportune kiam la agordo de Kontinua Integriĝo estas konservita ne en la UI-interfaco de Jenkins aŭ TeamCity, ktp., sed en formo de tekstaj dosieroj rekte en la projekta deponejo. Ĉi tio donas verseblecon. Ne estos malfacile retroiri aŭ konstrui la kodon sur alia branĉo.

Skriptoj povas esti stokitaj en projekto. Kion fari kun la medio?

Konsilo n-ro 3: Docker povas helpi pri la medio.

Ĝi certe helpos al Android-programistoj; iOS ankoraŭ ne havas, bedaŭrinde.

Jen ekzemplo de simpla docker-dosiero kiu enhavas jdk kaj 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

Skribinte ĉi tiun Docker-dosieron (mi diros al vi sekreton, vi ne devas skribi ĝin, sed simple tiri ĝin preta el GitHub) kaj kunveninte la bildon, vi ricevas virtualan maŝinon sur kiu vi povas konstrui la aplikaĵon. kaj ruli Junit-testojn.

La du ĉefaj kialoj kial ĉi tio havas sencon estas skaleblo kaj ripeteblo. Uzante docker, vi povas rapide levi dekduon da konstruaj agentoj, kiuj havos ĝuste la saman medion kiel la antaŭa. Ĉi tio multe pli facilas la vivon de CI-inĝenieroj. Estas sufiĉe facile puŝi la android-sdk en docker, sed kun emuliloj ĝi estas iom pli malfacila: vi devos labori iom pli malfacile (aŭ elŝuti la finitan el GitHub denove).

Konsilo n-ro 4: ne forgesu, ke inspektadoj ne estas faritaj pro inspektadoj, sed por homoj.

Rapida kaj, plej grave, klara sugesto estas tre grava por programistoj: kio rompiĝis, kia testo malsukcesis, kie mi povas vidi la konstruprogramon.

Konsilo #5: Estu pragmata dum disvolvado de Daŭra Integriĝo.

Klare komprenu kiajn erarojn vi volas malhelpi, kiom da rimedoj, tempo kaj komputila tempo vi pretas elspezi. Ĉekoj kiuj daŭras tro longaj povas, ekzemple, esti prokrastitaj dum la nokto. Kaj tiuj el ili, kiuj kaptas ne tre gravajn erarojn, estu tute forlasitaj.

Konsilo #6: Uzu pretajn ilojn.

Estas multaj kompanioj nun, kiuj provizas cloud CI.

Evoluo de CI en la movebla evolua teamo

Ĉi tio estas bona solvo por malgrandaj teamoj. Vi ne bezonas subteni ion, nur pagi iom da mono, konstrui vian aplikaĵon kaj eĉ fari instrumentajn testojn.

Konsilo #7: En granda teamo, endomaj solvoj estas pli profitaj.

Sed baldaŭ aŭ malfrue, dum la teamo kreskas, endomaj solvoj fariĝos pli profitaj. Estas unu problemo kun ĉi tiuj decidoj. En ekonomio ekzistas leĝo de malpliiĝantaj rendimentoj: en iu ajn projekto, ĉiu posta plibonigo estas pli kaj pli malfacila kaj postulas pli kaj pli da investo.

Ekonomiko priskribas nian tutan vivon, inkluzive de Kontinua Integriĝo. Mi konstruis horaron de laborkostoj por ĉiu etapo de evoluo de nia Daŭra Integriĝo.

Evoluo de CI en la movebla evolua teamo

Estas klare, ke ĉiu plibonigo fariĝas pli kaj pli malfacila. Rigardante ĉi tiun grafikaĵon, vi povas kompreni, ke Daŭra Integriĝo devas esti disvolvita laŭ la kresko de la grandeco de la teamo. Por teamo de du homoj, pasigi 50 tagojn evoluigi internan emulan bienon estas mezbona ideo. Sed samtempe, por granda teamo, tute ne fari Daŭran Integradon ankaŭ estas malbona ideo, ĉar integrigaj problemoj, ripari komunikadon ktp. ĝi bezonos eĉ pli da tempo.

Ni komencis kun la ideo ke aŭtomatigo estas bezonata ĉar homoj estas multekostaj, ili faras erarojn kaj estas maldiligentaj. Sed homoj ankaŭ aŭtomatigas. Tial ĉiuj samaj problemoj validas por aŭtomatigo.

  • Aŭtomatigo estas multekosta. Memoru la laborhoraron.
  • Kiam temas pri aŭtomatigo, homoj faras erarojn.
  • Foje estas tre maldiligente aŭtomatigi, ĉar ĉio funkcias tiel. Kial plibonigi ion alian, kial ĉio ĉi Daŭra Integriĝo?

Sed mi havas statistikojn: eraroj estas kaptitaj en 20% de asembleoj. Kaj ĉi tio ne estas ĉar niaj programistoj skribas kodon malbone. Ĉi tio estas ĉar programistoj certas, ke se ili faras iun eraron, ĝi ne finiĝos en disvolviĝo, ĝi estos kaptita de aŭtomataj kontroloj. Sekve, programistoj povas pasigi pli da tempo skribante kodon kaj interesajn aferojn, prefere ol kuri kaj provi ion loke.

Praktiku Daŭran Integriĝon. Sed en modereco.

Cetere, Nikolao Nesterov ne nur donas bonegajn raportojn mem, sed ankaŭ estas membro de la programa komitato AppsConf kaj helpas aliajn prepari signifajn paroladojn por vi. La kompleteco kaj utileco de la venonta konferenca programo estas taksataj per temoj en horaro. Kaj por detaloj, venu al Infospace la 22-23-an de aprilo.

fonto: www.habr.com

Aldoni komenton