CI/CD in de praktijk

De productiviteit van je team in een hogere versnelling – dat kan met een geautomatiseerde oplossing voor integratie, levering en uitrol, welbekend als CI/CD (continuous integration, continuous delivery/deployment). Het is een vitaal onderdeel van elk volwassen ontwikkelteam. De behoefte aan een dergelijke oplossing was bij team BASIC bij Alliander groot, gezien wij veel producten beheren en bouwen: van API’s in Java tot libraries in Python met AWS Lambda functies als kers op de taart. Combineer je dat met drie deployment omgevingen, dan wordt een CI/CD implementatie broodnodig. Maar hoe zorg je dat deze implementatie met diverse talen en toepassing om kan gaan? Hoe hou je het geheel herbruikbaar, uitbreidbaar en onderhoudbaar? Wij hebben deze vragen beantwoord en de uitkomsten geïmplementeerd.

Het probleem en de wens

Het doel van CI/CD is om zoveel mogelijk werk uit de handen van het team te nemen: het stukje CI test en valideert de code, terwijl het stukje CD de code automatisch bouwt en uitrolt zodra deze in de correcte branch geïntegreerd is. Een dergelijk systeem biedt veel voordelen: het zorgt voor een consistente deploymentstrategie, bespaart veel tijd (op lange termijn), bewaakt codekwaliteit en vereenvoudigt het gehele leveringsproces voor het team.

Bouwblokken

Wij wilden een opzet waarmee we voor elk smaakje product gemakkelijk een geschikte pipeline in elkaar kunnen klikken. Ook moet elke pipeline alleen taken uitvoeren die relevant zijn voor het betreffende product en zo min mogelijk configuratie vereisen. Daarnaast is het belangrijk dat de pipeline makkelijk toe te voegen is aan onze repositories. Een echte plug-en-play oplossing dus.

Deze tool wilden we gaan bouwen met GitHub Actions. Dit is een CI/CD-platform van GitHub waarmee pipelines gebouwd kunnen worden op basis van actions: herbruikbare stukjes code die één specifieke taak uitvoeren. Een action kan bijvoorbeeld een Python environment opzetten, unit tests uitvoeren, een Docker-image bouwen, een zelfgeschreven bash-script uitvoeren, en nog veel meer. Deze actions worden vervolgens in een workflow bestand aangeroepen, waar de configuratie en volgorde van uitvoering gedefinieerd worden. Deze bestanden zijn in YAML-formaat geschreven en vormen samen de CI/CD-pipelines (hierna workflows te noemen).

Niet scripten, maar software bouwen

We gingen aan de slag – de eerste stap was het aanmaken van een nieuwe repository op GitHub: basic-workflows. In deze repository kunnen we alle bouwblokjes en bijbehorende workflows ontwikkelen. De structuur is eenvoudig opgezet met twee mapjes:

  • actions – waar we alle losse stappen van onze workflows opslaan.
  • workflows – waar we de actions samenkomen tot volwaardige workflows die in onze repositories gebruikt kunnen worden.

Een SOLID aanpak

Om ons te helpen een toereikende tool te bouwen, beschouwen we het niet als setje scripts, maar meer als softwareproduct. We houden ons aan de algemene ontwerpprincipes zoals KISS (“keep it simple, stupid”), DRY (“don’t repeat yourself”) en SOLID; de vijf principes van softwareontwikkeling. Onderstaand de drie die voor ons relevant zijn:

  • Single responsibility: dit houdt in dat een object maar één taak moet hebben – dus een object dat A én B doet, moet gesplitst worden in twee klassen. Dit geldt voor alle workflowstappen die we bouwen. Die moeten allemaal maar één taak hebben.
  • Open-closed principe: dit houdt in dat objecten open moeten zijn voor uitbreiding, maar gesloten voor wijzigingen. Oftewel, een object moet uitgebreid kunnen worden zonder dat het verder aangepast hoeft te worden. Dit is belangrijk voor alle workflowbestanden, zodat we later nog stappen toe kunnen voegen zonder dat de hele workflow kapot gaat.
  • Interface segregation principe: een object zou nooit methodes moeten implementeren die het niet gebruikt. Dit is eigenlijk niet helemaal van toepassing gezien we geen interfaces gebruiken, maar de filosofie erachter is relevant. Wanneer we een workflow in een van onze repositories toepassen, is het niet de bedoeling dat deze workflow allerlei stappen bevat die niet gebruikt worden. Dit is de reden dat we verschillende workflows voor verschillende typen producten gebruiken. De Java API workflow hoeft immers geen Python linting uit te voeren.

Al deze principes zorgen ervoor dat een softwareproduct modulair, herbruikbaar, onderhoudbaar en uitbreidbaar is. Niet te vergeten dat de workflows hierdoor sneller en efficiënter zijn, wat op zijn beurt weer tijd scheelt.

