CI-ի էվոլյուցիան բջջային զարգացման թիմում

Այսօր ծրագրային ապահովման արտադրանքի մեծ մասը մշակվում է թիմերով: Թիմի հաջող զարգացման պայմանները կարելի է ներկայացնել պարզ գծապատկերի տեսքով:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Ձեր կոդը գրելուց հետո դուք պետք է համոզվեք, որ այն.

  1. Աշխատանք.
  2. Այն ոչինչ չի խախտում, ներառյալ ձեր գործընկերների գրած կոդը:

Եթե ​​երկու պայմաններն էլ կատարվեն, ուրեմն դու հաջողության ճանապարհին ես։ Այս պայմանները հեշտությամբ ստուգելու և շահութաբեր ճանապարհից չշեղվելու համար մենք ստեղծեցինք Continuous Integration-ը:

CI-ն աշխատանքային հոսք է, որտեղ դուք հնարավորինս հաճախ ինտեգրում եք ձեր կոդը ընդհանուր արտադրանքի կոդի մեջ: Եվ դուք ոչ միայն ինտեգրվում եք, այլև անընդհատ ստուգում եք, որ ամեն ինչ աշխատում է: Քանի որ դուք պետք է շատ և հաճախ ստուգեք, արժե մտածել ավտոմատացման մասին: Դուք կարող եք ամեն ինչ ձեռքով ստուգել, ​​բայց դա չպետք է անեք, և ահա թե ինչու.

  • Ժողովուրդ ջան. Ցանկացած ծրագրավորողի աշխատանքի մեկ ժամը ավելի թանկ է, քան ցանկացած սերվերի աշխատանքը:
  • Մարդիկ սխալվում են. Հետևաբար, կարող են առաջանալ իրավիճակներ, երբ թեստերն առաջադրվել են սխալ ճյուղի վրա կամ սխալ հանձնառություն է կազմվել թեստավորողների համար:
  • Մարդիկ ծույլ են. Ժամանակ առ ժամանակ, երբ ավարտում եմ առաջադրանքը, միտք է առաջանում. «Ի՞նչ կա ստուգելու։ Ես գրել եմ երկու տող - ամեն ինչ աշխատում է: Կարծում եմ՝ ձեզանից ոմանք նույնպես երբեմն նման մտքեր են ունենում։ Բայց դուք միշտ պետք է ստուգեք.

Ինչպես է շարունակական ինտեգրումը ներդրվել և մշակվել Avito բջջային ծրագրավորման թիմում, ինչպես են նրանք օրական 0-ից հասել 450-ի, և այդ շինարարական մեքենաները հավաքում են օրական 200 ժամ, ասում է Նիկոլայ Նեստերովը (nnesterov) CI/CD Android հավելվածի բոլոր էվոլյուցիոն փոփոխությունների մասնակից է։

Պատմությունը հիմնված է Android հրամանի օրինակի վրա, սակայն մոտեցումների մեծ մասը կիրառելի է նաև iOS-ի վրա:


Ժամանակին մի մարդ աշխատում էր Avito Android-ի թիմում։ Ըստ սահմանման, նրան ոչինչ պետք չէր Continuous Integration-ից. չկար մեկը, ում հետ ինտեգրվեր:

Բայց հավելվածն աճեց, ավելի ու ավելի շատ նոր առաջադրանքներ հայտնվեցին, և թիմը համապատասխանաբար աճեց: Ինչ-որ պահի ժամանակն է ավելի պաշտոնապես հաստատել կոդի ինտեգրման գործընթաց: Որոշվեց օգտագործել Git flow-ը։

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Git flow-ի հայեցակարգը հայտնի է. նախագիծն ունի մեկ ընդհանուր զարգացող ճյուղ, և յուրաքանչյուր նոր ֆունկցիայի համար ծրագրավորողները կտրում են առանձին ճյուղ, պարտավորվում են դրան, հրում, և երբ ցանկանում են միացնել իրենց կոդը զարգացման ճյուղին, բացում են քաշելու հարցում. Գիտելիքները կիսելու և մոտեցումները քննարկելու համար մենք ներմուծեցինք կոդերի վերանայում, այսինքն՝ գործընկերները պետք է ստուգեն և հաստատեն միմյանց ծածկագիրը։

Չեկեր

Աչքերով կոդը տեսնելը լավ է, բայց բավարար չէ: Ուստի ներդրվում են ավտոմատ ստուգումներ։

  • Առաջին հերթին մենք ստուգում ենք ԱՐՔ ժողով.
  • Շատ բան Junit թեստեր.
  • Մենք համարում ենք ծածկագրի ծածկույթ, քանի որ մենք թեստեր ենք անցկացնում։

Հասկանալու համար, թե ինչպես պետք է իրականացվեն այս ստուգումները, եկեք նայենք Avito-ի զարգացման գործընթացին:

