How to deploy Shopify themes automatically

If you’re a startup or a small company selling products online there’s a good chance you’re using Shopify. Most of the time you’ll buy a third party theme and customize it to your needs. But how do you deploy these changes without breaking things in production? This tutorial walks you through creating a CI/CD pipeline with separate development, staging and production environments.

Knowledge required: Liquid (basics) / What CI,CD pipelines are / some experience with GitLab

You’ll end up with this nice workflow:

  1. Develop locally on a feature branch and once you save files -> your development environment gets updated instantly, you see changes immediately without a pipeline.

Now lets’ get to it. This will take you about 20–30 minutes and I promise it’s well worth your time. As with anything tutorial-related I write, please reach out to me immediately if you have issues or the steps outlined stop working altogether. Tutorials on the internet should just work.

1. Creating multiple theme versions

The first step is to create multiple versions of the same theme. One for active development where you can try and break things, one as a staging environment so you can beta-test your changes, and the last one as a production-ready environment (your actual live store).

To show you real examples I’ve created a new Shopify store in trial mode. If you already have a live theme, duplicate it two times so you have 3 versions in total and then rename them to something meaningful. This should end up looking like this:

As you can see, my live theme is called “Debut Production”, my staging theme “Debut Staging” and the dev theme “Debut Development”.

2. Set up a GitLab Repository

The next step is to set up a git repository so you can track your changes. If you didn’t know it already, your Shopify theme is basically just a file and folder structure you can download. Even all your settings (site layout, translations, etc.) are just files! This is awesome for us because we can utilize the full power of Git.

The reason I recommend GitLab and not GitHub is “GitLab CI” — GitLab’s integrated CI tool with more than enough free quota which isn’t offered by GitHub. We will use this to update our theme whenever we push to our master branch.

For now, just head over to gitlab.com and create a new repo which we’ll need in a bit.

3. Set up ThemeKit CLI

I’m assuming you’re coding on MacOS, to install ThemeKit run the following commands:

brew tap shopify/shopify
brew install themekit

For detailed instructions and installation guides on other operating systems visit: https://shopify.github.io/themekit/

Next, we need to get an API key from Shopify so we can actually use ThemeKit on our local machine. In your Shopify Dashboard go to Apps, scroll down to “manage private apps” and then click “Create new private app”.

Name it whatever you like, the only important thing is to set the correct permissions: “Products — Read access”, and “Themes — Read, Write access”. This should look like this:

Note: This private Shopify app has already been deleted and was used as a showcase, the API keys seen in this video are not available anymore so abusing them is pointless.

Take note of your password, you’ll need it later.

3. Download theme to local machine

To make changes offline, we need to download the theme to our machine. To do that create a new folder first, run git init and add your remote git repo.

Now it’s getting a little more complicated. We need to use the ThemeKit CLI to download the live theme version of our store. While a little more complicating, it’s actually still quite straightforward:

theme get -p=[your-password] -s=[you-store.myshopify.com] -t=live

Substitute the brackets with your actual password and store name (we’ll use environment variables in a moment)

After our theme has been downloaded successfully, you will notice that a config.yml file has been created. Right now it contains our actual shopify API password so we have to change that in the next step to keep our environment secure.

4. Setting up environment variables

Because we do not want to store the Shopify password in our git repo we need to set up environment variables.

We need to do this for:

  1. Our local machine

Local Machine

First, we’ll do it for our local machine. Depending on your OS you need to create a “variables” file at a different location.

The ThemeKit documentation (https://shopify.github.io/themekit/configuration/) tells you exactly where you have to create it.

As I’m a Mac user, I’ll need to create a variables file at /Library/Application Support/Shopify/Themekit/variables (without a file extension) and add the following content:

You can already fill out your API password (the password you noted down earlier) but what about the theme IDs? We need to use the ThemeKit CLI for that again to retrieve all the available themes of our store:

theme get --list -p=[your-api-password] -s=[your-store.myshopify.com]

This should display all your theme IDs. As you can see, these are the ones we duplicated in the first step.

Now just copy these numbers to your variables file (without the brackets) and save it. Leave your terminal open for now as we need the theme IDs again for our GitLab repo.

GitLab repo

When we push new code changes we want GitLab to automatically run the ThemeKit command to deploy the changes to the correct environment. For that, we need some environment variables first.

Here’s how you add the environment variables to your GitLab repo:

Note that I turned the “protected” feature off. When it’s turned on, these variables will not show in the CI logs, which adds an extra layer of security. If you want to turn them on, you need to make sure that your master branch and the tag v* wildcard is protected as well.

5. Auto Deployments with GitLab CI

Now comes the best part. Imagine you develop on your local machine and once you’re happy with your changes you want to test them and then update the live theme. A really bad thing would be to only have one single theme (your live theme) and do all the changes while your customers can still shop online. That would make for a very bad user experience. Instead, we want to be able to break things in our development theme, completely isolated from what customers see and once everything works as defined, we update our live theme without any service disruption. To make that happen we’re going to create a CI pipeline.

We will set it up like this:

  • Pushes to master will update the staging theme

Creating .gitlab-ci.yml

Go to your local theme folder and create a file called .gitlab-ci.yml at project root. Add the following content:

This is the configuration for our CI pipeline. It has two stages: “staging” and “production”. Both stages install the ThemeKit CLI first and then deploy the whole theme to the corresponding environment.

Note: We have to use Python2 because ThemeKit doesn’t seem to support Python3 at the moment, but it literally makes no difference because this is just the Docker image used behind the scenes to run our script.

Updating config.yml

ThemeKit uses a config file so you can run commands in different environments. Just create a file at project root called “config.yml”. Make sure to change your store URL but leave the password and theme id as is (these will be populated by our variables file we created in step 4.)

Once you created these two files, your project structure should look like this:

6. Development flow

Now once you run the following code on your master branch:

git commit -am "commit message"
git push

Your theme will get automatically deployed to your staging environment:

Isn’t that incredibly useful?

And once you create a new tag and push it, your live theme will be updated:

git tag -a "v1.0.0" -m "first  prod version of our customized theme"
git push --tags

And if you want to develop locally you can just run:

theme watch -e=development

Which will update your development theme instantly without the use of a pipeline. On the one hand, we want to develop fast, but once we’re happy with our results it doesn’t matter if deployment to production takes 5 seconds or 2 minutes.

Now how could a nice development flow look like?

  1. Develop locally on a feature branch and once you save files -> your development theme gets updated instantly and you see changes immediately without a pipeline.

This video exactly depicts this workflow:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store