Essayez sans attendre l'hébergement proposé par WordPress
-15% sur le premier mois avec le code 2025PRESS15AFF

Essayer maintenant

WordPress Composer Workflows : Automatiser le déploiement avec GitHub Actions

Bon, je vais être honnête avec vous : gérer un projet WordPress avec du code qui part dans tous les sens et des déploiements à la main, c’est le cauchemar assuré. Heureusement, on peut transformer tout ça en workflow professionnel grâce à Composer et GitHub Actions ! Dans cet article, je vous montre comment j’ai mis en place une chaîne de déploiement automatisée qui teste, build et déploie mes sites WordPress comme un chef.

Architecture d’un projet WordPress avec Composer

Quand on commence à travailler sérieusement avec WordPress, on se rend vite compte que l’installation classique via l’admin ou le téléchargement direct a ses limites. C’est là que Composer entre en jeu ! Cette approche moderne transforme complètement la façon dont on structure et maintient nos projets WordPress.

Structure moderne des dossiers

Fini le temps où tout était mélangé dans le dossier racine ! Avec Composer, on adopte une architecture plus propre et professionnelle :

mon-projet/
├── web/
│   ├── wp/              # WordPress core
│   ├── wp-content/
│   │   ├── themes/
│   │   ├── plugins/
│   │   └── uploads/
│   ├── wp-config.php
│   └── index.php
├── vendor/              # Dépendances Composer
├── composer.json
├── composer.lock
└── .gitignore

Cette structure sépare clairement le code WordPress (web/wp/) de notre configuration personnalisée. Le dossier web/ devient notre document root, tandis que les fichiers sensibles (comme composer.json) restent inaccessibles depuis le navigateur. C’est un énorme plus pour la sécurité !

Configuration du composer.json

Le fichier composer.json est le cœur de notre architecture. Voici un template complet que j’utilise régulièrement :

{
    "name": "mon-agence/mon-projet",
    "type": "project",
    "require": {
        "php": ">=7.4",
        "johnpbloch/wordpress-core": "^6.0",
        "johnpbloch/wordpress-core-installer": "^2.0",
        "wpackagist-plugin/advanced-custom-fields": "*",
        "wpackagist-plugin/yoast-seo": "*",
        "wpackagist-theme/twentytwentythree": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.0",
        "wp-coding-standards/wpcs": "^2.3"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://wpackagist.org"
        }
    ],
    "extra": {
        "wordpress-install-dir": "web/wp",
        "installer-paths": {
            "web/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
            "web/wp-content/themes/{$name}/": ["type:wordpress-theme"]
        }
    },
    "autoload": {
        "psr-4": {
            "MonProjet\\": "src/"
        }
    }
}

La clé repositories permet d’accéder à WPackagist, qui mirror tous les plugins et thèmes du répertoire WordPress. Les installer-paths définissent où installer chaque type de package. Plutôt pratique, non ?

Gestion des dépendances WordPress

Avec cette approche, WordPress devient une simple dépendance comme une autre ! Plus besoin de télécharger manuellement le core ou les plugins. Un simple composer install et tout est en place.

Pour ajouter un plugin, par exemple :

composer require wpackagist-plugin/contact-form-7

Pour mettre à jour WordPress :

composer update johnpbloch/wordpress-core

Les avantages sont énormes : versionning précis (fini les « quelle version j’avais déjà ? »), sécurité renforcée (les fichiers sensibles ne sont pas exposés), et maintenance simplifiée. Quand votre collègue récupère le projet, il fait juste composer install et boom, l’environnement est identique au vôtre. Plus d’excuses du type « ça marche chez moi » !

Gestion des plugins et thèmes via Composer

Maintenant qu’on a configuré notre projet WordPress avec Composer, on peut enfin gérer nos plugins et thèmes comme de vraies dépendances. Et croyez-moi, une fois qu’on a goûté à cette approche, difficile de revenir en arrière !

Le secret ? Utiliser wpackagist.org, un repository qui transforme automatiquement les plugins et thèmes du répertoire WordPress.org en packages Composer. C’est génial, car on peut installer n’importe quel plugin gratuit avec une simple commande.

Prenons un exemple concret. Pour installer Yoast SEO, au lieu de passer par l’interface WordPress, on fait ça :

composer require wpackagist-plugin/wordpress-seo

Pour un thème comme Twenty Twenty-Four :

composer require wpackagist-theme/twentytwentyfour

La différence entre require et require-dev ? C’est simple : require pour les dépendances nécessaires en production (vos plugins actifs), require-dev pour les outils de développement uniquement.

Je mets souvent Query Monitor en require-dev :

composer require --dev wpackagist-plugin/query-monitor

Comme ça, mes environnements de production restent propres.