Այն սխեմատիկորեն կարող է ներկայացվել այսպես.

  • Մշակողը գրում է կոդը իր նոութբուքի վրա: Դուք կարող եք կատարել ինտեգրման ստուգումներ հենց այստեղ՝ կա՛մ commit hook-ով, կա՛մ պարզապես ստուգումներ կատարել ֆոնային ռեժիմում:
  • Այն բանից հետո, երբ մշակողը սեղմեց կոդը, նա բացում է ձգման հարցումը: Որպեսզի դրա կոդը ներառվի զարգացման մասնաճյուղում, անհրաժեշտ է անցնել կոդերի վերանայում և հավաքել անհրաժեշտ քանակի հաստատումներ։ Այստեղ կարող եք ակտիվացնել ստուգումները և կառուցումները. քանի դեռ բոլոր կառուցումները հաջող չեն, ձգման հարցումը չի կարող միավորվել:
  • Այն բանից հետո, երբ pull-ի հարցումը միաձուլվի և կոդը ներառվի մշակման մեջ, կարող եք ընտրել հարմար ժամանակ. օրինակ՝ գիշերը, երբ բոլոր սերվերները ազատ են, և կատարեք այնքան ստուգումներ, որքան ցանկանում եք:

Ոչ ոքի դուր չի եկել սկանավորումը իր նոութբուքի վրա: Երբ ծրագրավորողը ավարտում է գործառույթը, նա ցանկանում է արագ մղել այն և բացել ձգման հարցումը: Եթե ​​այս պահին որոշ երկար ստուգումներ սկսվեն, դա ոչ միայն այնքան էլ հաճելի չէ, այլև դանդաղեցնում է զարգացումը. մինչ նոութբուքը ինչ-որ բան է ստուգում, անհնար է դրա վրա նորմալ աշխատել։

Մեզ շատ դուր եկավ գիշերը ստուգումներ կատարելը, քանի որ շատ ժամանակ և սերվերներ կան, կարող եք շրջել: Բայց, ցավոք, երբ առանձնահատկությունների կոդը մշակվում է, մշակողը շատ ավելի քիչ մոտիվացիա ունի շտկելու CI-ի հայտնաբերած սխալները: Ես պարբերաբար մտածում էի, երբ նայում էի առավոտյան զեկույցում հայտնաբերված բոլոր սխալները, որ դրանք մի օր անց կուղղեմ, քանի որ այժմ Ժիրայում մի հիանալի նոր խնդիր կա, որը ես պարզապես ուզում եմ սկսել անել:

Եթե ​​չեկերը արգելափակում են ձգման հարցումը, ապա բավական մոտիվացիա կա, քանի որ քանի դեռ բիլլերը կանաչ չեն դարձել, կոդը չի մշակվի, ինչը նշանակում է, որ առաջադրանքը չի ավարտվի:

Արդյունքում մենք ընտրեցինք հետևյալ ռազմավարությունը. մենք իրականացնում ենք ստուգումների առավելագույն հնարավոր փաթեթը գիշերը և սկսում ենք դրանցից ամենակրիտիկականը և, ամենակարևորը, ամենաարագները՝ ձգման խնդրանքով: Բայց մենք դրանով կանգ չենք առնում. զուգահեռաբար մենք օպտիմիզացնում ենք ստուգումների արագությունը, որպեսզի դրանք գիշերային ռեժիմից տեղափոխենք հարցումների ստուգումներ:

Այն ժամանակ մեր բոլոր կառուցումները ավարտվեցին բավականին արագ, ուստի մենք պարզապես ներառեցինք ARK-ի կառուցումը, Junit-ի թեստերը և ծածկույթի ծածկույթի հաշվարկները՝ որպես ձգման հարցումի արգելափակող: Մենք միացրեցինք այն, մտածեցինք դրա մասին և հրաժարվեցինք ծածկագրի ծածկույթից, քանի որ կարծում էինք, որ դա մեզ պետք չէ:

Մեզնից երկու օր պահանջվեց հիմնական CI-ն ամբողջությամբ ստեղծելու համար (այսուհետ՝ ժամանակի գնահատումը մոտավոր է, անհրաժեշտ է մասշտաբի համար):

Դրանից հետո մենք սկսեցինք ավելին մտածել՝ նույնիսկ ճի՞շտ ենք ստուգում։ Արդյո՞ք մենք ճի՞շտ ենք գործարկում կառուցումներ՝ կապված ձգողականության պահանջների վրա:

Մենք սկսեցինք կառուցել ճյուղի վերջին հանձնման վրա, որտեղից բացվեց ձգման հարցումը: Բայց այս commit-ի թեստերը կարող են միայն ցույց տալ, որ մշակողի գրած կոդը աշխատում է: Բայց չեն ապացուցում, որ նա ոչինչ չի կոտրել։ Փաստորեն, դուք պետք է ստուգեք զարգացման ճյուղի վիճակը այն բանից հետո, երբ մի հատկանիշ միաձուլվի դրան:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Դա անելու համար մենք գրեցինք պարզ bash սցենար premerge.sh:

#!/usr/bin/env bash

set -e

git fetch origin develop

git merge origin/develop

Այստեղ մշակված բոլոր վերջին փոփոխությունները պարզապես վեր են հանվում և միաձուլվում ընթացիկ ճյուղին: Մենք ավելացրինք premerge.sh սկրիպտը որպես բոլոր կառուցումների առաջին քայլը և սկսեցինք ստուգել այն, ինչ ուզում ենք, այսինքն. ինտեգրում.

Երեք օր պահանջվեց խնդիրը տեղայնացնելու, լուծում գտնելու և այս սցենարը գրելու համար։

Հավելվածը զարգացավ, ավելի ու ավելի շատ առաջադրանքներ էին հայտնվում, թիմը մեծանում էր, և premerge.sh-ը երբեմն սկսում էր մեզ հիասթափեցնել: Develop-ն ունեցել է հակասական փոփոխություններ, որոնք կոտրել են կառուցվածքը:

