UNPKG

@smartimpact-it/json-merge-shopify

Version:
260 lines (209 loc) 8.16 kB
# JSON Merger and formatter for Shopify ## JSON Merger The library handles merging JSON objects and arrays. ```bash npm install --save @smartimpact-it/json-merge-shopify ``` ```javascript import { Merger } from '@smartimpact-it/json-merge-shopify'; const merger = new Merger({ ancestor, ours, theirs, preferred, filename, }); const merged = merger.merge(); ``` ## JSON formatter This formats JSON files to be Shopify compatible. ```javascript import { formatJson } from '@smartimpact-it/json-merge-shopify'; const formatted = formatJson(json); ``` ## Git Branch Merger 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. the `live` 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 the `production` branch - `checkJsonValidity` (default: `true`): whether or not to check the validity of the JSON files using `shopify theme check` ```javascript title="path/to/json-merger.js" 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(); })(); ``` ### Config file 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. ```javascript 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. ```javascript 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, }); ``` ### Github Workflows 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 the `live-mirror` branch ```yaml title=".github/workflows/check-json-changes.yml" 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 sections/**/*.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', }, }); ``` ```yaml title=".github/workflows/merge-json-changes.yml" 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" ``` ### Github Action You can also use the [`siit-dev/merge-json-shopify-branches` pre-built Github Action](https://github.com/siit-dev/merge-json-shopify-branches).