GitHub Actions is een automatiseringstool die je tests draait telkens wanneer je code pusht en, als alles groen is, je project automatisch naar de server deployt. Het leeft binnen je repository, dus er is geen aparte dienst om je voor aan te melden, en het komt met een royaal gratis quotum voor open source-projecten. In deze gids bouwen we een CI/CD-pipeline vanaf nul: eerst verhelderen we de begrippen, daarna schrijven we een echte test- en deploy-workflow.
Waarom CI/CD en GitHub Actions helpen
CI (Continuous Integration) betekent het automatisch bouwen en testen van elke codewijziging, zodat je een kapotte commit opvangt voordat hij überhaupt gemerged is. CD (Continuous Delivery/Deployment) betekent het automatisch uitleveren van code die de tests doorstaat naar een staging- of productieomgeving. De gecombineerde stroom heet een CI/CD-pipeline.
De handmatige cyclus van "lokaal tests draaien, bestanden via FTP uploaden, duimen" is traag en foutgevoelig. GitHub Actions maakt die cyclus herhaalbaar:
- Consistentie: de pipeline draait op een schone virtuele machine, wat het "het werkte op mijn machine"-probleem grotendeels wegneemt.
- Snelheid: jobs kunnen parallel draaien, dus lint, test en build vorderen tegelijk.
- Veiligheid: SSH-sleutels en tokens worden versleuteld opgeslagen in repository-secrets in plaats van hard-coded.
Kernbegrippen: workflow, job, step, action
De woordenschat van GitHub Actions is klein maar belangrijk:
- Workflow: een YAML-bestand in de map
.github/workflows/. Het bepaalt wanneer en wat er draait. - Event (trigger): de gebeurtenis die de workflow start —
push,pull_request, een geplandeschedule, of een handmatigeworkflow_dispatch. - Job: een groep stappen die op dezelfde runner draait. Jobs draaien standaard parallel en sequentieel met
needs. - Step: een enkel commando (
run) binnen een job, of een kant-en-klareuses-action. - Runner: de virtuele machine waarop de job draait, bijvoorbeeld
ubuntu-latest.
Je eerste workflow: tests draaien
Laten we een Node.js-project nemen. Maak .github/workflows/ci.yml in de root van de repository:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
actions/checkout@v4 klont je repo op de runner, setup-node installeert de juiste Node-versie en cache: npm cachet je dependencies. npm ci doet een schone installatie die strikt package-lock.json volgt — betrouwbaarder dan npm install in CI. Op het moment dat je dit bestand pusht, draaien de tests automatisch bij elke commit en pull request.
Meerdere versies testen met een matrix
Wil je een library tegen meerdere taalversies testen, dan vermenigvuldigt strategy.matrix één job:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
Deze workflow draait dezelfde tests parallel op Node 18, 20 en 22. Aan de PHP/Laravel-kant pas je hetzelfde idee toe met de shivammathur/setup-php-action om meerdere PHP-versies te proberen, en draai je daarna php artisan test.
Secrets en de deploy-job
De deploy-stap heeft toegang tot je server nodig, en dat betekent secrets. Schrijf nooit een SSH-privésleutel of API-token in de YAML. Maak in plaats daarvan een secret aan op GitHub onder Settings → Secrets and variables → Actions (bijvoorbeeld SSH_PRIVATE_KEY, SSH_HOST) en verwijs ernaar in de workflow met ${{ secrets.SSH_HOST }}.
Het onderstaande voorbeeld voegt een tweede job toe die deployt nadat de tests slagen. Dankzij needs: test draait de deploy alleen als de test-job slaagde, en de if-voorwaarde beperkt het tot pushes op main:
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy op de server via SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
cd ~/app
git pull origin main
composer install --no-dev -o
php artisan migrate --force
php artisan optimize
Hier is de deploy-strategie een eenvoudige "verbind met de server, pull, update"-stroom. Gebruik je Docker, dan zou je in plaats daarvan de image bouwen en naar een registry pushen (docker/build-push-action), en daarna de nieuwe image op de server pullen. Het principe blijft hetzelfde: configuratie in code, secrets in secrets.
Tips om de pipeline robuuster te maken
- Faal snel: maak lint en test aparte jobs vóór de deploy, zodat een rode test de deploy volledig blokkeert.
- Gebruik caching: dependency- en build-caches verkorten de pipelinetijd van minuten naar seconden.
- Pin action-versies: bind aan een vaste major-versie zoals
@v4; voor de gevoeligste projecten pin je aan een commit-SHA. - Concurrency: gebruik een
concurrency-blok om oudere runs van dezelfde branch te annuleren en overbodige deploys te voorkomen. - Zichtbaarheid: voeg een status-badge toe aan je README zodat je in één oogopslag ziet of de pipeline groen of rood is.
Veelgestelde vragen
Is GitHub Actions gratis?
Standaard runners zijn gratis voor publieke repositories. Private repositories krijgen een gratis maandelijks minutenquotum; zodra je dat overschrijdt, wordt er per minuut afgerekend. De meeste kleine en middelgrote projecten blijven comfortabel binnen het gratis quotum.
Waarom GitHub Actions in plaats van Jenkins of GitLab CI?
Staat je code al op GitHub, dan leeft Actions op dezelfde plek als je repo, dus je begint met nul infrastructuur. Jenkins biedt meer controle en plugins maar vereist dat je een server beheert. De keuze hangt af van waar je team werkt en hoeveel maatwerk je nodig hebt.
Wat gebeurt er als een deploy mislukt?
De job wordt rood, latere stappen draaien niet en GitHub stuurt je een melding. De logs tonen het exacte commando en de foutuitvoer. Voor veilige deploys ontwerp je je migraties omkeerbaar en gebruik je waar mogelijk een blue-green- of rolling-deploystrategie.
Wil je je pipeline opzetten of een bestaande deploy-stroom automatiseren? Ik help je je project naar een snelle, veilige en herhaalbare CI/CD-pipeline te brengen — neem contact op.