Օրինակ, թե ինչպես է դա տեղի ունենում.

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Երկու մշակող միաժամանակ սկսում են աշխատել A և B հատկանիշների վրա: A հատկանիշի մշակողը հայտնաբերում է չօգտագործված հատկանիշ նախագծում answer() և լավ սկաուտի պես հեռացնում է այն: Միաժամանակ B հատկանիշի մշակողը նոր զանգ է ավելացնում այս ֆունկցիային իր մասնաճյուղում։

Մշակողները ավարտում են իրենց աշխատանքը և միաժամանակ բացում ձգման հարցումը: Կառուցումները գործարկվել են, premerge.sh-ը ստուգում է երկու հարցումները՝ կապված վերջին զարգացման վիճակի հետ. բոլոր ստուգումները կանաչ են: Դրանից հետո միաձուլվում է A հատկանիշի ձգման հարցումը, միաձուլվում է B հատկանիշի ձգման հարցումը... Բում! Մշակել ընդմիջումներ, քանի որ մշակման կոդը պարունակում է զանգ գոյություն չունեցող ֆունկցիայի:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Երբ այն չի զարգանալու, դա է տեղական աղետ. Ամբողջ թիմը չի կարող որևէ բան հավաքել և հանձնել փորձարկման:

Այնպես ստացվեց, որ ես ամենից հաճախ աշխատում էի ենթակառուցվածքային առաջադրանքների վրա՝ վերլուծություն, ցանց, տվյալների բազաներ։ Այսինքն, ես էի, որ գրել եմ այն ​​գործառույթներն ու դասերը, որոնք օգտագործում են այլ մշակողները։ Այդ պատճառով ես շատ հաճախ եմ հայտնվել նմանատիպ իրավիճակներում։ Ես նույնիսկ այս նկարը որոշ ժամանակ կախված ունեի:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Քանի որ դա մեզ հարմար չէր, մենք սկսեցինք ուսումնասիրել տարբերակները, թե ինչպես դա կանխել:

Ինչպես չխախտել զարգացնել

