Build files workflow (vite-plugin-shopify + .shopifyignore)

Hey everyone,

I’m using vite-plugin-shopify to generate optimized build files for my theme (JS, CSS, etc.). These build files are intentionally excluded from version control using both .gitignore and .shopifyignore, since I don’t want them tracked or synced globally.

I’m also using Shopify’s GitHub Integration to handle Liquid and JSON synchronization, which works well except for one issue:

The GitHub integration keeps restoring deleted/ignored build files, even though they’re in .shopifyignore and .gitignore.

This creates an annoying conflicts.

I’d love to set up a clean workflow where:

  1. I ignore build files in GitHub and live theme (for cleanliness and repo clarity),
  2. But still manually push the compiled assets via shopify theme push --only <file paths> from a GitHub Action during deploys.
  3. Keep the GitHub integration enabled to sync Liquid and JSON files globally as usual.

But since .shopifyignore is unidirectional, and there’s no equivalent on the Online Store theme, I have no way to stop the GitHub integration from re-adding the build files.

Has anyone figured out a reliable way to combine a Vite build pipeline with the GitHub integration without losing control over these build assets? Would love to hear your approach or any ideas. Thanks!

Hey @devenini :waving_hand: - hopefully I’m understanding correctly, but at the moment out Github integration does only support the “two way” sync between edits made in the Shopify admin and within the Github branch itself (more info here).

It’s not the most ideal, but one workaround you could try would be implementing Vite to build to a separate directory (e.g., dist/assets ) and use GitHub Actions to copy files only during deployment over to the “real” assets folder through that pipeline.

That said, I’m happy to put through a feature request for you for sure to see if we can enable easier version control, since you raise some great points. Let me know if I can set that up and I’d be happy to get that escalated :slight_smile:

@devenini we’ve actually done this sort of thing with Adastra (similar Vite toolset) and Github Actions.

name: Deploy Shopify Themes by Branch

