CI/CD, branch protection en ITIL change management: DevOps in de praktijk met GitLab (deel 3 van 3)

Dit is het laatste deel van een driedelige serie over version control, branching en CI/CD. In deel 1 stonden version control, Git, branching strategieën en versienummering centraal. In deel 2 ging het over merge requests: de plek waar kwaliteit daadwerkelijk wordt afgedwongen. In dit derde, en laatste deel leg ik de koppeling naar CI/CD, laat ik zien hoe je branch protection rules concreet maakt, en behandel ik de vaak onderschatte relatie tussen ITIL change management en CI/CD.

De koppeling met DevOps en CI/CD

Version control, branching en merge requests zijn los te begrijpen, maar hun waarde ontstaat pas echt in samenhang met een CI/CD-pijplijn. Een CI/CD-pijplijn is het geautomatiseerde proces dat software (en optioneel de bijbehorende infrastructuur) van commit naar releasebare uitkomst brengt — herhaalbaar, betrouwbaar, snel en efficiënt. Alles wat nodig is om releasability te bereiken hoort daarin thuis: unit- en acceptatietests, integratie, versiebeheer, eventuele goedkeuringen (denk ook aan change approval / CAB), en elke andere eis die gesteld wordt voordat software veilig naar productie kan.

In een GitLab-omgeving loopt dat in de praktijk zo:

  1. Een ontwikkelaar maakt een featurebranch aan.
  2. Bij elke push draaien code-kwaliteits- en security-checks.
  3. Zodra die kwaliteitspoort geslaagd is, volgen (geautomatiseerde) tests.
  4. De ontwikkelaar opent een merge request (MR); de pipeline draait opnieuw, nu in de context van de MR.
  5. Code review vindt plaats binnen de MR, met eventueel verplichte approvals.
  6. Bij goedkeuring én een groene pipeline wordt de MR samengevoegd — direct, of via een merge train bij hoge doorvoersnelheid.
  7. De hoofdbranch triggert de uitrol, vaak automatisch en rekening houdend met change approval (en eventueel Change Advisory Board (CAB)).
  8. Feature flags bepalen welke functionaliteit daadwerkelijk zichtbaar wordt voor gebruikers.

Branch protection rules zijn hierin geen bijzaak: ze zorgen ervoor dat niemand — bewust of per ongeluk — direct naar main pusht, dat een pipeline verplicht moet slagen, en dat approvals niet omzeild kunnen worden. Dat is waar “we hebben een branching strategie” verandert in “onze branching strategie kán niet doorbroken worden”.

Verdieping: branch protection rules concreet gemaakt

Een branch protection rule is een instelling op een branch — meestal main — die afdwingt hoe wijzigingen daar mogen belanden. Zonder deze regels is elke afspraak die je in dit artikel leest optioneel: “we pushen niet direct naar main” is een goede intentie tot iemand het toch doet, bewust of per ongeluk om 17:58 op een vrijdag. Met branch protection wordt het technisch onmogelijk, niet alleen sociaal ongewenst.

De meest gebruikte regels in GitLab zijn:

  • Geen directe push naar main — wijzigingen kunnen alleen via een merge request binnenkomen.
  • Pipeline moet slagen — een MR kan pas gemerged worden als de bijbehorende pipeline groen is.
  • Minimaal N approvals — bijvoorbeeld twee reviewers, of één als het om een kleine bugfix gaat.
  • Code-owner approval verplicht — voor gevoelige mappen (denk aan /infra of /payments) moet iemand uit een specifiek team akkoord geven, ongeacht wie de wijziging maakt.
  • Geen force push en geen verwijdering — de geschiedenis van main blijft intact en herleidbaar.
  • Beperking op wie mag mergen — bijvoorbeeld alleen rol Maintainers, niet elke Developer.

Je kunt deze regels handmatig instellen via de GitLab-projectinstellingen, maar bij meerdere repositories wordt dat al snel inconsistent — het ene team vergeet iets, het andere wijkt af “omdat het sneller werkte”. Daarom codificeren steeds meer teams hun branch protection net zo goed als hun infrastructuur, bijvoorbeeld met Terraform en de GitLab-provider:

resource "gitlab_branch_protection" "main" {
  project                        = gitlab_project.app.id
  branch                         = "main"
  push_access_level              = "no one"      # niemand mag direct pushen
  merge_access_level             = "maintainer"   # alleen maintainers mogen mergen
  allow_force_push                = false
  code_owner_approval_required    = true
}

Wie precies goedkeuring moet geven voor welke bestanden, leg je vast in een CODEOWNERS-bestand in de root van de repository:

# CODEOWNERS
# Wijzigingen aan betaalintegraties vereisen goedkeuring van het finance-team
/src/payments/    @finance-team

# Infrastructuurwijzigingen vereisen goedkeuring van het platform-team
/infra/           @platform-team

# De rest van de codebase: standaard reviewers
*                 @team-backend

Het mooie hiervan: deze regel is zelf ook onderdeel van versiebeheer. Een wijziging aan wie mag goedkeuren, gaat op zijn beurt weer via een merge request — inclusief review. Branch protection controleert zichzelf.

