Automating Shopify Deployments with GitLab CI/CD (2024)

Automating Shopify Deployments with GitLab CI/CD (1)

by Matt Cotton

8 min read

Introduction

Shopify development projects often involve multiple team members working on different features simultaneously. Efficient collaboration and continuous integration are crucial for delivering high-quality Shopify stores. To streamline this process, we've developed an automated deployment process that integrates Shopify themes with a GitLab repo by utilising the GitLab CI/CD.

This is done by defining pipelines in the .gitlab-ci.yml file that executes a shell script which determines how to deploy the branch to a Shopify theme. This could be anything from a feature branch to a production deployment. In this blog post, we'll delve into how this automation works and how you can implement this on your or your clients Shopify stores.

All files referenced below can be found in this gist.

GitLab CI Script

For Shopify projects, the GitLab CI/CD file manages the deployment workflow for various branches, including feature branches, staging, UAT (User Acceptance Testing), and the main/production branch. Let's break down the key stages of the script:

1. Review Stage

review: stage: review script: - echo "Contents of root directory before actions:" - ls -la - echo "Contents of shopify-deployment before actions:" - ls -la shopify-deployment || true - shopify version - mkdir -p ./shopify-deployment - chmod +x ./shopify-deployment-script.sh; ./shopify-deployment-script.sh - echo "Contents of shopify-deployment after actions:" - cat ./shopify-deployment/deployment-data - DYNAMIC_ENVIRONMENT_URL=$(grep -o '"preview_url":"[^}]*' ./shopify-deployment/deployment-data | grep -Eo '(http|https)://[^"]+') - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env artifacts: reports: dotenv: deploy.env environment: name: review/$CI_COMMIT_REF_NAME url: $DYNAMIC_ENVIRONMENT_URL on_stop: stop_review cache: <<: *global_cache only: - branches except: - staging - uat - main

The Review stage deploys feature branches to a Shopify development theme. It uses the shopify-deployment-script.sh to deploy updates to a Shopify development theme if this branch hasn’t been deployed before, or updates an existing Shopify development theme if it has. This shell script is explained in detail in the Shopify Deployment Script section below.

The Shopify CLI is used to enable this automated deployment. This means that you will need to have the Shopify CLI installed on your GitLab Runner. It may be possible to install this directly but we are using a Docker container that has the Shopify CLI and all required packages pre-installed. This image is then saved to a GitLab Container Registry. The Dockerfile used to generate this image is available in this gist.

After the deployment occurs in the shopify-deployment-script.sh file the review stage then saves the Shopify development theme URL in GitLab as the App URL. It does this by setting the DYNAMIC_ENVIRONMENT_URL to the preview_url returned by the Shopify CLI. A grep command is used to extract this preview_url from the JSON data in the deployment-data file. Finally, this DYNAMIC_ENVIRONMENT_URL variable is written to the deploy.env file.

Automating Shopify Deployments with GitLab CI/CD (2)

All of this enables the deployed development theme to be opened directly within a GitLab merge request by clicking the ‘View app” button. Bear in mind that Shopify automatically removes development themes that have been inactive for seven days. Therefore if your review process takes longer than this you will need to rerun the pipeline after seven days to deploy this feature branch to a new Shopify development theme.

2. Staging and UAT Stages

staging: stage: staging script: - echo "Contents of root directory before actions:" - ls -la - echo "Contents of shopify-deployment before actions:" - ls -la shopify-deployment || true - shopify version - mkdir -p ./shopify-deployment - echo "Deploying updates to Shopify Staging theme:" - shopify theme push --theme $STAGING_THEME_ID --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-data - echo "Contents of shopify-deployment after actions:" - cat ./shopify-deployment/deployment-data - DYNAMIC_ENVIRONMENT_URL=$(grep -o '"preview_url":"[^}]*' ./shopify-deployment/deployment-data | grep -Eo '(http|https)://[^"]+') - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env artifacts: reports: dotenv: deploy.env environment: name: review/$CI_COMMIT_REF_NAME url: $DYNAMIC_ENVIRONMENT_URL cache: <<: *global_cache only: - staging
uat: stage: uat script: - echo "Contents of root directory before actions:" - ls -la - echo "Contents of shopify-deployment before actions:" - ls -la shopify-deployment || true - shopify version - mkdir -p ./shopify-deployment - echo "Deploying updates to Shopify UAT theme:" - shopify theme push --theme $UAT_THEME_ID --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-data - echo "Contents of shopify-deployment after actions:" - cat ./shopify-deployment/deployment-data - DYNAMIC_ENVIRONMENT_URL=$(grep -o '"preview_url":"[^}]*' ./shopify-deployment/deployment-data | grep -Eo '(http|https)://[^"]+') - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env artifacts: reports: dotenv: deploy.env environment: name: review/$CI_COMMIT_REF_NAME url: $DYNAMIC_ENVIRONMENT_URL cache: <<: *global_cache only: - uat

