Een Magento 2 deployment die handmatig verloopt is een deployment die vroeg of laat misgaat. Automated testing, staging workflows en zero-downtime deploys via GitHub Actions — zo doe je dat.
Magento 2 CI/CD pipeline opzetten met GitHub Actions
Een deployment die handmatig verloopt is een deployment die vroeg of laat misgaat. Verkeerde branch, vergeten setup:upgrade, cache niet geleegd — de varianten zijn talrijk. Met een CI/CD pipeline via GitHub Actions wordt dat onmogelijk.
Wij zetten CI/CD in voor alle Magento 2 projecten die wij beheren. Het bespaart gemiddeld 2 uur per deployment en elimineert menselijke fouten bij productie-uitrol. Dit artikel legt de volledige pipeline uit.
Wat je leert in dit artikel
- De structuur van een professionele Magento 2 CI/CD pipeline
- Automated testing met PHPUnit en MFTF
- Staging en productie deployment workflows
- Zero-downtime deployment via symlink-strategie
- Secrets beheer in GitHub Actions
De structuur van de pipeline
Een Magento 2 pipeline bestaat uit drie fasen:
- Test — Code quality, unit tests, integration tests
- Build — Composer install, assets compileren, pakket maken
- Deploy — Uitrollen naar staging of productie
Push naar branch → Test → (bij merge naar main) Build → Deploy staging → Handmatige goedkeuring → Deploy productie
Dit is de mappenstructuur in je repository:
.github/
workflows/
test.yml # Draait bij elke push
deploy.yml # Draait bij merge naar main
hotfix.yml # Directe productie-deploy bij nood
Test workflow
De test workflow draait bij elke push naar elke branch. Hij blokkeert een merge als tests falen.
# .github/workflows/test.yml
name: Tests
on:
push:
branches-ignore:
- main
pull_request:
branches:
- main
- develop
jobs:
php-cs-fixer:
name: Code Style
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: PHP instellen
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
tools: cs2pr
- name: Composer cache
uses: actions/cache@v3
with:
path: ~/.composer/cache
key: composer-${{ hashFiles('composer.lock') }}
- name: Composer install
run: composer install --no-interaction --prefer-dist --no-progress
- name: PHP CS Fixer uitvoeren
run: vendor/bin/php-cs-fixer fix --dry-run --diff --format=checkstyle | cs2pr
phpstan:
name: Static Analysis
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: PHP instellen
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Composer install
run: composer install --no-interaction --prefer-dist --no-progress
- name: PHPStan uitvoeren
run: vendor/bin/phpstan analyse --memory-limit=1G
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: PHP instellen
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
coverage: xdebug
- name: Composer install
run: composer install --no-interaction --prefer-dist --no-progress
- name: PHPUnit uitvoeren
run: vendor/bin/phpunit --testsuite unit --coverage-clover coverage.xml
- name: Coverage uploaden
uses: codecov/codecov-action@v3
with:
files: coverage.xml
Deploy workflow
De deploy workflow draait alleen bij een merge naar main. Hij deployt eerst naar staging, wacht op handmatige goedkeuring en deployt dan naar productie.
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches:
- main
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: PHP instellen
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
- name: Composer install (productie)
run: composer install --no-dev --optimize-autoloader --no-interaction
- name: Frontend assets compileren
run: |
npm ci
npm run build
- name: Deployment-pakket maken
run: |
tar -czf deploy.tar.gz \
--exclude='.git' \
--exclude='node_modules' \
--exclude='var/cache' \
--exclude='var/page_cache' \
--exclude='var/session' \
.
- name: Pakket uploaden als artifact
uses: actions/upload-artifact@v3
with:
name: deploy-package
path: deploy.tar.gz
retention-days: 1
deploy-staging:
name: Deploy naar Staging
needs: build
runs-on: ubuntu-latest
environment: staging
steps:
- name: Pakket downloaden
uses: actions/download-artifact@v3
with:
name: deploy-package
- name: SSH-sleutel instellen
run: |
mkdir -p ~/.ssh
echo "${{ secrets.STAGING_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan ${{ secrets.STAGING_HOST }} >> ~/.ssh/known_hosts
- name: Uitrollen naar staging
run: |
scp deploy.tar.gz ${{ secrets.STAGING_USER }}@${{ secrets.STAGING_HOST }}:/tmp/
ssh ${{ secrets.STAGING_USER }}@${{ secrets.STAGING_HOST }} 'bash -s' << 'ENDSSH'
set -e
RELEASE_DIR="/var/www/magento/releases/$(date +%Y%m%d%H%M%S)"
mkdir -p $RELEASE_DIR
tar -xzf /tmp/deploy.tar.gz -C $RELEASE_DIR
# Gedeelde mappen koppelen
ln -nfs /var/www/magento/shared/env.php $RELEASE_DIR/app/etc/env.php
ln -nfs /var/www/magento/shared/media $RELEASE_DIR/pub/media
# Magento-setup uitvoeren
php $RELEASE_DIR/bin/magento setup:upgrade --keep-generated
php $RELEASE_DIR/bin/magento setup:di:compile
php $RELEASE_DIR/bin/magento setup:static-content:deploy nl_NL en_US -f
# Symlink wisselen (zero-downtime)
ln -nfs $RELEASE_DIR /var/www/magento/current
# Cache legen
php /var/www/magento/current/bin/magento cache:flush
ENDSSH
deploy-production:
name: Deploy naar Productie
needs: deploy-staging
runs-on: ubuntu-latest
environment: production # Vereist handmatige goedkeuring in GitHub
steps:
- name: Pakket downloaden
uses: actions/download-artifact@v3
with:
name: deploy-package
- name: SSH-sleutel instellen
run: |
mkdir -p ~/.ssh
echo "${{ secrets.PROD_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan ${{ secrets.PROD_HOST }} >> ~/.ssh/known_hosts
- name: Uitrollen naar productie
run: |
scp deploy.tar.gz ${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}:/tmp/
ssh ${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }} 'bash -s' << 'ENDSSH'
set -e
RELEASE_DIR="/var/www/magento/releases/$(date +%Y%m%d%H%M%S)"
mkdir -p $RELEASE_DIR
tar -xzf /tmp/deploy.tar.gz -C $RELEASE_DIR
ln -nfs /var/www/magento/shared/env.php $RELEASE_DIR/app/etc/env.php
ln -nfs /var/www/magento/shared/media $RELEASE_DIR/pub/media
php $RELEASE_DIR/bin/magento setup:upgrade --keep-generated
php $RELEASE_DIR/bin/magento setup:di:compile
php $RELEASE_DIR/bin/magento setup:static-content:deploy nl_NL en_US -f
ln -nfs $RELEASE_DIR /var/www/magento/current
php /var/www/magento/current/bin/magento cache:flush
# Opruimen: bewaar alleen de laatste 5 releases
ls -dt /var/www/magento/releases/*/ | tail -n +6 | xargs rm -rf
ENDSSH
Zero-downtime deployment: de symlink-strategie
De deployment hierboven gebruikt een symlink-strategie. De serverstructuur ziet er zo uit:
/var/www/magento/
current -> releases/20240315143022/ # Symlink naar huidige release
releases/
20240315143022/ # Huidige release
20240314091500/ # Vorige release (rollback-kandidaat)
20240313162011/ # Oudere release
shared/
env.php # Wordt gedeeld tussen alle releases
media/ # Productafbeeldingen, gedeeld
Nginx of Apache wijst naar /var/www/magento/current/. Wanneer je de symlink wisselt, is de nieuwe release onmiddellijk actief. Geen downtime.
Terugdraaien gaat ook snel:
# Rollback naar vorige release
ln -nfs /var/www/magento/releases/20240314091500 /var/www/magento/current
php /var/www/magento/current/bin/magento cache:flush
Secrets beheer
Sla nooit credentials op in je workflow-bestanden. Gebruik GitHub Secrets. Ga naar je repository → Settings → Secrets and variables → Actions.
Aan te maken secrets per environment:
| Secret | Beschrijving |
|---|---|
STAGING_HOST | IP-adres of hostname staging-server |
STAGING_USER | SSH-gebruikersnaam |
STAGING_SSH_KEY | Private SSH-sleutel (zonder passphrase) |
PROD_HOST | IP-adres of hostname productie |
PROD_USER | SSH-gebruikersnaam productie |
PROD_SSH_KEY | Private SSH-sleutel productie |
COMPOSER_AUTH | JSON met Magento auth-credentials |
De COMPOSER_AUTH secret gebruik je om Magento packages te downloaden:
- name: Composer authenticatie instellen
run: echo '${{ secrets.COMPOSER_AUTH }}' > ~/.composer/auth.json
Veelgemaakte fouten
setup:di:compileop de server draaien — Dit kost 5-10 minuten en geeft downtime. Compileer assets in de build-stap en deploy het gecompileerde resultaat.- Geen environment protection rules — Zonder protection rules kan iedereen een deploy naar productie triggeren. Stel required reviewers in via GitHub Environments.
- Secrets in workflow-output loggen — GitHub maskeert bekende secrets automatisch, maar
echo $VARIABLEmet een afgeleid waarde logt wel gewoon. Wees voorzichtig met debug-logging.
Conclusie
Een CI/CD pipeline voor Magento 2 met GitHub Actions is geen luxe. Het is de enige manier om betrouwbaar en snel te deployen zonder menselijke fouten. De setup in dit artikel is productie-klaar en schaalbaar.
De symlink-strategie geeft je zero-downtime deployments en een betrouwbaar rollback-mechanisme. De environment protection in GitHub zorgt dat niemand per ongeluk naar productie deployt.
Lees ook onze aanpak voor Magento 2 updatestrategieën voor meer context over veilig updaten. Meer weten over onze Magento 2 diensten? Bekijk onze Magento-pagina. Voor hosting met ingebouwde CI/CD-ondersteuning is Hypernode een sterke optie.
Wil je een professionele CI/CD pipeline voor je Magento 2 webshop? Neem contact op — wij helpen je verder.

Geschreven door Ruthger Idema
15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.
Meer over ons team →