Combien de fois avez-vous déployé un thème WordPress à la main, en FTP, en croisant les doigts pour que rien ne casse en production ? Combien d’équipes travaillent encore avec un fichier deploy.sh lancé manuellement depuis un terminal, sans filet ? En 2026, cette époque appartient au passé — du moins pour ceux qui ont adopté GitHub Actions. Cette plateforme d’automatisation native à GitHub transforme chaque push en un pipeline reproductible, traçable et sécurisé. Dans ce tutoriel, on construit de zéro un workflow complet pour déployer un site WordPress sur un serveur mutualisé ou VPS, avec tests, vérification de syntaxe PHP et notification en cas d’erreur.

Pourquoi GitHub Actions plutôt qu’un script FTP classique

La tentation du script shell est forte : quelques lignes, un lftp ou rsync, et le tour est joué. Le problème surgit dès que l’équipe grossit ou que le projet devient critique. Qui a lancé le dernier déploiement ? Depuis quelle version ? Le build PHP a-t-il été vérifié avant la mise en ligne ?

GitHub Actions répond à ces questions par design. Chaque workflow est un fichier YAML versionné dans le dépôt. L’historique des runs est conservé, les logs sont accessibles, et les secrets (mot de passe FTP, clé SSH) sont chiffrés dans les Encrypted Secrets de GitHub — jamais en clair dans le code. C’est la différence entre un déploiement artisanal et un processus d’ingénierie logicielle.

Pour WordPress spécifiquement, l’intérêt est double. D’un côté, vous automatisez le déploiement du thème ou du plugin maison. De l’autre, vous pouvez y brancher des outils comme phpcs (vérification des standards de codage WordPress), des tests unitaires avec PHPUnit, ou une vérification de la syntaxe avant que le moindre fichier n’arrive sur le serveur.

Structure du projet WordPress pour CI/CD

Avant d’écrire le workflow, le dépôt doit être organisé de façon à distinguer ce qui part en production de ce qui reste en développement. Une structure typique pour un thème enfant ou un plugin custom :

mon-projet-wp/
├── .github/
│   └── workflows/
│       └── deploy.yml
├── src/
│   ├── functions.php
│   ├── style.css
│   └── templates/
├── tests/
│   └── test-functions.php
├── composer.json
└── phpcs.xml

Le dossier .github/workflows/ contient les workflows YAML. Le reste du projet suit les conventions WordPress : functions.php, style.css pour le thème, composer.json pour les dépendances PHP. Cela permet d’utiliser composer install dans le pipeline sans friction.

Créer le workflow GitHub Actions pas à pas

Voici le fichier .github/workflows/deploy.yml complet, annoté section par section :

