CI/CD for Drupal with GitHub Actions
Lint, test against MySQL, and deploy your Composer-managed Drupal site.
A modern Drupal site is Composer-managed, with code standards checked by PHPCS and tests run against a database. This recipe installs dependencies, lints, runs tests against MySQL, and prepares a config-import deploy.
What the pipeline does
- start a MySQL service container
- install PHP with setup-php
- install deps with composer install
- lint with PHPCS
- run PHPUnit against MySQL
The workflow
The MySQL service container backs the test run via SIMPLETEST_DB. PHPCS uses the Drupal and DrupalPractice standards from coder.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: drupal
ports: ['3306:3306']
options: >-
--health-cmd "mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 5
env:
SIMPLETEST_DB: mysql://root:root@127.0.0.1:3306/drupal
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: pdo_mysql, gd
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/phpcs --standard=Drupal,DrupalPractice web/modules/custom
- run: vendor/bin/phpunit -c web/core web/modules/customCaching and speed
Cache the Composer cache directory keyed on composer.lock so installs are quick. Bootstrapping Drupal for kernel and functional tests is the slow part; cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep the suite fast and auto-retry transient MySQL-container startups.
Deploying
Deploy by syncing code to the host, then running composer install --no-dev, drush updatedb, drush config:import, and drush cache:rebuild. Containerized deploys build a php-fpm image and run the same drush steps as an entrypoint or init job.
Key takeaways
- Test against a MySQL service container via SIMPLETEST_DB.
- Lint custom modules with the Drupal PHPCS standards.
- Deploy with drush updatedb and config:import.