Implementatie

Na de initiële opzet was het simpelweg een kwestie van functionaliteit inbouwen. Omdat dit van alles omvat – tests draaien, code scans, images bouwen, lambda’s zippen, alles uitrollen en meer – kostte dit natuurlijk wat tijd. Maar de moeite loont: het resultaat is een breed inzetbare tool die precies doet wat we voor ogen hadden.

Wanneer nieuwe code op een van de permanente branches (main, release, develop) komt, start deze workflow. Dan wordt automatisch een nieuwe versie gemaakt en uitgerold. Op dezelfde manier is een workflow voor de continuous delivery/deployment stap toegevoegd in elke repository waar nodig.

Onderstaand diagram toont hoe de implementatie van basic-workflows nieuwe code integreert in onze codebase en hoe features, bugs en hotfixes naar onze live omgevingen uitgerold worden:

Het stukje CI wordt door de python-integration workflow uitgevoerd, en het stukje CD door de python-delivery workflow. Twee soortgelijke workflows bestaan voor alle talen die we gebruiken en voor de Lambda-functies.

Vanuit een feature- of hotfix branch wordt de code middels een pull request naar develop gebracht. Vanuit deze pull request gaat de CI workflow draaien om de code te testen, scannen en te valideren. Wanneer dit geslaagd is wordt de merge handmatig uitgevoerd en wordt automatisch de C- workflow afgetrapt. Deze workflow bouwt een artifact of Docker image (afhankelijk van het type product) en deployt deze naar de relevante omgeving. Ook wordt er gelijk een corresponderende GitHub release gemaakt met behulp van GitVersion.

Vervolgens wordt de code (ook via pull requests) handmatig doorgevoerd naar release en main en wordt wederom automatisch de CD workflow afgetrapt. Dit zorgt ervoor dat we controle hebben over welke versies in welke omgeving terechtkomen, wat erg belangrijk is als je met test/acceptatie/productieomgevingen te maken hebt.

Conclusie

Het resultaat is een tool die ons enorm helpt: we kunnen in een handomdraai nieuwe code integreren en uitrollen naar de gewenste omgeving, het zorgt ervoor dat elke versie blijft bestaan in GitHub, en biedt daarmee de mogelijkheid om zeer snel en gemakkelijk een deployment terug te draaien naar een vorige versie. Ook zijn we vliegensvlug geworden in het opleveren van onze producten, waardoor we betere kwaliteit sneller kunnen leveren. En niet te vergeten – als er een keer iets in productie kapot gaat – hebben we het zo gefixt middels een hotfix. Al met al is het de moeite waard, een aanrader voor elk ontwikkelteam!

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*
Dit veld is bedoeld voor validatiedoeleinden en moet niet worden gewijzigd.

De productiviteit van je team in een hogere versnelling – dat kan met een geautomatiseerde oplossing voor integratie, levering en uitrol, welbekend als CI/CD (continuous integration, continuous delivery/deployment). Het is een vitaal onderdeel van elk volwassen ontwikkelteam. De behoefte aan een dergelijke oplossing was bij team BASIC bij Alliander groot, gezien wij veel producten beheren en bouwen: van API’s in Java tot libraries in Python met AWS Lambda functies als kers op de taart. Combineer je dat met drie deployment omgevingen, dan wordt een CI/CD implementatie broodnodig. Maar hoe zorg je dat deze implementatie met diverse talen en toepassing om kan gaan? Hoe hou je het geheel herbruikbaar, uitbreidbaar en onderhoudbaar? Wij hebben deze vragen beantwoord en de uitkomsten geïmplementeerd.

Software Engineer

Meer weten?

"*" geeft vereiste velden aan

Privacyverklaring*
Dit veld is bedoeld voor validatiedoeleinden en moet niet worden gewijzigd.

Dit artikel delen

Bekijk ook deze artikelen

– Wat is diabetes “type 1” ook alweer? Diabetes type 1 wordt gekenmerkt door een gebrek aan insulineproductie door de alvleesklier. In de meeste gevallen wordt dit veroorzaakt door een...
Er draait echter wel een stevige energiecentrale voor. Met de toename van AI-gebruik, stijgen ook de zorgen over de impact op het klimaat. Rekenen kost nu eenmaal energie, en AI...
Zelf loop ik al lange tijd met de vraag: Wat is de beste snelheid voor je elektrische auto, om zo snel mogelijk op je bestemming te komen? (Inclusief tijd gespendeerd...

Samen met ons bouwen aan een duurzame toekomst? Neem contact op!

Maak impact. Samen. Jij ook?

"*" geeft vereiste velden aan

Privacyverklaring*
Dit veld is bedoeld voor validatiedoeleinden en moet niet worden gewijzigd.

×

Welkom bij Infiniot! Wij helpen je graag verder op weg.

× Stel hier jouw vraag