on:
  push:
    branches:
      - production
      - staging
      - uat
      - testing

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Clean Assets
        run: rm -rf assets/theme*

      - name: Setup Node.js 20
        uses: actions/setup-node@v3
        with:
          node-version: 20

      - name: Install Dependencies
        run: npm install --frozen-lockfile

      - name: Build Assets
        run: npm run build

      - uses: EndBug/add-and-commit@v9
        with:
          default_author: 'user_info'
          message: 'Build Assets'

  deploy:
    needs: build
    runs-on: ubuntu-latest
    strategy:
      matrix:
        store: [NA, MX, EU, UK]
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}
          token: ${{ secrets.GITHUB_TOKEN }}
          fetch-depth: 0

      - name: Pull latest changes
        run: |
          git config --global user.name 'github-actions[bot]'
          git config --global user.email 'github-actions[bot]@users.noreply.github.com'
          git pull origin ${{ github.ref_name }}

      - name: Setup Node.js 20
        uses: actions/setup-node@v3
        with:
          node-version: 20

      - name: Install Shopify CLI
        run: npm install -g @shopify/cli@latest

      - name: Deploy to Shopify ${{ matrix.store }} Theme for ${{ github.ref_name }}
        run: |
          set -e

          branch="${{ github.ref_name }}"
          store="${{ matrix.store }}"

          if [[ "$store" == "NA" ]]; then
            store_domain=${{ secrets.SHOPIFY_NA_STORE }}
            if [[ "$branch" == "production" ]]; then theme_id=${{ secrets.SHOPIFY_NA_THEME_PRODUCTION }}
            elif [[ "$branch" == "staging" ]]; then theme_id=${{ secrets.SHOPIFY_NA_THEME_STAGING }}
            elif [[ "$branch" == "uat" ]]; then theme_id=${{ secrets.SHOPIFY_NA_THEME_UAT }}
            elif [[ "$branch" == "testing" ]]; then theme_id=${{ secrets.SHOPIFY_NA_THEME_TESTING }}
            fi
            token=${{ secrets.SHOPIFY_NA_TOKEN }}

          elif [[ "$store" == "MX" ]]; then
            store_domain=${{ secrets.SHOPIFY_MX_STORE }}
            if [[ "$branch" == "production" ]]; then theme_id=${{ secrets.SHOPIFY_MX_THEME_PRODUCTION }}
            elif [[ "$branch" == "staging" ]]; then theme_id=${{ secrets.SHOPIFY_MX_THEME_STAGING }}
            elif [[ "$branch" == "uat" ]]; then theme_id=${{ secrets.SHOPIFY_MX_THEME_UAT }}
            elif [[ "$branch" == "testing" ]]; then theme_id=${{ secrets.SHOPIFY_MX_THEME_TESTING }}
            fi
            token=${{ secrets.SHOPIFY_MX_TOKEN }}

          elif [[ "$store" == "EU" ]]; then
            store_domain=${{ secrets.SHOPIFY_EU_STORE }}
            if [[ "$branch" == "production" ]]; then theme_id=${{ secrets.SHOPIFY_EU_THEME_PRODUCTION }}
            elif [[ "$branch" == "staging" ]]; then theme_id=${{ secrets.SHOPIFY_EU_THEME_STAGING }}
            elif [[ "$branch" == "uat" ]]; then theme_id=${{ secrets.SHOPIFY_EU_THEME_UAT }}
            elif [[ "$branch" == "testing" ]]; then theme_id=${{ secrets.SHOPIFY_EU_THEME_TESTING }}
            fi
            token=${{ secrets.SHOPIFY_EU_TOKEN }}

          elif [[ "$store" == "UK" ]]; then
            store_domain=${{ secrets.SHOPIFY_UK_STORE }}
            if [[ "$branch" == "production" ]]; then theme_id=${{ secrets.SHOPIFY_UK_THEME_PRODUCTION }}
            elif [[ "$branch" == "staging" ]]; then theme_id=${{ secrets.SHOPIFY_UK_THEME_STAGING }}
            elif [[ "$branch" == "uat" ]]; then theme_id=${{ secrets.SHOPIFY_UK_THEME_UAT }}
            elif [[ "$branch" == "testing" ]]; then theme_id=${{ secrets.SHOPIFY_UK_THEME_TESTING }}
            fi
            token=${{ secrets.SHOPIFY_UK_TOKEN }}

          else
            echo "❌ Unknown store: $store"
            exit 1
          fi

          echo "Deploying to $store_domain for $branch (theme $theme_id)..."

          SHOPIFY_CLI_THEME_TOKEN="$token" SHOPIFY_FLAG_STORE="$store_domain" SHOPIFY_FLAG_FORCE=1 shopify theme push --allow-live --theme $theme_id --ignore "templates/*.json" --ignore "config/settings_data.json" --ignore "sections/*.json"

          echo "✅ Preview (if unpublished): https://$store_domain/?preview_theme_id=$theme_id"

      - name: Notify Slack on failure
        if: ${{ failure() }}
        uses: slackapi/slack-github-action@v1.24.0
        with:
          payload: |
            {
              "text": "🔍 *Theme Check Errors/Warnings Found!*",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "🔍 *Theme Check errors/warnings were found in `${{ github.workflow }}`*"
                  }
                },
                {
                  "type": "section",
                  "fields": [
                    {
                      "type": "mrkdwn",
                      "text": "*Repository:*\n${{ github.repository }}"
                    },
                    {
                      "type": "mrkdwn",
                      "text": "*Branch:*\n${{ github.ref_name }}"
                    },
                    {
                      "type": "mrkdwn",
                      "text": "*Commit:*\n${{ github.sha }}"
                    },
                    {
                      "type": "mrkdwn",
                      "text": "*Triggered by:*\n${{ github.actor }}"
                    }
                  ]
                },
                {
                  "type": "actions",
                  "elements": [
                    {
                      "type": "button",
                      "text": {
                        "type": "plain_text",
                        "text": "View Workflow Run"
                      },
                      "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
                    }
                  ]
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
          SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK

@devenini - are you still experiencing this issue after following the advice above?

Hey @Liam-Shopify,

Unfortunately, the advices didn’t quite solve my use case. I think the issue is more about a lack of flexibility in the GitHub integration. It would be great if the .shopifyignore file was also respected by the Online Store. That way, if I copy or send files there, they wouldn’t get re-added to the Git repository.

Hey @devenini, thanks for the extra detail.

You’re right that today the GitHub integration is two‑way and the Online Store doesn’t read .shopifyignore, so if those build artifacts exist in the theme they’ll be synced back to the repo. I’ve happy to go ahead file a feature request with our product team to explore honoring an ignore list from the Online Store side (or making .shopifyignore bidirectional) for sure though.

In the meantime, the cleanest path we’ve seen is building to a separate directory and pushing only the compiled assets during deploy via shopify theme push.

If you can share the exact paths you’d want excluded and a quick summary of your deploy flow, that can definitely help strengthen the feature request on our dev’s side of things. Appreciate you raising this, hope to hear from you soon!