Bon, parlons maintenant des plugins premium (ACF Pro, Gravity Forms, etc.). C’est là que ça se complique un peu. Ces plugins ne sont pas sur wpackagist, donc plusieurs solutions :

  1. Repository privé : Créer votre propre repository Composer
  2. Packages locaux : Déposer les .zip dans un dossier packages/
  3. Services tiers : Utiliser des solutions comme Composer Packages ou WP Pusher

Pour ACF Pro, je configure souvent un repository privé dans mon composer.json :

{
  "repositories": [
    {
      "type": "composer",
      "url": "https://connect.advancedcustomfields.com/v2/plugins"
    }
  ],
  "require": {
    "wpengine/advanced-custom-fields-pro": "^6.0"
  }
}

Pour les thèmes custom, deux approches : soit vous les versionnez dans un repository Git séparé (recommandé), soit vous les gérez localement. Dans le premier cas :

{
  "repositories": [
    {
      "type": "vcs",
      "url": "git@github.com:votre-compte/votre-theme.git"
    }
  ]
}

Les commandes de base ? composer install pour installer exactement ce qui est défini dans le composer.lock (parfait pour la production), composer update pour mettre à jour selon les contraintes définies.

Attention avec composer update : ça peut casser des choses ! Mieux vaut spécifier le package :

composer update wpackagist-plugin/wordpress-seo

Pour les versions, utilisez les contraintes Composer. ^5.0 accepte 5.x mais pas 6.0, ~5.2 accepte 5.2.x mais pas 5.3. Pour des plugins critiques, je fixe parfois la version exacte : "5.2.1" (mais c’est plus rigide pour les mises à jour de sécurité).

Un conseil : testez toujours vos mises à jour sur un environnement de staging avant la production. WordPress, c’est parfois capricieux !

Configuration GitHub Actions pour CI/CD

Alors là, on entre dans le vif du sujet ! GitHub Actions, c’est vraiment un game changer pour automatiser tout le processus de déploiement WordPress. J’ai mis du temps à m’y mettre (je restais sur du FTP manuel comme un sauvage), mais une fois qu’on a goûté à l’automatisation… impossible de revenir en arrière.

Workflow de base pour WordPress

Voici un template complet que j’utilise depuis des mois sur mes projets. Ce fichier va dans .github/workflows/deploy.yml :

name: WordPress CI/CD

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout code
      uses: actions/checkout@v3
      
    - name: Setup PHP
      uses: shivammathur/setup-php@v2
      with:
        php-version: '8.1'
        extensions: mysql, zip, gd
        tools: composer
        
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Install Composer dependencies
      run: composer install --no-dev --optimize-autoloader
      
    - name: Install NPM dependencies
      run: npm ci

Ce workflow se déclenche sur les pushs vers main et develop, plus les pull requests. C’est exactement ce qu’on veut : tester avant de merger, déployer automatiquement en production.

Variables d’environnement et secrets

Bon, parlons sécurité. Les secrets GitHub, c’est VITAL. Dans Settings > Secrets and variables > Actions, j’ajoute toujours :

  • SSH_PRIVATE_KEY : ma clé SSH pour accéder au serveur
  • SSH_HOST : l’adresse de mon serveur
  • SSH_USER : le nom d’utilisateur SSH
  • DB_PASSWORD : mot de passe de la base de données
  • WP_ENV : l’environnement (staging, production)

Pour les utiliser dans le workflow :

    - name: Deploy to server
      env:
        SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        SSH_HOST: ${{ secrets.SSH_HOST }}
        SSH_USER: ${{ secrets.SSH_USER }}
      run: |
        echo "$SSH_PRIVATE_KEY" | tr -d '\r' > /tmp/deploy_key
        chmod 600 /tmp/deploy_key
        rsync -avz --delete -e "ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no" \
          --exclude='.git' --exclude='node_modules' ./ $SSH_USER@$SSH_HOST:/var/www/html/

Attention : ne JAMAIS commiter de secrets dans le code. J’ai vu trop de projets compromis à cause de ça…

Tests de qualité de code

Les tests, c’est là que GitHub Actions devient vraiment puissant. Voici ma config PHPStan et PHPCS :

    - name: Run PHPStan analysis
      run: ./vendor/bin/phpstan analyse --no-progress
      
    - name: Run PHPCS coding standards
      run: ./vendor/bin/phpcs --standard=WordPress-Core wp-content/themes/mon-theme/
      
    - name: Run PHPUnit tests
      run: ./vendor/bin/phpunit
      env:
        WP_TESTS_DB_NAME: wordpress_test
        WP_TESTS_DB_USER: root
        WP_TESTS_DB_PASS: ''

J’ajoute aussi un setup MySQL pour les tests d’intégration :

    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: ''
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: wordpress_test
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

Si les tests échouent, le déploiement s’arrête. C’est exactement ce qu’on veut !