Առաջին տարբերակը ` վերակառուցել բոլոր ձգման հարցումները, երբ թարմացվում են: Եթե ​​մեր օրինակում A հատկանիշով ձգման հարցումն առաջինն է ներառված մշակման մեջ, B հատկանիշի ձգման հարցումը կվերակառուցվի, և, համապատասխանաբար, ստուգումները կձախողվեն կոմպիլյացիայի սխալի պատճառով:

Հասկանալու համար, թե որքան ժամանակ կպահանջվի դա, դիտարկենք երկու PR-ի օրինակ: Մենք բացում ենք երկու PR՝ երկու շինարարություն, երկու ստուգում: Այն բանից հետո, երբ առաջին PR-ը միաձուլվի և մշակվի, երկրորդը պետք է վերակառուցվի: Ընդհանուր առմամբ, երկու PR-ները պահանջում են ստուգման երեք փուլ՝ 2 + 1 = 3:

Սկզբունքորեն, դա լավ է: Բայց մենք նայեցինք վիճակագրությունը, և մեր թիմում բնորոշ իրավիճակը 10 բաց PR-ն էր, իսկ հետո ստուգումների քանակը առաջընթացի գումարն է՝ 10 + 9 +... + 1 = 55։ Այսինքն՝ ընդունել 10։ PR-ներ, դուք պետք է վերակառուցեք 55 անգամ: Եվ սա իդեալական իրավիճակում, երբ բոլոր ստուգումները անցնում են առաջին անգամ, երբ ոչ ոք չի բացում հավելյալ ձգման հարցում, մինչ այս տասնյակը մշակվում են։

Պատկերացրեք ձեզ որպես ծրագրավորող, ով պետք է առաջինը սեղմի «միաձուլման» կոճակը, քանի որ եթե հարևանը դա անի, ապա դուք պետք է սպասեք, մինչև բոլոր կառուցումները նորից անցնեն... Ոչ, դա չի աշխատի: , դա լրջորեն կդանդաղեցնի զարգացումը։

Երկրորդ հնարավոր ճանապարհը. կոդի վերանայումից հետո հավաքեք ձգման հարցումները: Այսինքն՝ դուք բացում եք pull-ի հարցումը, հավաքում եք անհրաժեշտ քանակի հաստատումներ գործընկերներից, ուղղում եք այն, ինչ անհրաժեշտ է, և այնուհետև գործարկում եք բիլդերը։ Եթե ​​դրանք հաջող լինեն, ապա ձգման հարցումը միաձուլվում է մշակման մեջ: Այս դեպքում լրացուցիչ վերագործարկումներ չկան, բայց հետադարձ կապը մեծապես դանդաղում է: Որպես ծրագրավորող, երբ ես բացում եմ ձգման հարցումը, ես անմիջապես ուզում եմ տեսնել, թե արդյոք այն կաշխատի: Օրինակ, եթե թեստը ձախողվում է, դուք պետք է արագ շտկեք այն: Հետաձգված կառուցման դեպքում հետադարձ կապը դանդաղում է, հետևաբար՝ ամբողջ զարգացումը: Սա էլ մեզ սազում չէր։

Արդյունքում մնաց միայն երրորդ տարբերակը. հեծանիվ. Մեր ամբողջ կոդը, մեր բոլոր աղբյուրները պահվում են Bitbucket սերվերի պահեստում: Համապատասխանաբար, մենք պետք է մշակեինք հավելված Bitbucket-ի համար։

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Այս փլագինը անտեսում է ձգման հարցումների միաձուլման մեխանիզմը: Սկիզբը ստանդարտ է. PR-ը բացվում է, բոլոր հավաքները գործարկվում են, ծածկագրի վերանայումն ավարտված է: Բայց այն բանից հետո, երբ կոդի վերանայումն ավարտված է, և մշակողը որոշում է սեղմել «միաձուլման» վրա, փլագինը ստուգում է, թե որ մշակման վիճակի դեմ են իրականացվել ստուգումները: Եթե ​​մշակումը թարմացվել է կառուցումից հետո, ապա plugin-ը թույլ չի տա, որ նման ձգման հարցումը միավորվի հիմնական ճյուղին: Այն պարզապես կվերսկսի համեմատաբար վերջերս մշակված կառուցումները:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Հակասական փոփոխություններով մեր օրինակում նման կառուցումները ձախողվելու են կոմպիլացիոն սխալի պատճառով: Համապատասխանաբար, B հատկանիշի մշակողը պետք է ուղղի կոդը, վերագործարկի չեկերը, այնուհետև փլագինը ավտոմատ կերպով կկիրառի ձգման հարցումը։

Նախքան այս հավելվածի ներդրումը, մենք միջին հաշվով 2,7 վերանայման գործարկում ենք մեկ ձգման հարցում: Փլագինով 3,6 գործարկում է եղել: Սա մեզ սազում էր։

Հարկ է նշել, որ այս plugin-ն ունի մի թերություն՝ այն միայն մեկ անգամ է վերագործարկում build-ը: Այսինքն՝ դեռ կա մի փոքր պատուհան, որով կարող են զարգանալ հակասական փոփոխություններ։ Բայց դրա հավանականությունը ցածր է, և մենք այս փոխզիջումն արեցինք մեկնարկների քանակի և ձախողման հավանականության միջև: Երկու տարվա ընթացքում միայն մեկ անգամ է կրակել, ուստի, հավանաբար, իզուր չի եղել։

Մեզ երկու շաբաթ պահանջվեց Bitbucket հավելվածի առաջին տարբերակը գրելու համար:

Նոր ստուգումներ

Մինչդեռ մեր թիմը շարունակում էր աճել։ Ավելացվել են նոր ստուգումներ։

Մտածում էինք՝ ինչո՞ւ սխալվել, եթե դրանք կարելի է կանխել։ Եվ դրա համար էլ իրականացրեցին ստատիկ կոդի վերլուծություն. Մենք սկսեցինք lint-ով, որը ներառված է Android SDK-ում: Բայց այն ժամանակ նա ընդհանրապես չգիտեր, թե ինչպես աշխատել Կոտլին կոդով, իսկ մենք արդեն ունեինք Կոտլինով գրված հավելվածի 75%-ը։ Հետևաբար, ներկառուցվածները ավելացվել են լիսեռի վրա Android Studio-ի ստուգումներ.

Դա անելու համար մենք ստիպված էինք շատ այլասերություններ անել. վերցնել Android Studio-ն, փաթեթավորել այն Docker-ում և գործարկել այն CI-ով վիրտուալ մոնիտորով, որպեսզի մտածի, որ այն աշխատում է իրական նոութբուքի վրա: Բայց դա ստացվեց:

Նաեւ այս ընթացքում էր, որ սկսեցինք շատ գրել գործիքավորման թեստեր և իրականացվել սքրինշոթի փորձարկում. Սա այն դեպքում, երբ ստեղծվում է հղման սքրինշոթ առանձին փոքր դիտման համար, և թեստը բաղկացած է տեսադաշտից սքրինշոթ վերցնելուց և այն ուղղակիորեն պիքսել առ պիքսել ստանդարտի հետ համեմատելուց: Եթե ​​կա անհամապատասխանություն, դա նշանակում է, որ դասավորությունը ինչ-որ տեղ սխալվել է կամ ինչ-որ բան այն չէ ոճերում։

Բայց գործիքավորման թեստերը և սքրինշոթի թեստերը պետք է կատարվեն սարքերի վրա՝ էմուլյատորների կամ իրական սարքերի վրա: Հաշվի առնելով, որ թեստերը շատ են և հաճախակի են անցկացվում, անհրաժեշտ է մի ամբողջ ֆերմա։ Ձեր սեփական ֆերմա հիմնելը չափազանց աշխատատար է, ուստի մենք գտանք պատրաստի տարբերակ՝ Firebase Test Lab:

Firebase փորձարկման լաբորատորիա

Այն ընտրվել է, քանի որ Firebase-ը Google-ի արտադրանք է, ինչը նշանակում է, որ այն պետք է հուսալի լինի և դժվար թե երբևէ մահանա: Գները խելամիտ են՝ 5 դոլար իրական սարքի աշխատանքի մեկ ժամում, 1 դոլար՝ էմուլյատորի մեկ ժամում։

Մոտ երեք շաբաթ պահանջվեց Firebase Test Lab-ի ներդրումը մեր CI-ում:

Բայց թիմը շարունակեց աճել, և Firebase-ը, ցավոք, սկսեց հիասթափեցնել մեզ: Այն ժամանակ նա ոչ մի ՍԼԱ չի ունեցել։ Երբեմն Firebase-ը մեզ ստիպում էր սպասել, մինչև անհրաժեշտ թվով սարքերը ազատ լինեին թեստերի համար, և չսկսեր դրանք անմիջապես գործարկել, ինչպես ուզում էինք: Հերթում սպասելը տևեց մինչև կես ժամ, ինչը շատ երկար է։ Գործիքավորման թեստերը կատարվում էին ամեն PR-ի վրա, ուշացումներն իսկապես դանդաղեցնում էին զարգացումը, իսկ հետո ամսական հաշիվը գալիս էր կլոր գումարով: Ընդհանուր առմամբ, որոշվեց հրաժարվել Firebase-ից և աշխատել տանը, քանի որ թիմը բավականաչափ մեծացել էր:

Docker + Python + bash

Մենք վերցրեցինք Docker-ը, դրա մեջ լցրեցինք էմուլյատորներ, գրեցինք մի պարզ ծրագիր Python-ում, որը ճիշտ պահին ցույց է տալիս անհրաժեշտ քանակությամբ էմուլատորներ անհրաժեշտ տարբերակում և անհրաժեշտության դեպքում դադարեցնում դրանք։ Եվ, իհարկե, մի քանի բաշ սցենար. որտե՞ղ կլինեինք մենք առանց դրանց:

Հինգ շաբաթ պահանջվեց մեր սեփական փորձարկման միջավայր ստեղծելու համար:

Արդյունքում, յուրաքանչյուր ձգման խնդրանքի համար կար ստուգումների միաձուլման արգելափակման ընդարձակ ցուցակ.

  • ARK ժողով;
  • Junit թեստեր;
  • Լինտ;
  • Android Studio-ի ստուգումներ;
  • Գործիքների թեստեր;
  • Սքրինշոթի թեստեր.

Սա կանխեց բազմաթիվ հնարավոր խափանումներ: Տեխնիկապես ամեն ինչ ստացվեց, բայց մշակողները դժգոհեցին, որ արդյունքների սպասելը չափազանց երկար է:

Որքա՞ն երկար է: Մենք Bitbucket-ից և TeamCity-ից տվյալները վերբեռնեցինք վերլուծության համակարգ և հասկացանք դա միջին սպասման ժամանակը 45 րոպե. Այսինքն, մշակողը, երբ բացում է ձգման հարցումը, միջինը 45 րոպե է սպասում կառուցման արդյունքներին։ Իմ կարծիքով, սա շատ է, և դուք չեք կարող այդպես աշխատել:

Իհարկե, մենք որոշեցինք արագացնել մեր բոլոր կառուցումները:

Եկեք արագացնենք

Տեսնելով, որ շենքերը հաճախ հերթ են կանգնում, առաջին բանը, որ անում ենք, դա է գնել է ավելի շատ սարքավորում - լայնածավալ զարգացումը ամենապարզն է: Շինությունները դադարեցին հերթագրվել, բայց սպասման ժամանակը մի փոքր պակասեց, քանի որ որոշ ստուգումներ իրենք շատ երկար տևեցին:

Չափից շատ երկար տևող չեկերի հեռացում

Մեր շարունակական ինտեգրումը կարող է բռնել այս տեսակի սխալներն ու խնդիրները:

  • Չի պատրաստվում. CI-ն կարող է բռնել կոմպիլյացիայի սխալ, երբ ինչ-որ բան չի կառուցվում հակասական փոփոխությունների պատճառով: Ինչպես արդեն ասացի, այդ դեպքում ոչ ոք ոչինչ չի կարող հավաքել, զարգացումը կանգ է առնում, և բոլորը նյարդայնանում են։
  • Սխալ վարքագծի մեջ. Օրինակ, երբ հավելվածը կառուցված է, բայց կոճակ սեղմելիս խափանում է, կամ կոճակն ընդհանրապես չի սեղմվում։ Սա վատ է, քանի որ նման սխալը կարող է հասնել օգտվողին:
  • Սխալ դասավորության մեջ. Օրինակ, կոճակը սեղմված է, բայց 10 պիքսել է տեղափոխվել ձախ:
  • Տեխնիկական պարտքի ավելացում.

Այս ցուցակը դիտելուց հետո մենք հասկացանք, որ միայն առաջին երկու կետերն են կարևոր: Մենք ուզում ենք առաջին հերթին բռնել նման խնդիրները։ Դասավորության սխալները հայտնաբերվում են նախագծման-վերանայման փուլում և կարող են հեշտությամբ ուղղվել: Տեխնիկական պարտքի հետ գործ ունենալը պահանջում է առանձին գործընթաց և պլանավորում, ուստի մենք որոշեցինք չփորձարկել այն ձգման խնդրանքով:

Այս դասակարգման հիման վրա մենք ցնցեցինք ստուգումների ամբողջ ցանկը: Լինտ հատած և մեկ գիշերվա ընթացքում հետաձգեց դրա մեկնարկը. հենց այնպես, որ հաշվետվություն ներկայացնի, թե որքան խնդիրներ կան նախագծում: Պայմանավորվեցինք, որ տեխնիկական պարտքով առանձին աշխատենք, և Android Studio-ի ստուգումներն ամբողջությամբ հրաժարվել են. Android Studio-ն Docker-ում ստուգումների գործարկման համար հետաքրքիր է թվում, բայց աջակցության մեջ շատ դժվարություններ է առաջացնում: Android Studio-ի տարբերակների ցանկացած թարմացում նշանակում է պայքար անհասկանալի սխալների դեմ: Դժվար էր նաև սքրինշոթ թեստերն աջակցելը, քանի որ գրադարանն այնքան էլ կայուն չէր և կային կեղծ պոզիտիվներ: Սքրինշոթի թեստերը հանվել են ստուգաթերթից.

Արդյունքում մեզ մնաց.

  • ARK ժողով;
  • Junit թեստեր;
  • Գործիքավորման թեստեր.

Gradle հեռավոր քեշ

Առանց ծանր ստուգումների՝ ամեն ինչ ավելի լավացավ։ Բայց կատարելության սահման չկա:

Մեր դիմումն արդեն բաժանված էր մոտ 150 gradle մոդուլների: Gradle հեռավոր քեշը սովորաբար լավ է աշխատում այս դեպքում, ուստի մենք որոշեցինք փորձել այն:

Gradle հեռավոր քեշը ծառայություն է, որը կարող է քեշավորել կառուցված արտեֆակտները առանձին մոդուլներում առանձին առաջադրանքների համար: Գրադլը, փաստացի կոդը կազմելու փոխարեն, օգտագործում է HTTP՝ թակելու հեռավոր քեշը և հարցնելու՝ արդյոք ինչ-որ մեկն արդեն կատարել է այս առաջադրանքը: Եթե ​​այո, ապա այն պարզապես ներբեռնում է արդյունքը:

Gradle-ի հեռավոր քեշի գործարկումը հեշտ է, քանի որ Gradle-ն ապահովում է Docker պատկեր: Մեզ հաջողվեց դա անել երեք ժամում։

Ընդամենը պետք էր գործարկել Docker-ը և մեկ տող գրել նախագծում: Բայց թեև այն կարող է արագ գործարկվել, բավականին շատ ժամանակ կպահանջվի, որպեսզի ամեն ինչ լավ աշխատի:

Ստորև բերված է քեշի բաց թողնված գրաֆիկը:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Հենց սկզբում քեշի բացթողումների տոկոսը մոտ 65 էր: Երեք շաբաթ անց մեզ հաջողվեց այս արժեքը հասցնել 20%-ի: Պարզվել է, որ առաջադրանքները, որոնք հավաքում է Android հավելվածը, տարօրինակ անցումային կախվածություններ ունեն, ինչի պատճառով Գրեդլը բաց է թողել քեշը։

Միացնելով քեշը, մենք մեծապես արագացրեցինք կառուցումը: Բայց բացի հավաքումից, կան նաև գործիքավորման թեստեր, որոնք երկար ժամանակ են պահանջում: Հավանաբար, ոչ բոլոր թեստերը պետք է կատարվեն յուրաքանչյուր ձգման խնդրանքի համար: Պարզելու համար մենք օգտագործում ենք ազդեցության վերլուծություն:

Ազդեցության վերլուծություն

Ձգման խնդրանքով մենք հավաքում ենք git diff և գտնում ենք փոփոխված Gradle մոդուլները:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Իմաստ է գործարկել միայն գործիքավորման թեստերը, որոնք ստուգում են փոփոխված մոդուլները և դրանցից կախված բոլոր մոդուլները: Հարևան մոդուլների համար թեստեր անցկացնելն իմաստ չունի. այնտեղ ծածկագիրը չի փոխվել և ոչինչ չի կարող կոտրվել:

Գործիքավորման թեստերն այնքան էլ պարզ չեն, քանի որ դրանք պետք է տեղակայվեն վերին մակարդակի Application մոդուլում: Մենք օգտագործեցինք էվրիստիկա բայթկոդի վերլուծությամբ՝ հասկանալու համար, թե որ մոդուլին է պատկանում յուրաքանչյուր թեստ։

Գործիքավորումների թեստերի աշխատանքի բարելավումն այնպես, որ դրանք փորձարկեն միայն ներգրավված մոդուլները, տևեց մոտ ութ շաբաթ:

Ստուգումների արագացմանն ուղղված միջոցառումները հաջողությամբ են աշխատել: 45 րոպեից մենք հասանք մոտ 15-ի: Արդեն նորմալ է շինարարության համար քառորդ ժամ սպասելը:

Բայց հիմա ծրագրավորողները սկսել են բողոքել, որ չեն հասկանում, թե որ բիլդներն են գործարկվում, որտեղ տեսնել տեղեկամատյանը, ինչու է բիլդը կարմիր, ո՞ր թեստը ձախողվել է և այլն։

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Հետադարձ կապի հետ կապված խնդիրները դանդաղեցնում են զարգացումը, ուստի մենք փորձեցինք հնարավորինս պարզ և մանրամասն տեղեկատվություն տրամադրել յուրաքանչյուր PR-ի և շինարարության մասին: Մենք սկսեցինք Bitbucket-ում PR-ի մեկնաբանություններից՝ նշելով, թե որ կառուցումն է ձախողվել և ինչու, և գրեցինք նպատակային հաղորդագրություններ Slack-ում: Ի վերջո, մենք էջի համար ստեղծեցինք PR վահանակ, որը պարունակում է բոլոր կառուցումների ցանկը, որոնք ներկայումս աշխատում են և դրանց կարգավիճակը՝ հերթագրված, գործարկված, խափանված կամ ավարտված: Դուք կարող եք սեղմել build-ի վրա և հասնել դրա մատյան:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Վեց շաբաթ ծախսվել է մանրամասն արձագանքների վրա:

Plans

Անցնենք նորագույն պատմությանը։ Լուծելով հետադարձ կապի հարցը՝ մենք հասանք նոր մակարդակի. մենք որոշեցինք կառուցել մեր էմուլյատորների ֆերմա: Երբ կան բազմաթիվ թեստեր և էմուլյատորներ, դրանք դժվար է կառավարել: Արդյունքում, մեր բոլոր էմուլյատորները տեղափոխվեցին k8s կլաստեր՝ ռեսուրսների ճկուն կառավարմամբ:

Բացի այդ, կան այլ ծրագրեր.

  • Վերադարձիր Լինթ (և այլ ստատիկ վերլուծություններ): Մենք արդեն աշխատում ենք այս ուղղությամբ։
  • Գործարկեք ամեն ինչ PR արգելափակման միջոցով վերջից մինչև վերջ թեստեր SDK-ի բոլոր տարբերակներում:

Այսպիսով, մենք հետևել ենք Avito-ում Continuous Integration-ի զարգացման պատմությանը: Հիմա ես ուզում եմ մի քանի խորհուրդ տալ փորձառու տեսանկյունից.

Советы

Եթե ​​ես կարողանայի ընդամենը մեկ խորհուրդ տալ, դա կլիներ հետևյալը.

Խնդրում ենք զգույշ լինել shell-ի սցենարների հետ:

Bash-ը շատ ճկուն և հզոր գործիք է, այն շատ հարմար և արագ է գրելու սցենարներ։ Բայց դրանով կարելի է թակարդն ընկնել, և, ցավոք, մենք ընկանք դրա մեջ։

Ամեն ինչ սկսվեց պարզ սցենարներից, որոնք աշխատում էին մեր շինարարական մեքենաների վրա.

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

Բայց, ինչպես գիտեք, ժամանակի ընթացքում ամեն ինչ զարգանում և բարդանում է. եկեք գործարկենք մի սկրիպտը մյուսից, եկեք որոշ պարամետրեր անցկացնենք այնտեղ, վերջում մենք պետք է գրեինք մի ֆունկցիա, որը որոշում է, թե բաշի բույնի որ մակարդակում ենք մենք հիմա կարգի մեջ: անհրաժեշտ չակերտները տեղադրելու, ամեն ինչ սկսելու համար:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Դուք կարող եք պատկերացնել, թե ինչպիսի աշխատուժի ծախսեր կան նման սցենարների մշակման համար։ Խորհուրդ եմ տալիս չընկնել այս ծուղակը։

Ինչ կարելի է փոխարինել:

  • Ցանկացած սցենարային լեզու: Գրեք Python կամ Kotlin Script ավելի հարմար, քանի որ դա ծրագրավորում է, ոչ թե սցենարներ:
  • Կամ նկարագրեք ամբողջ կառուցման տրամաբանությունը ձևի մեջ Պատվերով gradle առաջադրանքներ ձեր նախագծի համար:

Մենք որոշեցինք ընտրել երկրորդ տարբերակը, և այժմ մենք համակարգված կերպով ջնջում ենք բոլոր bash սկրիպտները և գրում ենք շատ պատվերով gradle առաջադրանքներ:

Հուշում #2. Պահպանեք ենթակառուցվածքը կոդով:

Հարմար է, երբ Continuous Integration պարամետրը պահվում է ոչ թե Jenkins-ի կամ TeamCity-ի UI ինտերֆեյսում, այլ տեքստային ֆայլերի տեսքով անմիջապես նախագծի պահեստում։ Սա տալիս է տարբերակելիություն: Դժվար չի լինի ետ վերադարձնելը կամ կոդը կառուցել մեկ այլ ճյուղում:

Սցենարները կարող են պահպանվել նախագծում: Ի՞նչ անել շրջակա միջավայրի հետ:

Հուշում #3. Docker-ը կարող է օգնել շրջակա միջավայրին:

Այն անպայման կօգնի Android ծրագրավորողներին, iOS-ը, ցավոք, դեռ չունի:

Սա պարզ docker ֆայլի օրինակ է, որը պարունակում է jdk և 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

Գրելով այս Docker ֆայլը (ես ձեզ մի գաղտնիք կասեմ, պետք չէ գրել այն, այլ պարզապես այն պատրաստի GitHub-ից քաշեք) և հավաքելով պատկերը, դուք ստանում եք վիրտուալ մեքենա, որի վրա կարող եք ստեղծել հավելվածը: և գործարկել Junit թեստերը:

Երկու հիմնական պատճառները, թե ինչու դա իմաստ ունի, մասշտաբայնությունն ու կրկնելիությունն են: Օգտագործելով docker-ը, դուք կարող եք արագ բարձրացնել տասնյակ build գործակալներ, որոնք կունենան ճիշտ նույն միջավայրը, ինչ նախորդը: Սա զգալիորեն հեշտացնում է CI ինժեներների կյանքը: Android-sdk-ն դոկեր մտցնելը բավականին հեշտ է, բայց էմուլյատորների դեպքում մի փոքր ավելի դժվար է. դուք պետք է մի փոքր ավելի շատ աշխատեք (կամ նորից ներբեռնեք պատրաստը GitHub-ից):

Հուշում թիվ 4՝ մի մոռացեք, որ ստուգումները կատարվում են ոչ թե հանուն ստուգումների, այլ մարդկանց։

Արագ և, ամենակարևորը, հստակ հետադարձ կապը շատ կարևոր է մշակողների համար՝ ինչն է կոտրվել, ինչ թեստը ձախողվել է, որտեղ կարող եմ տեսնել buildlog-ը։

Հուշում #5. Եղեք պրագմատիկ՝ շարունակական ինտեգրում զարգացնելիս:

Հստակ հասկացեք, թե ինչ տեսակի սխալներ եք ուզում կանխել, որքան ռեսուրսներ, ժամանակ և համակարգչային ժամանակ եք պատրաստ ծախսել: Չափազանց երկար տևող ստուգումները, օրինակ, կարող են հետաձգվել մեկ գիշերվա ընթացքում: Եվ նրանցից, ովքեր բռնում են ոչ շատ կարևոր սխալներ, պետք է ամբողջությամբ հրաժարվել:

Հուշում թիվ 6. Օգտագործեք պատրաստի գործիքներ:

Այժմ կան բազմաթիվ ընկերություններ, որոնք ապահովում են ամպային CI:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Սա լավ լուծում է փոքր թիմերի համար: Ձեզ հարկավոր չէ որևէ բան աջակցել, պարզապես վճարեք մի փոքր գումար, ստեղծեք ձեր հավելվածը և նույնիսկ կատարեք գործիքավորման թեստեր:

Հուշում #7. Մեծ թիմում ներքին լուծումներն ավելի շահավետ են:

Սակայն վաղ թե ուշ, քանի որ թիմը մեծանում է, ներքին լուծումները կդառնան ավելի շահավետ: Այս որոշումների հետ մեկ խնդիր կա. Տնտեսագիտության մեջ կա նվազող եկամտաբերության օրենք. ցանկացած նախագծում յուրաքանչյուր հաջորդ բարելավում ավելի ու ավելի դժվար է և պահանջում է ավելի ու ավելի շատ ներդրումներ:

Տնտեսագիտությունը նկարագրում է մեր ողջ կյանքը, ներառյալ շարունակական ինտեգրումը: Ես կազմել եմ աշխատուժի ծախսերի ժամանակացույց մեր Շարունակական ինտեգրման զարգացման յուրաքանչյուր փուլի համար:

CI-ի էվոլյուցիան բջջային զարգացման թիմում

Հասկանալի է, որ ցանկացած բարելավում գնալով դժվարանում է։ Նայելով այս գրաֆիկին՝ դուք կարող եք հասկանալ, որ շարունակական ինտեգրումը պետք է մշակվի թիմի չափի աճին համապատասխան: Երկու հոգուց բաղկացած թիմի համար ներքին էմուլյատորների ֆերմայի մշակման վրա 50 օր ծախսելը միջակ գաղափար է: Բայց միևնույն ժամանակ, մեծ թիմի համար Continuous Integration ընդհանրապես չանելը նույնպես վատ գաղափար է, քանի որ ինտեգրման խնդիրներ, կապի շտկում և այլն։ դա էլ ավելի շատ ժամանակ կպահանջի:

Մենք սկսեցինք այն մտքով, որ ավտոմատացումն անհրաժեշտ է, քանի որ մարդիկ թանկ են, սխալվում են և ծույլ են։ Բայց մարդիկ նաև ավտոմատացնում են: Հետեւաբար, բոլոր նույն խնդիրները վերաբերում են ավտոմատացմանը:

  • Ավտոմատացումը թանկ է. Հիշեք աշխատանքային գրաֆիկը.
  • Երբ խոսքը վերաբերում է ավտոմատացմանը, մարդիկ սխալներ են թույլ տալիս:
  • Երբեմն շատ ծույլ է լինում ավտոմատացնել, քանի որ ամեն ինչ այդպես է աշխատում: Ինչու՞ բարելավել որևէ այլ բան, ինչու՞ այս ամբողջ շարունակական ինտեգրումը:

Բայց ես վիճակագրություն ունեմ. սխալները հայտնաբերվում են հավաքների 20%-ում: Եվ դա այն պատճառով չէ, որ մեր մշակողները վատ են գրում կոդը: Դա պայմանավորված է նրանով, որ մշակողները վստահ են, որ եթե նրանք ինչ-որ սխալ թույլ տան, այն չի ավարտվի մշակման մեջ, այն կբռնվի ավտոմատացված ստուգումների միջոցով: Համապատասխանաբար, մշակողները կարող են ավելի շատ ժամանակ ծախսել կոդ և հետաքրքիր բաներ գրելու համար, այլ ոչ թե տեղական ինչ-որ բան գործարկելու և փորձարկելու փոխարեն:

Կիրառեք շարունակական ինտեգրում: Բայց չափավոր:

Ի դեպ, Նիկոլայ Նեստերովը ոչ միայն ինքն է հիանալի զեկույցներ տալիս, այլեւ ծրագրային հանձնաժողովի անդամ է AppsConf և օգնում է ուրիշներին պատրաստել բովանդակալից ելույթներ ձեզ համար: Հաջորդ համաժողովի ծրագրի ամբողջականությունն ու օգտակարությունը կարելի է գնահատել ըստ թեմաների ժամանակացույց. Իսկ մանրամասների համար համեցե՛ք Infospace ապրիլի 22-23-ը։

Source: www.habr.com

Добавить комментарий