Has someone tips for deploying Sage with Bitbucket pipelines


I am new to both Sage and Bitbucket pipelines, but they seem to be the tool for the job. I have just figured out with Bitbucket pipelines to push to my staging server when I commit to my staging branch. But because the compiled files like CSS are ignored in the default .gitignore I need to figure out a way to build the site before pushing my site.

I could just try to do it myself, but I was hoping that someone here already uses Bitbucket pipelines with Sage and if they could share some pointers.

Deploying Sage 9 with Bitbucket Pipelines

I guess you should run Trellis deploy.yml playbook from pipleines container and use hooks to build stuff. Also, have I look at Build, Release, Run “factor” of 12-factor WordPress app.


@mvasin thanks for the reply, but this sounds like abracadabra to me. I got something working now and all my files are being pushed but I am missing the compiled files like the dist, vender and bower_compontends

This is what my pipeline looks like

and the log look likes this

So I got everything working, but how do I also push the compiled files?


git ftp doesnt push files which are in your .gitignore file. Which dist, vendor and bower_components seem to be (which is good ;)). But there is a way to push them via git ftp anyways, see https://github.com/git-ftp/git-ftp/issues/245

Hope this helps


Here’s my bitbucket-pipelines.yml:

image: kkarczmarczyk/node-yarn

      - step:
            - cd wp-content/themes/sage
            - yarn install
            - yarn run build:production
            - apt-get install lftp
            - lftp -d -u $PREPROD_FTP_USERNAME,$PREPROD_FTP_PWD -e "set ssl:verify-certificate no ; mirror -e -R ./dist/ /wp-content/themes/sage/dist/ ; quit" ftp://$PREPROD_FTP_ADDRESS
  • You might have to do so with composer install for the vendor folder (not needed in my case)
  • Here I’m only pushing dist files because the website is deployed with git (using the plugin Revisr with Bitbuckets webhooks).
  • Note that the FTP connection is not secured
  • I’m using Bitbucket Pipelines environment variables for FTP credentials

If you’re still using git-ftp, the latest version allows to push --auto-init: https://github.com/git-ftp/git-ftp/pull/331. This way you don’t have to init, which push all files every time.


Hey @nico thanks for your reply, but git-ftp is still missing the include all files in a folder feature (https://github.com/git-ftp/git-ftp/issues/329), but maybe lftp has a solution? How would I push all the files of my theme excluding the bower_components, node_modules, npm-debug.log, vendor files and folders.

I am still using Sage 8 because when I tried 9 I spend all day trying to get it to work and after that all my sage 8 projects broke and had to spend another day to get them back.

Hope to hear from you,


Sorry, didn’t receive any notification!

So, you need to push some gitignored files? Looks like git-ftp isn’t meant to do that indeed. I guess you’d have to use one tool to push modified git-aware files (git-ftp), and another to dumbly push dist files (lftp)…

lftp is a simple FTP command, so I guess you can do whatever you need. There’s a --exclude flag (you can call it multiples times). I’m not an expert so you should take a look here: https://www.cyberciti.biz/faq/lftp-command-mirror-x-exclude-files-sub-directory-syntax/

I know what you mean, Sage 9 is a big step, especially the Webpack part. I also spent a lot of time to get it fit in my workflow. That being said, since Sage 8 is generating dist files while watching, my workflow was simply to commit them. Not really following the best practices, but much simpler. This way you could just use git-ftp. If you do that, I recommend editing gulpFile.js and removing all the minifying stuff, like CSSnano:

  • this should be done with PHP (eg. W3 Total Cache) IMO,
  • it’s way faster to compile at each save,
  • and the output files are more readable, so you can easily debug them or stage chunk of them.

Good luck :slight_smile:


Bitbucket Pipelines utilizes docker containers…you should get comfortable with Dockerized versions of Wordpress and transfer the commands into pipelines to setup a flawless continuous integration system for Wordpress…

I’ve got it setup this way and its exactly to 12-factor and WAAAY better than using Trellis (although Trellis is what turned me on to the 12-factor.)

Sorry I cant be of much help currently as I’m tied up with several private projects, but I will circle back with a public version of dockerized Wordpress using pipelines. It is TRULY the way to go. You’re on the right path!!!


@nico has a pretty decent solution, but ftp is not ideal.

Rsync is definitely a better option than git-ftp if you wish to deploy the files straight to another server, it’s more secure than FTP, will overall transfer less etc

Setting up a key pair, and whitelisting the destinations as detailed in this doc is the first step.

You can commit a text file to the repo with your exclude paths in it then tell rsync to reference it when performing the sync using the --exclude-from flag.

In order to get the full advantage of rsync with bitbucket pipelines it’s important to use the --ignore-times flag so that it diffs using the filehash only, see here for more info

Here’s a gist with a sample command

Remember kids, git is version control, not a deployment system, your repo and artefact are often pretty different things :wink:


@bish thanks for the really clear explanation, this really helped and cleared somethings up. I did a test run and everything seems to work fine, but now when I try and do a run on a Sage site Rsync seems to work, but I can’t see my changes on the server.

For example the main-a2c261fb66.css file should be pushed but on my live server it still is main-c5d7ad9ce5.css and in the log down here I can see that it recognised the file and should have send it over, but it didn’t. I’m really new to Rsync and don’t know where to look for errors, could you see something strange?


Trailing slashes make a big difference to rsync, in your case you WANT to have trailing slashes on both directories, as this will transfer the files inside the directories, but ignore the root directory itself. I would be willing to bet if you look inside the “alloy-sage” folder on the server ( I’m assuming you’re using a vagrant box or something as both addresses are local ) you would see another folder named alloy-sage with the transfer results in there.

try running

rsync -azvvP -e "ssh -i $HOME/.ssh/MY-KEY-ssh" --ignore-times --exclude-from excludes.conf /Applications/AMPPS/www/DOMAIN/DOMAIN/wp-content/themes/alloy-sage/ USER@


Amazing! Thanks that was it!