Așa cum se întâmplă în foarte multe companii cu experiență îndelungată în IT, există o mare dorință de a se obține o modalitate prin care programatorii să cunoască efectele muncii lor nu numai în contextul modulului la care lucrează, dar mai ales din perspectiva întregului produs software comercializat. Acest lucru ar putea părea relativ ușor, dar în cazul unei soluții complexe, cum ar fi cazul unui ERP, cu multiple module atașate la core-ul soluției, este un demers presărat cu momente tensionate.
Cu toate acestea, noi am hotărât că, indiferent cât de mare este provocarea, rezultatul final va fi unul spectaculos. Cu atât mai mult cu cât, o dată cu acest demers, urma să trecem întreaga soluție în Microsoft Azure și în cele din urmă la o soluție SaaS (Software as a Service).
Evident, ne-am adunat într-o sală de ședințe și am pus pe hârtie:
Unde suntem? Utilizăm TFS, Jenkins, Jira, obținem artefactele (în mare parte .msi sau .msp) buildurilor echipelor de dezvoltare, apoi după un proces laborios reușim să obținem un pachet livrabil. Abia atunci, o dată pe lună, putem vedea rezultatul muncii dezvoltatorilor și succesul (sau nu) integrării. Lucram cu mai multe medii de dezvoltare (DEV/TEST/ACCEPT) instalate on-premises. Nu aș vrea să intrăm în detaliu în ceea ce privește aceste medii deoarece, fiind găzduite într-un data center, orice modificare trebuia planificată cu mult timp înainte, se făceau zeci de tichete pentru orice schimbare a acestor medii și timpul necesar pentru scalare (de exemplu, adăugarea de resurse hardware doar pentru a rula anumite teste) era foarte mare.
Unde vrem să ajungem? Simplu, să avem feedback FUNCȚIONAL(produsul funcționează în totalitatea sa) pentru fiecare commit al dezvoltatorilor.
Întrucât produsul nostru este bazat pe Dynamics NAV și .NET, decizia în ceea ce privește uneltele necesare a fost relativ ușoară: Microsoft stack. Pentru orchestrarea întregii evoluții a software-ului, am ales VSTS (Visual Studio Team Services), care, deși complex -urmărește un task de la crearea acestuia, a branchului aferent, a buildurilor și release-urilor, precum și a testelor funcționale- a devenit în scurt timp o unealtă utilizată în mod natural de către echipa DevOps.
După mai multe ședințe, reveniri la reveniri și găsirea de noi soluții, am pus totul pe .... perete (nu suntem singurii care fac acest lucru!). Și a rezultat imaginea alăturată.
Ceea ce noi ne-am propus nu era doar o schimbare de tooluri (din TFS în Git, din Jira/Jenkins în VSTS), dar mai ales o schimbare de abordare și de mod de lucru al dezvoltatorilor. Această nouă lume implică trecerea de la lucrul cu medii statice de dezvoltare la a avea un mediu nou în fiecare zi, un mediu care să reflecte modificările, cel puțin zilnice, aduse în cod de către toate echipele. Presupune o gândire și apropiere de TDD (Test Driven Development), deoarece pleacă de la ipoteza că realizarea testelor funcționale și introducerea acestora în fluxul de dezvoltare se realizează concomitent cu introducerea noilor funcționalități în cod.
Îi spunem "pipeline" și este o linie de automatizare a întregului proces de obținere a feedbackului funcțional pentru modificările aduse în cod.
Utilizând VSTS, cu Git ca modalitate de source control, se creează un "build depot" cu artefactele obținute din buildurile tuturor echipelor, apoi cu ajutorul codului dezvoltat de echipa DevOps construim în Azure un mediu de lucru (mașini virtuale, rețele, service busuri, alte servicii cloud necesare pentru funcționarea soluției) în care instalăm produsul nostru. Rulăm pre/post checks și culegem rezultatul acestor teste sub formă de Junit, interpretabila de VSTS. Astfel, în câteva ore, cât durează întregul proces, un dezvoltator are o imagine clară a efectelor pe care modificările realizate de el în cod le au la nivel funcțional al întregului produs software.
O primă problemă a fost trecerea codului din TFS în Git. Deoarece vorbim de milioane de linii de cod, trecerea este una anevoioasă, iar noi ne doream rezultate cât mai curând. În consecință, am creat ceea ce se numesc "shadow builds", care ne permit preluarea automată din Jenkins a artefactelor rezultate din buildurile echipelor și publicarea acestora, cu ajutorul VSTS, în build depot. Apoi, utilizând ARM (Azure Resource Manager), un serviciu cloud ce permite realizarea de resurse cloud prin descrierea lor în fișiere JSON, obținem întregul arsenal de resurse necesare pentru instalarea produsului software. Deoarece mașinile virtuale sunt doar la nivelul sistemului de operare, este necesară instalarea prerequisite-urilor, moment în care intră în scenă DSC (Desired State Configuration), un tool de management al configurației specific Microsoft. După încheierea acestui proces, este necesară rularea unor teste de infrastructură pentru a determina eventualele greșeli de configurație (work in progress). Cu ajutorul unui tool de instalare/configurare realizat "în casă", rulăm testele anterioare instalării produsului software, apoi instalăm și rulăm testele post-deployment.
Întregul proces este automatizat și putem obține la cerere medii necesare pentru testarea întregii soluții sau medii custom, necesare doar anumitor echipe. De asemenea, unul din punctele forte este faptul că fiecare release are o versiune, ceea ce permite obținerea la cerere a unui mediu de lucru specific (de exemplu, release 4, service pack 7, bug fix 20).
Migrarea întregului cod sursa (acele câteva milioane de linii) din TFS în Git, adăugarea testelor de infrastructură, integrarea soluției cu alte produse software 3rd party utilizate de clienții noștri sunt sarcini la care lucrăm momentan. Progresele realizate până acum și rezultatele obținute ne dau speranța că într-o zi (curând) vom uita de momentele când nu eram siguri ce efecte va produce la nivelul întregii soluții software modificarea unui rând de cod.
de Mihai Varga
de Călin Diniș , Mihai Tentis