name: Deploy WordPress Theme

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  lint-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup PHP 8.2
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'
          tools: composer, phpcs

      - name: Install Composer dependencies
        run: composer install --no-dev --optimize-autoloader

      - name: Run PHP syntax check
        run: find src/ -name "*.php" -exec php -l {} ;

      - name: Run PHPCS (WordPress Coding Standards)
        run: phpcs --standard=WordPress src/

      - name: Deploy via FTP
        uses: SamKirkland/FTP-Deploy-Action@v4.3.5
        with:
          server: ${{ secrets.FTP_HOST }}
          username: ${{ secrets.FTP_USER }}
          password: ${{ secrets.FTP_PASS }}
          local-dir: ./src/
          server-dir: /public_html/wp-content/themes/mon-theme/
          exclude: |
            **/.git*
            **/node_modules/**
            **/tests/**

      - name: Purge cache via WP-CLI (optionnel)
        run: |
          curl -s "${{ secrets.SITE_URL }}/wp-json/purge-cache"             -H "Authorization: Bearer ${{ secrets.WP_TOKEN }}" || true

Analysons les points clés. Le déclencheur on: push: branches: [main] garantit que seul le code validé sur la branche principale déclenche un déploiement. workflow_dispatch permet un lancement manuel depuis l’interface GitHub, pratique pour un hotfix urgent. L’action shivammathur/setup-php est devenue le standard pour configurer PHP dans GitHub Actions : elle supporte les versions 7.4 à 8.4 et installe Composer et phpcs en une ligne.

Configurer les secrets GitHub correctement

Les identifiants ne doivent jamais apparaître dans le YAML. GitHub propose deux niveaux de secrets :

Repository secrets — accessibles uniquement depuis le dépôt concerné. Idéal pour les projets monorepo ou les credentials propres à un seul site.

Organization secrets — partagés entre plusieurs dépôts d’une organisation GitHub. Parfait pour les agences qui gèrent plusieurs sites WordPress avec le même hébergeur.

Pour ajouter un secret : Settings → Secrets and variables → Actions → New repository secret. Dans notre workflow, on a besoin de : FTP_HOST, FTP_USER, FTP_PASS, SITE_URL (pour la purge de cache), et optionnellement WP_TOKEN.

Un piège fréquent : les mots de passe qui contiennent des caractères spéciaux comme (, & ou $. GitHub les échappe correctement dans les secrets, mais certaines actions FTP peuvent mal les interpréter. Testez toujours un premier déploiement en mode dry-run si l’action le supporte, ou vérifiez les logs du run pour repérer une erreur d’authentification.

Ajouter les tests PHPUnit avant le déploiement

Un déploiement automatisé sans tests, c’est un script qui vous amène en production sans vérifier si la voiture freine encore. PHPUnit s’intègre facilement dans le pipeline :

      - name: Run PHPUnit tests
        run: |
          composer require --dev phpunit/phpunit ^11
          ./vendor/bin/phpunit tests/ --testdox

Ce step se place avant le step FTP. Si les tests échouent, le workflow s’arrête et le déploiement n’a jamais lieu. Pour les plugins WordPress, la librairie wp-phpunit (anciennement wp-cli/scaffold) permet de bootstrapper un environnement WordPress minimal pour les tests d’intégration. Sur GitHub Actions, on peut même lancer MySQL en service pour tester les requêtes WP_Query :

    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: wordpress_test
        options: --health-cmd="mysqladmin ping" --health-interval=10s

Déploiements conditionnels : staging vs production

Une seule branche qui déploie directement en production est risquée dès qu’une équipe collabore. Le pattern recommandé est d’utiliser deux environnements GitHub (Environments) avec des règles de protection différentes :

  • staging — déclenché sur les push vers develop, déploie sur le sous-domaine staging.monsite.com
  • production — déclenché sur les push vers main, avec une règle Required reviewers qui bloque le déploiement tant qu’un revieweur n’a pas approuvé

Les Environments GitHub permettent aussi de définir des secrets différents par environnement (FTP de staging séparé de celui de production), une bonne pratique de sécurité ignorée dans trop de projets WordPress.

Aller plus loin : notifications Slack et rollback automatique

Un pipeline de déploiement professionnel inclut deux dernières briques. D’abord, les notifications : une action slackapi/slack-github-action peut envoyer un message dans un canal dédié à chaque déploiement réussi ou échoué. En agence, c’est la différence entre découvrir un problème par un client et le voir dans Slack avant lui.

Ensuite, le rollback. FTP ne gère pas nativement les rollbacks. La solution propre est de déployer dans un répertoire versionné (/themes/mon-theme-v1.2.3/), puis de changer un symlink atomique. Sur un hébergement mutualisé sans accès SSH, une alternative est de maintenir une archive ZIP du déploiement précédent sur le serveur et de la restaurer via un script PHP déclenché par webhook en cas de détection d’erreur (monitoring de la page d’accueil avec curl).

GitHub Actions a transformé la manière dont les équipes WordPress maintiennent leurs projets. Ce qui prenait 20 minutes de manipulation manuelle se fait maintenant en 3 minutes de pipeline, de façon reproductible, avec un historique complet et sans risque de déployer le mauvais fichier. Pour un thème WordPress ou un plugin sur mesure, c’est l’investissement de configuration le plus rentable de l’année.

Optimiser les performances du pipeline : cache et artefacts

Un pipeline qui repart de zéro à chaque run — téléchargement des dépendances Composer, setup PHP, installation de phpcs — peut prendre plusieurs minutes. GitHub Actions propose deux mécanismes pour accélérer les runs suivants.

Le cache Composer évite de retélécharger les packages à chaque push. Il suffit d’ajouter ce step avant composer install :

      - name: Cache Composer packages
        uses: actions/cache@v4
        with:
          path: vendor
          key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-

La clé de cache utilise le hash de composer.lock : si le fichier n’a pas changé depuis le dernier run, le dossier vendor est restauré instantanément depuis le cache. Sur un projet avec une vingtaine de dépendances Composer, on passe de 90 secondes à moins de 10 secondes pour ce step.

Les artefacts permettent de partager des fichiers entre jobs ou de conserver un build pour inspection. Si votre pipeline génère un ZIP du thème prêt à installer (utile pour les clients non techniques), vous pouvez l’uploader comme artefact :

      - name: Package theme as ZIP
        run: zip -r mon-theme-${{ github.sha }}.zip src/ --exclude "*/tests/*"

      - name: Upload artefact
        uses: actions/upload-artifact@v4
        with:
          name: theme-build-${{ github.sha }}
          path: mon-theme-*.zip
          retention-days: 14

Ce ZIP est consultable 14 jours dans l’onglet Actions → Artifacts de GitHub. Pour un client qui veut pouvoir revenir à une version précédente sans toucher à la ligne de commande, c’est un filet de sécurité apprécié.

Intégration avec WP-CLI pour les migrations de base de données

Les déploiements WordPress ne se limitent pas aux fichiers. Quand un plugin ou un thème ajoute une option en base ou crée une table personnalisée, il faut exécuter les migrations au moment du déploiement. WP-CLI est l’outil de référence pour piloter WordPress en ligne de commande, y compris depuis un pipeline CI/CD.

Sur un VPS avec accès SSH, on peut brancher WP-CLI directement dans le workflow :

      - name: Run WP-CLI migrations via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/html
            wp plugin activate mon-plugin --allow-root
            wp eval 'mon_plugin_run_migrations();' --allow-root
            wp cache flush --allow-root

Sur un hébergement mutualisé sans accès SSH direct, une alternative est d’uploader un script PHP temporaire via FTP, de le déclencher par curl, puis de le supprimer immédiatement après exécution. Ce pattern est moins élégant mais fonctionnel pour les contraintes d’hébergement mutualisé.

L’essentiel est que les migrations fassent partie du pipeline — pas une étape manuelle oubliée lors d’une mise en production un vendredi soir.

Sources et références

W
WP Admin Lab

Architecte web full-stack. WordPress, performance, data et sécurité. Notes de terrain, tests reproductibles et retours d'expérience.