Ultimii câţiva ani au adus cu ei o schimbare majoră a mentalităţii persoanelor în ceea ce priveşte software-ul şi modul în care îl folosesc. Această schimbare a fost adusă de către omniprezentul smartphone, apariţia cloud computing-ului şi de către mai recentul internet of things (IoT). Dacă sunt luate în combinaţie cu o constantă creştere în competiţia dintre companiile software pe o piaţă cu tendințe de stagnare pe anumite segmente, puteţi înţelege cu mai mare uşurinţă cum stau lucrurile în momentul de faţă.
În prezent, utilizatorii se aşteaptă să aibă acces la software ce evoluează în mod constant, cu cele mai noi feature-uri, în cel mai scurt timp posibil. Există şi un avantaj major: utilizatorii sunt dispuşi să ierte anumite lucruri, atunci când este vorba de mici probleme cu software-ul, dacă sunt conştienţi de faptul că ele vor fi reparate la următorul release, iar intervalul dintre update-uri este destul de scurt să merite așteptarea. Aici intră în ecuaţie tema despre care vrem să vorbim. Cum te poţi ridica la nivelul aşteptărilor? După părerea noastră, răspunsul este implementarea continuous deliveryului pe proiectul tău.
Ce este continuous delivery? În funcţie de persoana pe care o întrebi, vei primi răspunsuri diferite. Dar pentru noi, continuous delivery este abilitatea de a trece de la un singur commit către repositoryul tău la un nou release în deployment către utilizatori în mod automat, totul după o singură apăsare de buton. Procesele de testare și validare rămân la fel de importante, dar prin integrarea lor în Continuous Delivery, scopul și modul de executare sunt abordate diferit: accentul este pus pe testele automate, testele manuale sunt centrate pe experiența utilizatorului în folosirea aplicației, testarea de explorare a produsului, evaluarea ușurinței de utilizare a funcțiilor noi aduse produsului.
Cum ajungi aici? Există mai multe variante, iar reţeta poate varia în funcţie de caracteristicele proiectului tău, dar există destule elemente care au rămas constante în industrie.
Primul pas este implementarea de Continuous Integration. Poţi spune că ai reuşit, atunci când fiecare commit din repository declanşează un build, care, în caz de succes, declanşează execuţia testelor de modul, care finalizate cu un rezultat pozitiv, declanșează împachetarea livrabilelor tale. Paralel cu procesul build, poate fi implementat un proces de revizuire a codului.
Următorul pas este rolloutul automat al acestui software nou pe mediul de testare, apoi executarea testelor de sistem şi de acceptanţă. În mod ideal vor fi automatizate testele, dar se mai numeşte continuous delivery dacă testele tale sunt manuale? Da, atâta timp cât, după ce au fost executate cu succes, procesul de delivery se mişcă automat către un release în mediul de producţie.
Setupul pentru fiecare mediu este numit "deployment pipeline".
Fig. 1 Anatomia unui deployment pipeline
Pentru a face posibilă continuous delivery, trebuie prima oară să creăm un deployment pipeline.
Deployment pipeline-ul este reprezentarea procesului de dezvoltare.
Pentru a face posibil un continuous delivery, trebuie să creăm un deployment pipeline.
Un deployment pipeline este automatizarea proceselor de development, testare şi release a software-ului pentru proiect. Pipeline-ul poate fi vizualizat ca implementarea value stream map-ului pe proiect.
Deployment pipeline-ul este compus din mai multe stadii, fiecare nivel contribuind cu o anumită activitate către release-ul şi livrarea software-ului.
Stagiile comune aproape oricărui proiect software sunt:
Stadiul de commit,
Stadiul de integrare,
Stadiul de acceptanţă,
Stadiile ar trebui să fie întotdeauna adaptate nevoilor proiectului. Aceasta înseamnă că anumite stagii ar putea fi omise, altele ar putea să fie opţionale. De exemplu, este posibil ca testele de tip User acceptance să fie opţionale pentru cazul în care efortul este disproporţionat de mare față de toate celelalte stagii. Acest lucru ar permite deploymentul anumitor bug fix-uri critice înainte de toate criteriile de acceptanţă.
Primul stadiu în deployment pipeline este stadiul de commit. Ciclul este pornit de către un developer care face submit la o schimbare către repository, care declanşează un build pe serverul de CI care execută o serie de verificări care evaluează noul commit. Aceste verificări includ de obicei compilarea, rularea unui tool de verificare statică pe cod, executarea de unit teste. Paralel cu aceste verificări există şi o practică foarte bună, şi anume verificarea commitului de către alţi developeri. Procesul de review este integrat în stadiul de commit, iar procesul nu poate continua până când toate verificările au fost efectuate cu succes iar artefactele rezultate să fie salvate în repository pentru a fi folosite în paşii următori.
Următorul pas este integrarea modulului generat mai sus în aplicaţie. Este important să nu se lucreze împotriva modulului şi să se folosească artefactul generat. La acest pas rulăm testele de integrare. Dacă se trece cu bine de toate verificările, produsul potenţial livrabil este generat aici şi stocat în repository. Este important că la acest pas, toate commiturile cele mai noi să fie colectate şi stocate la Release Notes. O politică sănătoasă pentru mesajele de commit înseamnă o listă de feature-uri foarte bine explicate, bug fixes şi alte îmbunătăţiri la produs.
Următorul stadiu este cel de acceptanţă, foarte important pentru succesul proiectului. În cadrul acestui stadiu este testat pentru prima oară pipeline-ul în forma care va fi livrată clientului. Suita de teste de acceptanţă automate trebuie să fie îndeajuns de bune încât să se poată avea încredere în deploymentul software-ului către producţie pentru releaseuri minore. În paralel cu testele de acceptanţă automate, ar trebui să existe teste automate de performanţă pe medii de testare specializate. Testele de acceptanţă manuale vor fi efectuate de către echipa de QA pe un alt mediu de testare automat, cu beneficiul adăugat de a avea cunoştinţe în ceea ce priveşte calitatea software-ului de la testele automate.
Al doilea rol major al stadiului de acceptanţă este de a testa deploymentul software-ului către un mediu similar cu cel de producţie. Deploymentul este automatizat. Scripturile care efectuează deploymentul utilizează repositoryul pentru artefacte . Deploymentul către mediul de test este declanşat de către fiecare build de succes care trece de integrare. Aici testele de sistem automate şi cele de acceptanţă vor fi executate, şi, bazat pe rezultatele obţinute, va fi luată o decizie dacă se va continua cu testele manuale, deployment pe pre-producţie şi/sau producţie sau dacă se va renunţa la release.
Decizia de a face deploy va fi luată de către o persoană din cadrul organizaţiei, dar deploymentul în sine va fi automatizat. Scripturile de deployment utilizate pentru mediul de test vor fi utilizate şi pentru pre-producţie dar cu configuraţii diferite. Aceasta abordare limitează riscul de eşec în timpul unui deployment la un minim.
Aş începe cu observaţia că toolurile evoluează şi că o dependenţă prea strânsă a deployment pipeline-ului de anumite tooluri ar putea duce la o situaţie de tip lock-in care ar putea limita oportunităţile de a evolua îndeajuns de repede.
Sunt mai mulţi candidaţi, care ies în evidenţă datorită popularității ca fiind buni candidaţi pentru implementarea în cadrul pipeline-ului. Începând cu Jenkins pentru serverul de continuous integration, primul pas spre implementarea pipeline-ului ar fi utilizarea de pluginuri disponibile pentru continuous delivery.
Fig. 2 Implementarea unui deployment pipeline în Jenkins
Pipeline-ul Jenkins are deja conceptul de stadiu integrat, ceea ce ajută la definirea infrastructurii prin cod. Jenkins utilizează groovy DSL pentru a defini deployment pipeline-ul şi implementa continuous delivery.
Detaliile fiecărui stadiu trebuie programate şi depind de configurarea proiectului. De exemplu, în stadiul de commit s-ar putea să se dorească integrarea cu Gerrit, prin Gerrit:
set GerritReview unsuccessfulMessage:'Buildfailed'
Stadiul de acceptanţă conţine mai multe noduri pentru diferitele tipuri de testare. Între acceptanţă şi deployment va exista
în mod normal un stadiu intermediar care necesită input de la utilizator pentru a declanşa deploymentul către mediul de producţie.
Versatilitatea oferită de Jenkins prin multitudinea de plug-in-uri ne oferă posibilitatea să integrăm tooluri deja existente de virtualizare, de executare a testelor automate, de distribuție automată a software-ului și lista ar putea continua la nesfârșit.
Totul pare a implica multă muncă. Este necesară coordonarea dintre mai multe discipline şi de o perioadă de acomodare. Toolurile te pot duce departe, dar mentalitatea şi modul de implementare în cadrul companiei sunt singurele lucruri capabile de a te purta peste linia de sosire.
Cum poţi face mai uşoare aceste lucruri? În opinia noastră, cel mai uşor mod este de a avea persoane care să se ocupe de deployment pipeline pentru tine. Pipeline-ul în sine este un software care evoluează în timp, schimbă modul în care îndeplineşti anumite lucruri. Atunci când am lucrat pentru prima oară în cadrul unei echipe care construia un deployment pipeline, Jenkins nu suporta un pipeline. O dată cu avansul soluțiilor bazate pe cloud, a apărut posibilitatea externalizarii procesului de livrare și implicit al deployment pipeline-ului, dar părțile pozitive și negative ale unei astfel de decizii depășesc scopul acestui articol.
Lumea în care trăim accelerează în mod constant ritmul de dezvoltare. Abilitatea de a evolua cu timpurile, de a schimba produsele livrate în funcție de nevoile pieței, în cel mai scurt timp posibil și cu un efort acceptabil, forțează pe oricine să ia in considerare implementarea unei strategii de tip continuous delivery pentru proiectele software.