Magento 2 CI/CD pipeline opzetten met GitHub Actions
Terug naar blog

Magento 2 CI/CD pipeline opzetten met GitHub Actions

AuthorRuthger Idema
14 april 202612 min leestijd

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:

  1. Test — Code quality, unit tests, integration tests
  2. Build — Composer install, assets compileren, pakket maken
  3. 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.

yaml
# .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.

yaml
# .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:

bash
# 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:

SecretBeschrijving
STAGING_HOSTIP-adres of hostname staging-server
STAGING_USERSSH-gebruikersnaam
STAGING_SSH_KEYPrivate SSH-sleutel (zonder passphrase)
PROD_HOSTIP-adres of hostname productie
PROD_USERSSH-gebruikersnaam productie
PROD_SSH_KEYPrivate SSH-sleutel productie
COMPOSER_AUTHJSON met Magento auth-credentials

De COMPOSER_AUTH secret gebruik je om Magento packages te downloaden:

yaml
- name: Composer authenticatie instellen
  run: echo '${{ secrets.COMPOSER_AUTH }}' > ~/.composer/auth.json

Veelgemaakte fouten

  1. setup:di:compile op de server draaien — Dit kost 5-10 minuten en geeft downtime. Compileer assets in de build-stap en deploy het gecompileerde resultaat.
  2. Geen environment protection rules — Zonder protection rules kan iedereen een deploy naar productie triggeren. Stel required reviewers in via GitHub Environments.
  3. Secrets in workflow-output loggen — GitHub maskeert bekende secrets automatisch, maar echo $VARIABLE met 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.
Ruthger Idema

Geschreven door Ruthger Idema

15+ jaar ervaring in e-commerce development. Gespecialiseerd in Magento, Shopify en Laravel maatwerk.

Meer over ons team →
Deel dit artikel:

Wil je jouw e-commerce naar het volgende niveau?

Plan een vrijblijvend gesprek met onze experts over Magento, Shopify of Laravel maatwerk.

Plan een Tech Check