Pentru a putea vedea în esență motivarea din spatele creării unui asemenea utilitar, consider că este necesară o introducere în contextul problemei. De obicei, fiecare dintre noi lucrează în cadrul unei echipe mai mici sau mai mari și care dezvoltă sau mențin unul sau mai multe produse/componente care trebuie să fie livrate la un moment dat. Depinzând de companie și de domeniul produselor care trebuie furnizate, procesul de livrare (începând de la cod și până la livrarea produsului final către clienți) poate să fie destul de complex, necesitând timp, pe care un programator sau tester îl poate folosi pentru a face lucruri mult mai creative.
Beneficiile unei asemenea abordări sunt diverse: de la eliminarea posibilității factorului uman de a face erori, până la faptul că se va ajunge la o standardizare a procesului de livrare la nivel de companie.
Acestea fiind spuse, am definit algoritmul de livrare în felul următor:
Verificare dependențelor temporare(snapshot dependencies).
Verificarea taskurilor în jira. Mai exact, faptul că toate taskurile pentru versiunea care trebuie livrată au starea corespunzătoare și au definite detalii de livrare.
Crearea zipului (artefactului) care va fi furnizat la client. În cazul nostru, zipul este un zip auto-descriptiv, va conține un fișier care specifică compatibilitatea cu alte produse/componente (în contextul controlului versiunilor între componente), crearea unor labeluri care vor evidenția specificația platformei.
Încărcarea pe o platformă, de unde clientul va putea descărca artefactul, sau încărcarea direct pe platformă de testare a clientului.
Crearea noii versiuni a produsului, și de asemenea, comiterea acesteia într-o manieră automată, pe sistemul de versionare folosit (GIT). Crearea automată de tag și/sau branch în funcție de necesități.
Vederea în jenkins va fi următoarea:
Fig.1. Vederea pașilor procesului de livrare, cu jenkins pipeline
Tot acest mecanism de automatizare a procesului de livrare s-a realizat cu ajutorul tehnologiei Jenkins Pipeline. Mai exact, această tehnologie este o suită de plug-in-uri care ne permite implementarea unui sistem de Continuous Delivery Pipelines. În fond, tot ceea ce facem, este să scriem o suită de scripturi care orchestrate de un script părinte, va executa pașii algoritmului de livrare. Jenkins ne propune un limbaj specific domeniului, anume Jenkins DSL cu ajutorul căruia putem să ne definim scriptul de orchestrare a etapelor de livrare.
Cu ajutorul acestui limbaj, putem să ne definim node-uri care corespund unei mașini capabile să execute scriptul pipeline. În cadrul fiecărui nod, ne definim stage-uri care reprezintă un subset de pași executați în cadrul pipeline-ului, fiecare dintre acești pași pot fi definiți în cardul unei secțiuni steps, ultima secțiune fiind opțională :
node {
stage ("Remove snapshots") { ...}
stage ("Verify JIRAs") { ... }
stage ("Create the build") { ... }
stage ("Run integration tests") { ... }
stage ("Check distribution") { ... }
stage ("Upload on release center") { ... }
stage ("Update version and commit after release")
{...}
}
Fiecare stage poate fi configurat după necesitați. În cazul nostru, fiecare stage are responsabilitatea de a activa un jenkins job, de a procesa răspunsul acestuia și de a decide următoarele acțiuni pe baza răspunsului primit. Aceasta abordare ne dă posibilitatea să ne definim checkpoints per stage. Beneficiul acestor checkpoints este faptul că dă posibilitatea utilizatorului să interacționeze cu pipeline-ul în cazul unor situații excepționale (ex. Probleme de infrastructură sau hardware). În cazul unei intervenții manuale, utilizatorul are opțiunea de a reîncerca un anumit pas. De asemenea, poate ignora acel pas sau poate să oprească tot procesul de livrare. Aceste acțiuni pot varia în funcție de implementare.
Cu toate că avem la dispoziție jenkins pipeline DSL cu ajutorul căruia reușim procesul de definire și de orchestrare a pașilor de livrare, în cazul de față ne-a fost de foarte mare folosință o suită de gradle plugins prin intermediul cărora am implementat diverse taskuri care sunt manevrate în cadrul pipeline-ului, de exemplu: crearea artefactului auto-descriptiv și diverse taskuri de gradle care ne ajută în procesul de livrare. Odată avute aceste utilități și scriptul de pipeline (cu scripturile din interiorul pașilor), putem să livrăm oricare componentă care se pretează standardului propus, cu o minimă configurare: la nivel de componentă, trebuie aplicate acele plug-in-uri despre care menționam mai sus.
Tot procesul anterior se poate realiza fără necesitatea absolută a anumitor plug-in-uri, având suport nativ în Jenkins DSL pentru pașii cel mai des folosiți, cum ar fi: accesarea unui repository SCM, lucrul cu fișiere, git commit, folosirea variabilelor de sistem etc. .
De asemenea, jenkins pipeline ne permite rularea în paralel a anumitor pași. Această capabilitate este utilă mai ales în cadrul produselor care au mai multe suite de teste de integrare. Toate aceste teste pot fi rulate în paralel, astfel se salvează timp în procesul de livrare.
În cele mai multe cazuri, fiecare dintre produsele noastre au mai multe versiuni și în anumite situații este nevoie să furnizăm același produs în multiple versiuni (per branch). Acest lucru este posibil, folosind multi-branch pipeline, adică ne putem integra utilitarul cu Git, astfel încât fiecare branch poate fi abordat independent în procesul de livrare.
Tot acest proces automat are sens în cazul în care produsul nostru este acoperit de o suită de teste automate (sau mai multe) pentru a fi încrezători în calitatea produsului livrat. Așadar, Jenkins Pipeline vine în ajutorul acestor produse (cu mai multe nivele de testare automată) și dă posibilitatea implementării unor pași care să ruleze în mod paralel. Următorul pas este rulat doar dacă toți pașii anteriori (rulați în paralel) au fost executați.
Rularea în paralel a anumitor pași poate fi realizată prin simpla plasare a acestora în cadrul unei directive paralele.
Fig. 2. Structura pipeline în mod paralel- exemplu
Odată pus la punct un asemenea utilitar și odată deținută infrastructura necesară, se poate preda orice produs care se pretează procesului definit. Din moment ce procesul de livrare este unul destul de complex, iar rezultatul coincide cu livrarea către client a unei componente software, un pas foarte important este modalitatea de testare a procesului în sine, în speță a utilitarului. Acest lucru se poate utiliza valorificând frameworkul de testare JenkinsPipelineUnit, cu ajutorul căruia putem scrie unit teste care să ne valideze configurarea și logica condițională din codul pipeline. În acest fel, avem posibilitatea să facem mock la execuția efectivă a pipeline-ului (cum ar fi comenzi și configurări de jenkins).
Tehnologia Jenkins Pipeline este în fond, un utilitar de automatizare continuă a anumitor procese software, extensibile prin design, folosind multitudinea de plug-in-uri puse la dispoziție de comunitatea jenkins. Prin urmare, în multe situații se dovedește a fi o bună alegere, sau cel puțin o posibilitate care trebuie luată în considerare, atunci când vrem să automatizăm anumite procese în cadrul echipe/companiei noastre. Această extensibilitate este extrem de utilă, deoarece oricine își poate crea propriul gradle plug-in care poate fi folosit în cadrul pipeline-ului. Cu alte cuvinte, poate fi ușor integrat cu orice utilitar privat sau open-source.
Pe lângă toată această abilitate de integrare, avem beneficiul de a descrie procesul de livrare prin intermediul codului, folosind Jenkins DSL și implicit Groovy DSL. De asemenea, vom avea și un istoric de versionare, astfel încât orice modificare în procesul de livrare va putea fi verificată și trecută prin procesul de review al companiei.
de Ovidiu Mățan
de Ovidiu Mățan