Skip to content

fix(e2e): decouple smoke home test from featured collection image (#3… #279

fix(e2e): decouple smoke home test from featured collection image (#3…

fix(e2e): decouple smoke home test from featured collection image (#3… #279

Workflow file for this run

# We use this singular file for all of our releases because we can only
# specify a singular GitHub workflow file in npm's Trusted Publishing configuration.
name: Release
on:
push:
branches:
- main
# To do a back-fix of a past CalVer branch, update this to the relevant branch
# Example: If we are currently on 2025-07, add 2025-01 here to do a back-fix
# release for the 2025-01 CalVer branch
- 2025-01
workflow_dispatch:
concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && 'preview' || github.ref_name }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
id-token: write # Required for npm OIDC Trusted Publishing
jobs:
# ============================================
# PRODUCTION RELEASE (push to main, changesets)
# ============================================
release:
name: Production Release
runs-on: ubuntu-latest
if: github.repository_owner == 'shopify' && github.event_name == 'push' && github.ref_name == 'main'
permissions:
contents: write # enable pushing changes to the origin
id-token: write # enable generation of an ID token for publishing
outputs:
published: ${{ steps.changesets.outputs.published }}
publishedPackages: ${{ steps.changesets.outputs.publishedPackages }}
latest: ${{ env.latest }}
latestBranch: ${{ env.latestBranch }}
latestVersion: ${{ env.latestVersion }}
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: 'pnpm-lock.yaml'
node-version: 24 # Needed for npm@11 for Trusted Publishing
- name: Install the packages
run: pnpm install --frozen-lockfile
- name: Detect latest branch and version
id: flags
run: |
# Check if any CalVer packages have changesets (CalVer precedence logic)
HAS_CALVER=$(node .changeset/calver-shared.js has-calver-changesets)
echo "Has CalVer changesets: $HAS_CALVER"
if [ "$HAS_CALVER" = "true" ]; then
# CalVer packages have changesets - use CalVer version format
BRANCH=$(node .changeset/get-calver-version-branch.js)
echo "latestBranch=$BRANCH" >> $GITHUB_ENV
echo "latest=${{ github.ref_name == 'main' }}" >> $GITHUB_ENV
echo "Detected latestBranch: $BRANCH"
# Calculate next CalVer version using existing calver utilities
HYDROGEN_VERSION=$(node -p "require('./packages/hydrogen/package.json').version")
HAS_MAJOR=$(node .changeset/calver-shared.js has-major-changesets)
if [ "$HAS_MAJOR" = "true" ]; then
NEXT_VERSION=$(node .changeset/calver-shared.js get-next "$HYDROGEN_VERSION" "major")
echo "latestVersion=$NEXT_VERSION" >> $GITHUB_ENV
echo "Detected next version (major): $NEXT_VERSION"
else
NEXT_VERSION=$(node .changeset/calver-shared.js get-next "$HYDROGEN_VERSION" "patch")
echo "latestVersion=$NEXT_VERSION" >> $GITHUB_ENV
echo "Detected next version (patch): $NEXT_VERSION"
fi
else
# Only semver packages have changesets - use semver release format
echo "latestBranch=semver" >> $GITHUB_ENV
echo "latest=${{ github.ref_name == 'main' }}" >> $GITHUB_ENV
echo "latestVersion=semver" >> $GITHUB_ENV
echo "Detected semver-only release"
fi
- name: Build the dist code
run: pnpm run build
- name: Check for major protection bypass
if: env.latest == 'true'
run: |
echo "Checking for active major version bypass..."
# If bypass is active, ensure old release PR is closed
BYPASS_PRS=$(gh pr list --state open --label "major-bypass-active" --json number -q '.[].number' || echo "")
if [ -n "$BYPASS_PRS" ]; then
echo "Major bypass active on PR(s): $BYPASS_PRS"
echo "Checking for existing release PR to close..."
# Close any existing release PR to prevent conflicts
RELEASE_PR=$(gh pr list --state open --head changeset-release/main --json number -q '.[].number' || echo "")
if [ -n "$RELEASE_PR" ]; then
echo "Closing release PR #$RELEASE_PR due to active major bypass"
gh pr close $RELEASE_PR -c "Automatically closed: Major version bypass is active on PR #$BYPASS_PRS"
fi
else
echo "No active major bypass found"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Test OIDC Token
if: env.latest == 'true'
run: |
TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=npm" | jq -r '.value')
[ -n "$TOKEN" ] && echo "✅ OIDC working" || exit 1
- name: Create Release Pull Request or Publish (for latest release)
if: env.latest == 'true'
id: changesets
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
version: pnpm run version
publish: pnpm run changeset publish
# we use the commit message in next release workflow file. This avoid a next release when an actual release is happening
commit: '[ci] release ${{ env.latestVersion }}'
title: '[ci] release ${{ env.latestVersion }}'
env:
GITHUB_TOKEN: ${{ secrets.SHOPIFY_GH_ACCESS_TOKEN }}
NPM_TOKEN: '' # Empty string forces OIDC authentication
# ============================================
# NEXT/SNAPSHOT RELEASE (push to main, skips [ci] release commits)
# ============================================
next-release:
name: Next Release
runs-on: ubuntu-latest
if: |
github.repository_owner == 'shopify' &&
github.event_name == 'push' &&
github.ref_name == 'main' &&
!startsWith(github.event.head_commit.message, '[ci] release')
permissions:
contents: write # enable pushing changes to the origin
id-token: write # enable generation of an ID token for publishing
outputs:
NEXT_VERSION: ${{ steps.version.outputs.NEXT_VERSION }}
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: 'pnpm-lock.yaml'
node-version: 24 # Needed for npm@11 for Trusted Publishing
- name: Install the packages
run: pnpm install --frozen-lockfile
- name: Format release with Prettier
run: pnpm run format
- name: 🕵️ Check for changes
id: version
run: |
# get latest commit sha
SHA=$(git rev-parse HEAD)
# get first 7 characters of sha
SHORT_SHA=${SHA::7}
NEXT_VERSION=next-${SHORT_SHA}
# set output so it can be used in other jobs
echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_OUTPUT
- name: 🏗 Build CLI
if: steps.version.outputs.NEXT_VERSION
run: pnpm run build
- name: ⤴️ Update version
if: steps.version.outputs.NEXT_VERSION
run: |
git config user.email "hydrogen@shopify.com"
git config user.name "Hydrogen Bot"
git checkout -B next/${{ steps.version.outputs.NEXT_VERSION }}
# using changeset snapshot releases, this sets the version to 0.0.0-{tag}-DATETIMESTAMP where tag=next-SHORT_SHA
# as an example this results in a next release as following 0.0.0-next-1686a75-20230313113149 with a next tag
pnpm run version:next
pnpm run changeset -- version --snapshot ${{ steps.version.outputs.NEXT_VERSION }}
pnpm run version:post
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 🏗 Build
if: steps.version.outputs.NEXT_VERSION
run: pnpm run build
- name: Test OIDC Token
if: steps.version.outputs.NEXT_VERSION
run: |
TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=npm" | jq -r '.value')
[ -n "$TOKEN" ] && echo "✅ OIDC working" || exit 1
- name: Publish to npm
if: steps.version.outputs.NEXT_VERSION
run: pnpm run changeset -- publish --tag next
env:
NPM_TOKEN: '' # Empty string forces OIDC authentication
# ============================================
# PREVIEW RELEASE (manual dispatch, publishes preview branch)
# ============================================
preview-release:
name: Preview Release
runs-on: ubuntu-latest
if: github.repository_owner == 'shopify' && github.event_name == 'workflow_dispatch' && (github.ref_name == 'main' || github.ref_name == 'preview')
permissions:
contents: read
id-token: write # enable generation of an ID token for publishing
outputs:
PREVIEW_VERSION: ${{ steps.version.outputs.PREVIEW_VERSION }}
steps:
- name: ⬇️ Checkout preview branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
with:
ref: preview
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: 'pnpm-lock.yaml'
node-version: 24 # Needed for npm@11 for Trusted Publishing
- name: Install the packages
run: pnpm install --frozen-lockfile
- name: 🔢 Compute preview version
id: version
run: |
# get latest commit sha from the checked out preview branch
SHA=$(git rev-parse HEAD)
# get first 7 characters of sha
SHORT_SHA=${SHA::7}
TIMESTAMP=$(date -u +%Y%m%d%H%M%S)
PREVIEW_VERSION=0.0.0-preview-${SHORT_SHA}-${TIMESTAMP}
# set output so it can be used in other jobs
echo "PREVIEW_VERSION=${PREVIEW_VERSION}" >> $GITHUB_OUTPUT
- name: ⤴️ Set preview version
if: steps.version.outputs.PREVIEW_VERSION
run: |
node <<'EOF'
const fs = require('fs');
const packageJsonPath = 'packages/hydrogen/package.json';
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
packageJson.version = process.env.PREVIEW_VERSION;
fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`);
console.log(`Set ${packageJson.name} to ${packageJson.version}`);
EOF
pnpm run version:hydrogen
env:
PREVIEW_VERSION: ${{ steps.version.outputs.PREVIEW_VERSION }}
- name: ✅ Check
if: steps.version.outputs.PREVIEW_VERSION
run: pnpm run check
- name: Test OIDC Token
if: steps.version.outputs.PREVIEW_VERSION
run: |
TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=npm" | jq -r '.value')
[ -n "$TOKEN" ] && echo "✅ OIDC working" || exit 1
- name: Publish to npm
if: steps.version.outputs.PREVIEW_VERSION
run: npm publish packages/hydrogen --tag preview --access public --provenance
env:
NPM_TOKEN: '' # Empty string forces OIDC authentication
# ============================================
# BACK-FIX RELEASE (push to calver branches)
# ============================================
backfix-release:
name: Back-fix Release
runs-on: ubuntu-latest
if: github.repository_owner == 'shopify' && github.event_name == 'push' && github.ref_name != 'main'
permissions:
contents: write # enable pushing changes to the origin
id-token: write # enable generation of an ID token for publishing
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
cache-dependency-path: 'pnpm-lock.yaml'
node-version: 24 # Needed for npm@11 for Trusted Publishing
- name: Install the packages
run: pnpm install --frozen-lockfile
- name: Format release with Prettier
run: pnpm run format
- name: Build the dist code
run: pnpm run build
- name: Test OIDC Token
run: |
TOKEN=$(curl -s -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=npm" | jq -r '.value')
[ -n "$TOKEN" ] && echo "✅ OIDC working" || exit 1
- name: Create Back-fix Release Pull Request or Publish (for back-fix release)
id: changesets
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
version: pnpm run version
publish: pnpm run changeset -- publish --tag ${{ github.ref_name }}
commit: '[ci] back-fix release ${{ github.ref_name }}'
title: '[ci] back-fix release ${{ github.ref_name }}'
env:
GITHUB_TOKEN: ${{ secrets.SHOPIFY_GH_ACCESS_TOKEN }}
NPM_TOKEN: '' # Empty string forces OIDC authentication
# ============================================
# COMPILE TEMPLATES (after production release publishes)
# ============================================
compile:
needs: release
# Only compile templates if a release was published, and we're on the "latest" release branch
if: needs.release.outputs.published == 'true' && needs.release.outputs.latest == 'true'
runs-on: ubuntu-latest
name: Compile the typescript templates and push them to main
steps:
- name: Checkout the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320
with:
run_install: false
- name: Setup Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
cache: 'pnpm'
cache-dependency-path: 'pnpm-lock.yaml'
node-version: 24
- name: Install the packages
run: pnpm install --frozen-lockfile
- name: Build the dist code
run: pnpm run build
- name: Compile skeleton
run: |
node scripts/compile-template-for-dist.mjs skeleton
(cd templates/skeleton-js && pnpm install --lockfile-only --ignore-workspace)
(cd templates/skeleton-ts && pnpm install --lockfile-only --ignore-workspace)
- name: Update templates in the dist branch
run: |
git add .
git status
git config user.email "hydrogen@shopify.com"
git config user.name "Hydrogen Bot"
git show-ref
git commit -m "Update templates for dist"
git push origin HEAD:dist --force