name: Deploy Shopify theme on: push: branches: [staging, main] permissions: contents: read concurrency: group: shopify-theme-${{ github.ref_name == 'main' && 'production' || 'staging' }} cancel-in-progress: false jobs: deploy: runs-on: ubuntu-latest environment: ${{ github.ref_name == 'main' && 'production' || 'staging' }} defaults: run: shell: bash steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: actions/setup-node@v7 with: node-version: 24 - name: Install Shopify CLI run: npm install -g @shopify/cli@4.8.3 - name: Check theme run: shopify theme check --fail-level error - name: Deploy staging if: github.ref == 'refs/heads/staging' env: SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_STORE }} SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} STAGING_THEME_ID: ${{ vars.SHOPIFY_THEME_ID }} run: | set -euo pipefail : "${SHOPIFY_FLAG_STORE:?Missing store}" : "${SHOPIFY_CLI_THEME_TOKEN:?Missing Theme Access password}" : "${STAGING_THEME_ID:?Missing staging theme ID}" if [[ ! "$STAGING_THEME_ID" =~ ^[0-9]+$ ]]; then echo "Staging theme ID must be numeric." >&2 exit 1 fi shopify theme push --theme "$STAGING_THEME_ID" --json - name: Deploy production if: github.ref == 'refs/heads/main' env: SHOPIFY_FLAG_STORE: ${{ vars.SHOPIFY_STORE }} SHOPIFY_CLI_THEME_TOKEN: ${{ secrets.SHOPIFY_CLI_THEME_TOKEN }} run: | set -euo pipefail : "${SHOPIFY_FLAG_STORE:?Missing store}" : "${SHOPIFY_CLI_THEME_TOKEN:?Missing Theme Access password}" LIVE_ID=$(shopify theme list --role live --json | jq -er 'select(length == 1) | .[0].id') if [[ ! "$LIVE_ID" =~ ^[0-9]+$ ]]; then echo "Live theme ID must be numeric." >&2 exit 1 fi NAME="Release $(date -u +%Y%m%d-%H%M%S) ${GITHUB_SHA::7}" NEW_ID=$(shopify theme duplicate --theme "$LIVE_ID" --name "$NAME" --force --json | jq -er '.theme.id // empty') if [[ ! "$NEW_ID" =~ ^[0-9]+$ || "$NEW_ID" == "$LIVE_ID" ]]; then echo "Duplicate did not return a distinct numeric theme ID." >&2 exit 1 fi printf 'Previous live theme: %s\nCandidate theme: %s\nCommit: %s\n' "$LIVE_ID" "$NEW_ID" "$GITHUB_SHA" printf 'Previous live theme: `%s`\nCandidate theme: `%s`\nCommit: `%s`\n' "$LIVE_ID" "$NEW_ID" "$GITHUB_SHA" >> "$GITHUB_STEP_SUMMARY" shopify theme push \ --theme "$NEW_ID" \ --nodelete \ --ignore "config/settings_data.json" \ --ignore "templates/*.json" \ --ignore "sections/*.json" # A different live theme means the release was prepared against an outdated baseline. CURRENT_LIVE_ID=$(shopify theme list --role live --json | jq -er 'select(length == 1) | .[0].id') if [[ "$CURRENT_LIVE_ID" != "$LIVE_ID" ]]; then echo "The live theme changed during deployment; leaving the candidate unpublished." >&2 exit 1 fi shopify theme publish --theme "$NEW_ID" --force