Om dit helemaal concreet te maken: hier is een vereenvoudigd .gitlab-ci.yml dat laat zien hoe branch protection, de kwaliteitspoorten en de uitrol in de praktijk samenkomen:

YAML

stages:
- build
- test
- quality
- security
- deploy-staging
- deploy-production

build-job:
stage: build
script:
- echo "Applicatie bouwen..."
- make build
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'

unit-tests:
stage: test
script:
- echo "Unit tests draaien..."
- make test-unit
coverage: '/Total coverage:\s*(\d+(?:\.\d+)?%)/'
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'

code-quality:
stage: quality
script:
- echo "Linting en statische analyse..."
- make lint
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'

security-scan:
stage: security
script:
- echo "SAST en dependency scan..."
- make security-scan
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'

deploy-staging:
stage: deploy-staging
script:
- echo "Uitrollen naar staging..."
- make deploy ENV=staging
environment:
name: staging
rules:
- if: '$CI_COMMIT_BRANCH == "main"'

deploy-production:
stage: deploy-production
script:
- echo "Uitrollen naar productie..."
- make deploy ENV=production
environment:
name: production
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual

Alles tot en met security-scan draait volautomatisch bij elke merge request. deploy-staging gebeurt automatisch zodra de MR is samengevoegd met main. Alleen deploy-production staat op when: manual — iemand moet bewust op de knop drukken. Combineer dat met een protected environment (zodat alleen een bepaalde rol die knop ziet) en je hebt exact het evenwicht tussen snelheid en controle dat hierna in de ITIL-verdieping aan bod komt.

Verdieping: ITIL change management en CI/CD — spanning of aanvulling?

Voor organisaties die van een traditionele ITIL-inrichting komen, voelt CI/CD in eerste instantie als een bedreiging van change control: als code binnen minuten naar productie kan, waar blijft dan de Change Advisory Board (CAB)?

Het antwoord zit in een onderscheid dat ITIL zelf al maakt tussen typen wijzigingen:

  • Standaardwijzigingen (standard changes) zijn vooraf goedgekeurd, laag risico, en volgen een bekend, herhaalbaar patroon. De meeste reguliere featurewijzigingen die via een geautomatiseerde pipeline met volledige testdekking gaan, vallen hierin — mits dat vooraf is afgestemd met de organisatie die change management inricht. De “goedkeuring” zit dan in het ontwerp van de pipeline zelf: elke wijziging die de kwaliteitspoorten haalt, is per definitie akkoord.
  • Normale wijzigingen (normal changes) hebben wél een expliciete, individuele beoordeling nodig — bijvoorbeeld bij een hoog-risico wijziging, een aanpassing aan kritieke infrastructuur, of iets dat buiten een vooraf gedefinieerde standaardwijziging valt.

De praktische vertaling naar een pipeline is niet “overal een handmatige stap tussen zetten”, maar juist het tegenovergestelde: bouw één bewuste handmatige goedkeuringsstap in vóór de productie-uitrol, in plaats van vóór elke stap in het proces. Dat is precies wat de deploy-production-job met when: manual in het pipeline-voorbeeld hierboven doet — gecombineerd met een protected environment, waarbij alleen specifieke rollen (bijvoorbeeld een change manager of product owner) die job mogen starten. Zo blijft alles vóór dat punt (bouwen, testen, security-scannen, zelfs uitrollen naar staging) volledig geautomatiseerd en snel, terwijl de daadwerkelijke productievrijgave een bewust, auditeerbaar moment blijft.

Dat is meteen de connectie met commit-berichten en MR-beschrijvingen die verwijzen naar een work-item: die traceerbaarheid is precies wat een auditor of CAB nodig heeft om achteraf te kunnen reconstrueren wát er is gewijzigd, waaróm, en wíe akkoord heeft gegeven — zonder dat daarnaast nog een handmatig logboek hoeft te bestaan.

In de praktijk gaat deze koppeling vaak nog een stap verder dan een handmatige job in de pipeline. Veel organisaties hebben hun change management al belegd in een tool als ServiceNow, en die vervang je niet zomaar door een pipeline-stap — dat wíl je meestal ook niet, want ServiceNow blijft vaak de plek waar de organisatiebrede change-administratie, audit-trail en CAB-besluitvorming samenkomen. Voor dit soort situaties bestaan kant-en-klare integraties tussen ServiceNow en GitLab: de pipeline kan bij het bereiken van de deploy-production-stap automatisch een change-record aanmaken, of bij een standaardwijziging direct koppelen aan een vooraf goedgekeurd sjabloon. De when: manual-job wacht dan niet op een los klikje van een mens in GitLab, maar op de goedkeuringsstatus van dat change-record in ServiceNow zelf. Zo voedt het CI/CD-proces het change-managementproces, in plaats van er los naast te bestaan — en verdwijnt het handmatig aanmaken (en vaak ook het handmatig goedkeuren) van change-tickets geleidelijk uit het proces, zonder dat de governance die ITIL vraagt verloren gaat.