Similar to the Review stage, these stages deploy updates to Shopify staging and UAT themes, respectively. As with the Review stage it does this by using the Shopify CLI. Unlike the Review stage, this doesn’t require using the shopify-deployment-script.sh script though as the staging and UAT Shopify theme are created as permanent themes in the Shopify theme library. This has been implemented this way so that the Staging and UAT themes will not be automatically removed by Shopify after seven days.

The Staging and UAT themes need to be created in Shopify by duplicating the main theme and renaming it. Thereby adding these duplicate themes to the theme library. Then the theme IDs for both of these themes need to be added to the GitLab repo under Settings → CI/CD → Variables. In the example .gitlab-ci.yml file these variables are STAGING_THEME_ID and UAT_THEME_ID. These steps only have to be completed once when first adding this functionality to the project.

3. Generate Version Stage

generate_version: stage: prep_deploy image: alpine:latest rules: - if: $CI_COMMIT_TAG when: never - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH script: - echo "RELEASE_TAG = $(date '+%Y%m%d.%H%M')" >> variables.env artifacts: reports: dotenv: variables.env expire_in: 1 week

This stage is the first stage in a production deployment. It generates a version tag for deployments of the default branch (e.g. main) if a commit has not already been tagged. This allows for improved version tracking for the live theme.

4. Deploy Stage

deploy: stage: deploy script: - echo "Contents of root directory before actions:" - ls -la - echo "Contents of shopify-deployment before actions:" - ls -la shopify-deployment || true - shopify version - mkdir -p ./shopify-deployment - shopify theme push --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --live --allow-live --json > ./shopify-deployment/deployment-data - echo "Contents of shopify-deployment after actions:" - cat ./shopify-deployment/deployment-data - ID=$(grep -o '"id":[^"]*' ./shopify-deployment/deployment-data | grep -o '[^:]*$' | grep -o '^[^,]*') - PREVIEW_URL=$(grep -o '"preview_url":"[^}]*' ./shopify-deployment/deployment-data | grep -Eo '(http|https)://[^"]+') - DYNAMIC_ENVIRONMENT_URL=${PREVIEW_URL}?preview_theme_id=${ID} - echo "DYNAMIC_ENVIRONMENT_URL=$DYNAMIC_ENVIRONMENT_URL" >> deploy.env artifacts: reports: dotenv: deploy.env environment: name: live url: $DYNAMIC_ENVIRONMENT_URL cache: <<: *global_cache only: - main

The Deploy stage is the second stage in production deployment and handles the actual deployment of the live theme to Shopify. As with the Review, Staging and UAT stages, it pushes updates to the theme using the Shopify CLI.

It is very important to note that any changes made on the live store through the Shopify theme editor or code editor that are not contained in the code base may be overwritten by this deployment stage. It is recommended to always manually run the shopify theme pull command to pull and commit the latest changes from the live store before merging and pushing your changes to the default (e.g. main) branch.

5. Release Stage

release: stage: finalise_deploy image: registry.gitlab.com/gitlab-org/release-cli:latest rules: - if: $CI_COMMIT_TAG when: never - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH script: - echo "Running release $RELEASE_TAG..." release: name: 'Release $RELEASE_TAG' tag_name: '$RELEASE_TAG' description: '$RELEASE_TAG' ref: '$CI_COMMIT_SHA' artifacts: expire_in: 1 week

This stage is the third stage in production deployment and is triggered when a new tag is created. It runs the release CLI to finalise the deployment and create a release tag.

6. Stop Review Stage

stop_review: stage: cleanup script: - ./teardown-environment - dep ci:destroy cd --revision=$CI_COMMIT_SHA when: manual environment: name: review/$CI_COMMIT_REF_NAME action: stop only: - branches except: - main - uat - staging

This manual stage is used to tear down Review environments for feature branches.

Shopify Deployment Script

# IMPORTANT: Deployment results files (e.g. deployment-data) cannot use the file type '.json' as Shopify will interpret these as being theme files and the theme deployment will fail# When the deployment-data file already exisits (loaded from the cache) then try to redeploy to this themeif [ -f ./shopify-deployment/deployment-data ]then # Get the theme id from the deployment-data json file ID="$(grep -o '"id":[^"]*' ./shopify-deployment/deployment-data | grep -o '[^:]*$' | grep -o '^[^,]*')" echo "Deploying updates to Shopify development theme with id: $ID" echo "shopify theme push --theme $ID --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN > ./shopify-deployment/result" shopify theme push --theme $ID --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN > ./shopify-deployment/result # If the redeployment output includes the word 'Error' then deploy a development new theme ERROR="$(grep -w "Error" ./shopify-deployment/result)" if [ ! -z "$ERROR" ] then echo "WARNING: There was an error with the deployemnt. This is probably due to this Shopify development theme being inactive for more than 7 days. The theme will now be redeployed. This will result in the Shopify development theme having a new id and url." echo "shopify theme push --development --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-data" shopify theme push --development --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-data fi rm -f ./shopify-deployment/result# When the deployment-data file doesn't exisit deploy a new development themeelse echo "Deploying a new Shopify development theme:" echo "shopify theme push --development --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-data" shopify theme push --development --store $SHOPIFY_FLAG_STORE --password $SHOPIFY_CLI_THEME_TOKEN --json > ./shopify-deployment/deployment-datafi

