Since the integration of pipeline building tools into major git repository hosting services (GitHub Actions for GitHub, GitLab CI/CD for GitLab), there is no longer any excuse to continue manual deployment via FTP.
Personally more invested in the GitHub ecosystem than that of GitLab, I use GitHub Actions for the majority of my deployments with a pipeline that I have refined over the years.
This is the one I use for deploying my Drupal projects.
Checking out the code
name: Build and deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Here we create a pipeline called Build and deploy that runs on the latest version of Ubuntu. It is triggered as soon as code is pushed to the repository (here on all branches, but it is possible to scope this pipeline to the main branch only for example).
We then add a first step that retrieves the code via the actions/checkout
action.
Install PHP dependencies via Composer
- name: Validate composer.json
run: composer validate --no-check-all
- name: Install composer dependencies
run: composer install --prefer-dist --no-progress
We then add 2 steps:
- Validate composer.json: we validate that the composer.json file is compliant, a practice recommended by Composer
- Install composer dependencies: we install the project dependencies in the pipeline
Building the front-end assets
- name: Install NPM dependencies
run: npm ci
- name: Build assets
run: npm run build
- Install NPM dependencies: here we use the command
npm ci
(for Clean Install) instead ofnpm install
, which is convenient for ensuring that the dependencies installed are with a fixed version specified in thepackage-lock.json
file - Build assets : on lance ensuite la commande de build pour compiler les assets du front-end
Deploy files to a server via SSH
- name: Install SSH Key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
name: id_rsa
known_hosts: unnecessary
if_key_exists: fail
- name: Deploy to server
run: rsync -avzq --no-perms --no-owner --no-group --chown=www-data:www-data -e "ssh -o StrictHostKeyChecking=no" --exclude-from="${GITHUB_WORKSPACE}/rsync-exclude.txt" $GITHUB_WORKSPACE/ ${{ secrets.SSH_HOST }}:/var/www/html/
Several things are happening here:
- Install SSH Key: we install an SSH key to access the remote server. Here I use a secret called
SSH_PRIVATE_KEY
defined in the repository to be deployed on the GitHub side. Note that for these 2 steps, I disabled the host verification withStrictHostKeyChecking=no
to facilitate the configuration of the pipeline and the remote server. - Deploy to server: this is where everything happens. Once the project is compiled, I deploy it via rsync using the permissions defined on the server. The server connection address and the SSH user are defined in a single secret
SSH_HOST
of the form user@myserver.com. The path/var/www/html
is hard-coded here but can also be saved in a variable.
To avoid deploying files that have no place on the server, I use theexclude-from
argument which allows me to read from anrsync-exclude.txt
file a list of files/folders to exclude. At a minimum, this contains the.git
,.github
andnode_modules
folders.
Rebuild Drupal Cache
So far, the deployment steps are standard and can be used on most PHP projects as is.
Due to the way Drupal and its cache system work, it is often necessary to rebuild it so that it takes into account the latest file modifications, particularly when changing twig or PHP files.
So I add the next step to run the drush cr
command to rebuild the Drupal cache directly on the server.
Since we have already configured the SSH key in the pipeline, we just have to run the command directly on the remote server.
- name: Rebuild drush cache
run: ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_HOST }} "cd /var/www/html && vendor/bin/drush cr"
Complete pipeline
name: Build and deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Validate composer.json
run: composer validate --no-check-all
- name: Install composer dependencies
run: composer install --prefer-dist --no-progress
- name: Install NPM dependencies
run: npm ci
- name: Build assets
run: npm run build
- name: Install SSH Key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
name: id_rsa
known_hosts: unnecessary
if_key_exists: fail
- name: Deploy to server
run: rsync -avzq --no-perms --no-owner --no-group --chown=www-data:www-data -e "ssh -o StrictHostKeyChecking=no" --exclude-from="${GITHUB_WORKSPACE}/rsync-exclude.txt" $GITHUB_WORKSPACE/ {{ secrets.SSH_HOST }}:/var/www/html/
- name: Rebuild drush cache
run: ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_HOST }} "cd /var/www/html && vendor/bin/drush cr"
Bonus: Automatically warm up Drupal cache on deployments
If you want to automatically warm up the Drupal cache during deployments to ensure the fastest possible page load speed for all your visitors, I have written a specific article detailing the procedure to set up using the Warmer module.
No more excuses for manual deployments!