The library handles merging JSON objects and arrays.
npm install --save @smartimpact-it/json-merge-shopify
import { Merger } from '@smartimpact-it/json-merge-shopify';
const merger = new Merger({
ancestor,
ours,
theirs,
preferred,
filename,
});
const merged = merger.merge();
This formats JSON files to be Shopify compatible.
import { formatJson } from '@smartimpact-it/json-merge-shopify';
const formatted = formatJson(json);
This GitMerger
functionality is intended to workaround Shopify's limitations for the Git integration.
To use it, you will need 2 or 3 branches:
-
main
branch: this is the branch that you will be merging into -
live-mirror
branch: this is the branch that you will be merging from; this branch needs to be connected to Shopify (i.e. thelive
branch). We never write to this branch, we only read from it. Only Shopify should be writing to this branch. -
production
branch (optional): this is the branch that you be deploying from. It will not be connected directly to Shopify's git integration, but with a Github Action you can deploy this branch to Shopify.
To use it, import the GitMerger
class. It has the following options:
-
gitRoot
: the root of the git repository -
createCommit
: whether or not to create a commit with the changes -
mainBranch
: the name of the main branch (default:main
) -
liveMirrorBranch
: the name of the live mirror branch (default:live-mirror
) -
productionBranch
: the name of the production branch (default:production
) -
commitMessage
: the commit message to use (default:[AUTOMATED] Update JSON files from ``#liveMirror#`` branch: #files#
) -
preferred
: the preferred strategy for the merger (default:theirs
) -
jsonPaths
: the paths to the JSON files to merge (default:['templates/**/*.json', 'locales/*.json', 'config/*.json']
) -
exitIfNoExistingDeployment
(default:true
): whether or not to exit if there is no commit on theproduction
branch -
checkJsonValidity
(default:true
): whether or not to check the validity of the JSON files usingshopify theme check
const { GitMerger } = require('@smartimpact-it/json-merge-shopify');
const path = require('path');
const gitRoot = path.resolve(__dirname, '../../../'); // The root of the git repository
(async () => {
const createCommit =
process.argv.includes('--commit') || process.env.COMMIT_CHANGES == 'true';
// Initialize the merger
const merger = new GitMerger({
gitRoot,
createCommit,
});
// Run the merge
await merger.run();
})();
You can also use a config file to specify the options. The config file can be a JSON file (shopify-git-merger.config.json
) or a JS file (shopify-git-merger.config.js
) that exports an object with the options.
Then pass the path to the config file to the GitMerger
constructor.
import { GitMerger } from '@smartimpact-it/json-merge-shopify';
const gitRoot = path.resolve(__dirname, '../../../'); // The root of the git repository
const merger = new GitMerger('shopify-git-merger.config.json', {
gitRoot,
});
Or you can pass null
as the first argument and the GitMerger
will look for the config file in the root of the git repository.
import { GitMerger } from '@smartimpact-it/json-merge-shopify';
const gitRoot = path.resolve(__dirname, '../../../'); // The root of the git repository
const merger = new GitMerger(null, {
gitRoot,
});
You will need 2 workflows:
- on the
live-mirror
branch - to check if JSON files have been modified by Shopify and then trigger the second workflow - on the
main
branch - to merge the JSON changes from thelive-mirror
branch
name: Check modified JSON files
concurrency:
group: live-mirror
cancel-in-progress: false
on:
push:
branches:
- live-mirror
workflow_dispatch:
env:
NODE_VERSION: 18
NPM_VERSION: 9
jobs:
check-json:
name: Check if JSON files have been modified
runs-on: ubuntu-latest
if: contains(toJSON(github.event.head_commit.message), 'Update from Shopify')
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2 # Needed to get the previous commits
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v35.9.2
with:
files: |
templates/**/*.json
locales/**/*.json
config/*.json
- name: Trigger merge if necessary
if: steps.changed-files.outputs.any_changed == 'true'
uses: actions/github-script@v6
with:
script: |
# Check if there is any production deployment
# Remove this if you don't want to check for a production deployment
const lastRun = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'production.yml',
branch: 'production',
status: 'success',
per_page: 1,
});
if (lastRun.data.total_count === 0) {
console.log('No successful production runs found');
return;
}
# Trigger the merge workflow
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'merge-live-mirror-json.yml',
ref: 'main',
inputs: {
merge: 'true',
},
});
name: Merge JSON files
concurrency:
group: main
cancel-in-progress: true
on:
workflow_dispatch:
env:
NODE_VERSION: 18
NPM_VERSION: 9
COMMIT_CHANGES: true
jobs:
merge-json:
name: Merge JSON files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/setup-node@v3
with:
node-version: 18
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3
bundler: 'latest'
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Load NPM packages from cache
id: npm-cache
uses: actions/cache@v3
with:
path: |
${{ steps.npm-cache-dir.outputs.dir }}
**/node_modules
key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ env.NODE_VERSION }}-
${{ runner.os }}-node-
- name: Upgrade NPM to the correct version
shell: bash
env:
NPM_VERSION: ${{ env.NPM_VERSION }}
run: npm i -g npm@$NPM_VERSION
- name: Install Shopify CLI
run: npm install -g @shopify/cli @shopify/theme
- name: Install node modules
if: steps.npm-cache.outputs.cache-hit != 'true'
run: npm install
- name: Run the merge process
uses: mathiasvr/command-output@v2.0.0
id: merge-json
env:
COMMIT_CHANGES: ${{ env.COMMIT_CHANGES }}
with:
run: |
git config user.name github-actions
git config user.email github-actions@github.com
git status
node path/to/json-merger.js --commit
git status
- name: Push the changes, if there are any
if: success()
run: |
git status | grep 'Your branch is ahead' && git push && echo 'Pushed changes' || echo "No changes to push"
You can also use the siit-dev/merge-json-shopify-branches
pre-built Github Action.