Build et préparation des assets

Pour les assets CSS/JS, j’utilise cette approche (avec webpack dans mon cas) :

    - name: Build production assets
      run: |
        npm run build:production
        
    - name: Optimize images
      run: npm run imagemin
      
    - name: Create deployment archive
      run: |
        tar -czf wordpress-build.tar.gz \
          --exclude='node_modules' \
          --exclude='.git' \
          --exclude='src' \
          --exclude='tests' \
          .

Je sépare les environnements avec des conditions :

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/develop'
    # ... étapes de déploiement staging
    
  deploy-production:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    # ... étapes de déploiement production

Et voilà ! Avec cette config, chaque push déclenche les tests, et si tout passe, le déploiement se fait automatiquement. Plus de stress, plus d’erreurs humaines. C’est du bonheur !

Tests automatisés et monitoring

Une fois votre workflow GitHub Actions en place, il est temps de passer aux choses sérieuses : s’assurer que votre code WordPress fonctionne correctement avant le déploiement. Et croyez-moi, après avoir déployé quelques bugs en production (oui, ça m’est arrivé !), vous comprendrez vite l’importance d’une stratégie de tests solide.

Intégration PHPUnit

PHPUnit reste l’outil de référence pour les tests unitaires en PHP, et WordPress ne fait pas exception. La configuration est relativement simple : on ajoute PHPUnit dans notre composer.json et on configure un fichier phpunit.xml adapté à WordPress.

"require-dev": {
    "phpunit/phpunit": "^9.0",
    "wp-cli/wp-cli-bundle": "^2.5"
}

Pour tester vos fonctions custom et vos hooks, la clé c’est de bien isoler la logique métier. Par exemple, si vous avez développé une fonction qui calcule des prix avec des remises :

public function testCalculateDiscount() {
    $price = 100;
    $discount = 20;
    $result = calculate_discount($price, $discount);
    $this->assertEquals(80, $result);
}

Attention cependant : tester des hooks WordPress nécessite souvent de mocker l’environnement WP. C’est là que les outils comme WP_Mock deviennent indispensables pour simuler les fonctions WordPress sans charger tout le core.

Tests fonctionnels avec Behat

Behat, c’est le complément parfait de PHPUnit. Là où PHPUnit teste vos fonctions individuellement, Behat teste le comportement global de votre site depuis la perspective de l’utilisateur. Et franchement, c’est bluffant de voir des scénarios écrits en langage naturel !

Voici un exemple de scénario Behat pour tester un formulaire de contact :

Feature: Contact form
  Scenario: Submit contact form
    Given I am on "/contact"
    When I fill in "name" with "John Doe"
    And I fill in "email" with "john@example.com"
    And I press "Send"
    Then I should see "Message sent successfully"

L’avantage ? Même votre client peut comprendre ce qui est testé. Pour WordPress, on utilise généralement Mink avec un driver comme Selenium pour automatiser un vrai navigateur. C’est un peu plus lourd à configurer, mais ça teste vraiment l’expérience utilisateur complète.

Déploiement staging et production

Bon, maintenant que vos tests passent, il faut déployer ! Et là, on a plusieurs écoles. Personnellement, j’utilise souvent rsync pour sa simplicité, mais Deployer PHP est une excellente alternative pour des déploiements plus sophistiqués.

Voici un exemple de script de déploiement avec rsync dans votre GitHub Action :

- name: Deploy to staging
  run: |
    rsync -avz --delete \
      --exclude-from='.deployignore' \
      ./ user@staging-server:/var/www/html/

Le fichier .deployignore est crucial : il évite de synchroniser les fichiers de développement (.git, tests/, node_modules/, etc.). Et surtout, déployez TOUJOURS d’abord en staging ! J’ai vu trop de projets où on déployait directement en production… jusqu’au jour où ça casse tout.

Stratégies de rollback

Et quand ça casse malgré tous vos tests ? Il faut pouvoir revenir en arrière rapidement. Ma stratégie favorite : utiliser des tags Git avec des sauvegardes automatiques de la base de données.

Avant chaque déploiement, on crée un backup :

#!/bin/bash
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > backup_$TIMESTAMP.sql
tar -czf files_backup_$TIMESTAMP.tar.gz wp-content/uploads/

Pour le rollback, on garde les 5 dernières versions déployées. Si la version courante pose problème, on revient simplement à la précédente avec git checkout et on restaure le backup correspondant.

Côté monitoring, New Relic reste une valeur sûre pour surveiller les performances, tandis que Sentry excelle pour traquer les erreurs PHP. L’intégration est simple : quelques lignes dans wp-config.php et vous avez une visibilité complète sur ce qui se passe en production. Et croyez-moi, ça change la vie quand vous devez investiguer un bug signalé par un utilisateur !