Toby Schrapel WordPress Consultant & Developer

Deploying Sage 9 / Blade Templates to WP Engine using Gitlab CI Pipelines

I was recently working on a project that was hosted on WP Engine. I wanted to use things like Composer or Yarn and after speaking to others they recommended trying out DeployBot as a continuous deployment tool. I found the platform to be quite restrictive and spent a lot of time getting it to work how I’d like.

I had been deploying to staging for months to demo to the client. When I deployed to production the theme I was using did not work. It’s a site powered by Sage 9 that uses Blade as a template engine. These templates are rendered at runtime and cached in the wp-content/uploads directory. WP Engine does not allow the PHP user to write to the system. This makes sense to prevent rogue plugins from having write access but I would expect to have the same configuration between staging and production.

Blade offers a function to compile a template which requires all functions in the templates to be valid or accessible. So any function calls to WordPress would require that WP has been loaded. WP functions will not load unless you have an active database (or at least to my knowledge). I could no longer use DeployBot because they did not support multiple containers.

I switched to Gitlab CI which is very similar to CircleCI or Bitbucket. My Gitlab configuration uses a PHP 7 CLI container that has access to a MySQL service.

I should really create a Docker container that already has all my services preinstalled and also cache Composer / Yarn dependencies to speed up the build but it deploys within a couple of minutes so I am not too bothered about this.

Couple of notes:

  1. Change the cache path to the root of your install ABSPATH . /cache/compiled in app/setup.php
  2. Create a private key that has access to your WPE install and add this as a environment variable in Gitlab CI called PRIVATE_KEY
  3. Create an environment variable in Gitlab for your WPE_INSTALL and THEME_NAME
  4. Create an environment in Gitlab CI called staging and production (case sensitive)
  5. I would suggest adding your WP Engine install as a known host instead of turning off StrictHostKeyChecking

The code is pretty self explanatory but let me know if you have any questions.


if [ "production" != "${CI_ENVIRONMENT_NAME}" ]; then

git config --global "${WPE_INSTALL}@${WPE_INSTALL}.com"
git config --global "${WPE_INSTALL}"
rsync -a --exclude='.git/' --exclude='.gitignore' $(pwd)/ $FOLDER
composer install --no-ansi --no-dev --no-interaction --optimize-autoloader --no-progress
cd ./wp-content/themes/${THEME_NAME}
yarn run build:production
cd ../../../
wp --allow-root core config --dbname=wordpress --dbuser=root --dbpass=wordpress --dbhost=mysql
wp --allow-root core install --url=${WPE_INSTALL}.dev --title=${WPE_INSTALL} --admin_user=wordpress --admin_email=${WPE_INSTALL}@${WPE_INSTALL}.com --skip-email
wp --allow-root theme activate ${THEME_NAME}/resources
wp --allow-root blade compile
rm -rf ./wp-content/themes/${THEME_NAME}/.gitignore
rm -rf .gitignore
mv .gitignoredeploy .gitignore
git add .
git commit -m "Deployment Commit"
git push origin master


image: php:7.0.18-cli

  - mysql:latest

  MYSQL_DATABASE: wordpress

  # Updates
  - curl -sL | bash
  - apt-get update
  - apt-get -y install libpcre3-dev zlib1g-dev libbz2-dev libpng12-dev libjpeg-dev nodejs git zip unzip curl rsync mysql-client
  - docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr
  - docker-php-ext-install zip bz2 gd mysqli pdo pdo_mysql

  # Composer
  - php -r "copy('', 'composer-setup.php');"
  - php -r "copy('', 'composer-setup.sig');"
  - php -r "if (hash_file('SHA384', 'composer-setup.php') === trim(file_get_contents('composer-setup.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
  - php composer-setup.php --install-dir=/usr/local/bin --filename=composer
  - php -r "unlink('composer-setup.php');"
  - php -r "unlink('composer-setup.sig');"

  # Install Node / Yarn
  - npm -g install yarn

  # WP CLI
  - curl -O
  - chmod +x wp-cli.phar
  - mv wp-cli.phar /usr/local/bin/wp
  - php -d memory_limit=512M /usr/local/bin/wp --allow-root package install

  # SSH
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - ssh-add <(echo "$SSH_PRIVATE_KEY")
  - mkdir -p ~/.ssh
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

    - develop
    name: staging
    url: http://$
  script: ./bin/deploy

    - master
    name: production
    url: http://$
  script: ./bin/deploy


# Ignore everything in the root except the "wp-content" & "vendor" directory.

# Ignore specific files for deployment

# Plugins

# Uploads

# Themes

# Mac-specific

# Dev files

# known large file types

About the author

Toby Schrapel

Toby is a WordPress engineer & consultant, freelance full-stack developer, open source contributor and digital nomad that is currently living in Playa del Carmen, Mexico. Follow me on Twitter @tobyschrapel.


  • Bit new to all this (and Gitlab CI), but where am I supposed to run the BASH script for this? I’m assuming I upload the site to the Gitlab repo. The YAML and .gitignore I’m assuming are for the Gitlab repo as well correct (YAML being the .gitlab-ci.yml)?


    • I put it in a file called “deploy” in the “bin” folder of my repository. Where you put it is up to you as long as the .gitlab-ci.yml file references the path correctly. E.g. I use “script: ./bin/deploy” in my GitLab file.

  • Hi Toby,

    This is a brilliant plan, thanks so much for your post! I’m getting a bit stuck on the SSH config, however.

    I generated a keypair locally (with no passphrase) and saved the private key as a CI variable. The docker image, however, really wants a passphrase—did I miss something in your instructions?


    “`$ ssh-add <(echo "$SSH_PRIVATE_KEY")
    Enter passphrase for /dev/fd/63: ERROR: Job failed: exit code 1“`

    • It appears a line in the config was badly formatted by WordPress. Can you try using this line instead - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'. I have updated the post too.

Toby Schrapel WordPress Consultant & Developer

If you would like to get in touch fill out the form below or send me a Tweet.