Kortom: ITIL en CI/CD staan niet haaks op elkaar. De spanning ontstaat pas wanneer change management wordt ingericht als een uniforme, handmatige stap voor élke wijziging, ongeacht risico. Door onderscheid te maken tussen standaard- en normale wijzigingen, en de goedkeuring te verplaatsen naar één expliciete, geconfigureerde stap in de pipeline — desnoods gekoppeld aan het bestaande change-systeem — houd je zowel de snelheid van CI/CD als de auditeerbaarheid die ITIL vereist.

Praktische do’s en don’ts

Vóór het committen

  • Werk in kleine stappen; commit kleine, behapbare wijzigingen in plaats van hele features in één keer.
  • Overweeg Test Driven Development (TDD) om dekking en codekwaliteit te verhogen.
  • Draai lokale tests vóór je commit, zodat je fouten vroeg opvangt.
  • Automatiseer testen op elke commit.

Committen en integreren

  • Commit frequent — richt op elke 15 minuten — en bekijk testresultaten binnen 5 minuten.
  • Neem zelf verantwoordelijkheid voor het verifiëren van je wijziging.
  • Maak code review een vast onderdeel van je workflow, geen uitzondering.
  • Merge frequent naar main/trunk.

Bij falende builds

  • Streef ernaar falende checks binnen 15 minuten op te lossen; lukt dat niet, revert (draai de aanpassing terug) dan om de ontwikkelstroom veilig te houden.
  • Is onduidelijk welke wijziging de fout veroorzaakte? Zoek dit sámen met teamgenoten snel uit.
  • Snelle detectie en herstel wegen zwaarder dan perfectionisme — het doel is dat de software continu releasebaar blijft.

Branching en workflow

  • Begin met een eenvoudig branchmodel, documenteer het, en pas het aan naarmate het team groeit.
  • Houd featurebranches kortlevend (dagen, geen weken en zeker geen maanden of langer).
  • Zet branch protection rules op om fouten te voorkomen.

Automatisering en levering

  • Gebruik een CI/CD-pipeline om bouwen, testen en uitrollen te automatiseren.
  • Koppel CI/CD met Change Management voor een naadloze ervaring en optimale traceerbaarheid (compliance/ wet- en regelgeving).

Vermijd

  • Overmatig complexe workflows.
  • Langlevende featurebranches.
  • Handmatig uitrollen zonder versiebeheer.
  • Code reviews overslaan omdat iets “urgent” is.
  • Direct pushen naar main of productie.
  • Branches laten staan nadat ze gemerged zijn.
  • Falende tests in de pipeline negeren.

Samenvatting van de serie

Version control is het fundament van elke CI/CD-implementatie. Branching strategieën kies je op basis van teamvolwassenheid, releaseritme en projectbehoefte — niet op basis van wat “modern” klinkt of lekker bekt. Versienummering via SemVer geeft betekenis aan elke release, zodat iedereen zonder de changelog te lezen weet hoeveel risico een upgrade met zich meebrengt. Merge requests zijn de plek waar kwaliteit daadwerkelijk wordt afgedwongen, niet slechts besproken. En pas wanneer al deze elementen expliciet zijn afgesproken én verankerd in je branch protection rules en pipeline-configuratie, wordt CI/CD meer dan een verzameling scripts — dan wordt het een betrouwbare en robuuste manier van werken, die bovendien ruimte laat voor bestaande change management-kaders zoals ITIL.

Begin eenvoudig, documenteer je aanpak, en laat je branching- en mergestrategie meegroeien met de automatiseringsvolwassenheid van je team.

Meer weten?

Heb je deze serie met plezier gelezen, en loop je in je eigen team of organisatie tegen vergelijkbare vraagstukken aan — een branching strategie die niet meer past, een pipeline die opnieuw ingericht moet worden, of een discussie over hoe CI/CD, DevOps en change management (ITIL, ServiceNow) zich tot elkaar verhouden? Dan denk ik graag met je mee. Of het nu gaat om een concreet advies, een sparringspartner bij het maken van de juiste keuzes, of begeleiding bij het daadwerkelijk doorvoeren van de verbeteringen: neem gerust contact op via bertrand@deneveit.nl — ik hoor graag waar je tegenaan loopt.


Disclaimer: Dit artikel is uitsluitend bedoeld voor informatieve en educatieve doeleinden. De beschreven werkwijzen en voorbeelden weerspiegelen ervaringen opgedaan in de praktijk. De genoemde tools en platforms (waaronder GitLab, ServiceNow en Terraform) zijn gekozen ter illustratie van het onderliggende principe; de auteur is niet gelieerd aan welke van deze partijen dan ook. Codevoorbeelden zijn vereenvoudigd weergegeven en dienen ter illustratie, niet als kant-en-klare implementatie of template. Voor toepassing in uw specifieke situatie wordt professioneel advies aanbevolen. Dit artikel is tot stand gekomen met assistentie van een AI-systeem. De technische implementatie, inhoudelijke keuzes, conclusies en eindredactie zijn volledig van de auteur.

Photo by Annie Spratt on Unsplash