The Shopify deployment shell script (shopify-deployment-script.sh) complements the .gitlab-ci.yml file by handling the deployment specifics for feature branches. This script is used by the Review stage and is required as there is more complex logic required for a feature branch deployment than a staging, UAT or live deployment. This more complex logic is slightly easier to write and understand in a shell file than if written directly in the .gitlab-ci.yml file. Here's a summary of the functionality of this shell script:

  • If the deployment-data file exists, it attempts to redeploy to the existing Shopify development theme using the stored theme ID.

  • If the redeployment fails (e.g. due to the theme having been inactive for over 7 days) or if the deployment-data file doesn’t exist, it deploys a new development theme and updates the deployment-data file with the theme ID.

As the Shopify CLI returns fairly verbose command line messages, checking if a deployment has failed has been implemented in a fairly unusual way. The deployment response is redirected to a result file. A grep command is then used to determine if the result file contains the word "Error". If it does then the script triggers the development of a new theme. This will result in the Shopify development theme having a new theme ID and URL. As mentioned in 1. Review Stage this new URL will be set as the DYNAMIC_ENVIRONMENT_URL. This means that the ‘View app’ link in the MR is automatically updated to this new development theme URL.

Something you may have noticed when looking at this shell script and the .gitlab-ci.yml file is that the JSON output of the shopify theme push commands is not redirected into a file with a file extension of .json. This is because the Shopify CLI will interpret these as theme files and attempt to deploy these files. As they will contain data that doesn't match the expected format of any Shopify .json file the theme deployment will fail. To get around this issue these files have not been given any file extension.

Setup of GitLab CI/CD Variables

For the shopify-deployment-script.sh and .gitlab-ci.yml functionality to work the following variables need to be added to the GitLab repo under Settings → CI/CD → Variables.

Automating Shopify Deployments with GitLab CI/CD (3)

Shopify Store Name

The store name variable is required to tell the Shopify CLI instance that is running in your GitLab Runner which Shopify store it is communicating with. This variable can have any key, but for the example files in this gist use SHOPIFY_FLAG_STORE.

Theme Access Password

The theme Access password is needed to authorise the Shopify CLI instance that is running on your GitLab Runner to communicate with your store. This is created by:

  • Adding the Theme Access app to the Shopify store.

  • Create a password in the Theme Access app.

  • Adding this theme access password as a GitLab variable. In our example files we have defined the key for this variable as SHOPIFY_CLI_THEME_TOKEN.

For security, I recommend masking this variable so that it is not displayed in your pipeline job logs.

Staging and UAT Theme IDs

If your development process requires you to have a Staging and/or UAT store then these themes can be created and deployed by following the steps below.

  • Go to the admin for your Shopify store. This is at the URL for your Shopify store with /admin added at the end.

  • Within the 'Online Store' section, on the live theme click on the ellipses (3 dots) then click 'Duplicate'.

  • Once this theme has been duplicated click on the ellipses again and rename the theme to either Staging or UAT.

  • Get the theme IDs for these new themes. This can be done either:

    • Via the Shopify CLI with the command shopify theme list

    • Or by clicking 'Customize' and copying the ID from the URL (It should be a 12-digit number).

  • In GitLab add a variable with the value set as the theme ID.

  • In the example files the staging theme ID has the key STAGING_THEME_ID and the UAT theme ID has the key UAT_THEME_ID

  • Repeat steps 1-3 if a Staging and UAT theme are required.
    Summary

Summary

Has this post struck a chord with you? Have you been struggling with manual Shopify theme deployments? We can help! Contact us for a free consultation to discuss how to automate your workflows and streamline your development processes.

Automating Shopify Deployments with GitLab CI/CD (4)

Written by Matt Cotton

Senior Frontend Software Engineer

Matt joined our Development team from a Sheffield-based software house in 2021, bringing his passion for UX and building intuitive user interfaces to the role, as well as his experience creating React apps.

Matt formerly served as our CSR Officer to great effect, taking charge of our strategy to give back to the environment and local communities and leading our push for B Corp status.

Related Blog Posts

  • 07/02/2023 How we used CI/CD to Transform our Development Process by John Noel Technical Team Lead
  • 14/04/2021 Debunking the Web Development ‘5 Minute Fix’ Myth by Andy Carter Technical Team Lead
  • 15/11/2021 The Key To Writing Effective Developer Tasks by Andy Carter Technical Team Lead
Automating Shopify Deployments with GitLab CI/CD (2024)

References

Top Articles
Latest Posts
Article information

Author: Roderick King

Last Updated:

Views: 5847

Rating: 4 / 5 (71 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Roderick King

Birthday: 1997-10-09

Address: 3782 Madge Knoll, East Dudley, MA 63913

Phone: +2521695290067

Job: Customer Sales Coordinator

Hobby: Gunsmithing, Embroidery, Parkour, Kitesurfing, Rock climbing, Sand art, Beekeeping

Introduction: My name is Roderick King, I am a cute, splendid, excited, perfect, gentle, funny, vivacious person who loves writing and wants to share my knowledge and understanding with you.