Skip to content

Conversation

@juanpprieto
Copy link
Contributor

@juanpprieto juanpprieto commented Sep 26, 2025

Summary

Adds --version=next flag support to the Hydrogen CLI upgrade command, enabling developers to test unpublished package versions.

Why

Testing the upgrade command to upcoming Hydrogen versions is near impossible. This feature and associated e2e tests help us validate that soon-to-be-published changelog updates releases can successfully be upgraded to from the previous release. Merging this to main and rebasing the changelog branch should make the upgrade e2e flow tests pass on that branch. The final confirmation we are ready to release.

Developers can now test bleeding-edge features with a simple command: npx shopify hydrogen upgrade --version=next although this feature is intended for Hydrogen core maintainers testing. Hydrogen projects should never run @next versions as these are experimental until officially released.

What

When a new changelog.json entry is added including not yet published packages, the next version will be used by CI tests for both @shopify/hydrogen and @shopify/mini-oxygen. All other changelog versions for the latest entry will be respected to simulate the upgrade path as close as possible.

Test plan

Prerequisites

  • Existing Hydrogen project (2025.4.x or earlier). This Complementary PR would help us automate this step in the future.
  • Clean git working directory

Core Functionality Test

1. Create/find a outdated hydrogen project:

   npm create @shopify/hydrogen@latest test-next-upgrade  (currently 2025.5.0)
   cd test-next-upgrade
   git init && git add . && git commit -m "Initial commit"

2. Update docs/changelog.json

Temporary add the following release entry to the array above 2025.4.1. Note: this is a WIP version of the actual 2025.7.0 release entry.

Screenshot 2025-09-26 at 5 49 07 PM
Details
{
   "title": "React Router 7 migration with API version 2025-07",
   "version": "2025.7.0",
   "date": "2025-09-17",
   "hash": "pending-merge",
   "commit": "https://github.com/Shopify/hydrogen/pull/3166",
   "pr": "https://github.com/Shopify/hydrogen/pull/3166",
   "dependencies": {
     "@shopify/hydrogen": "2025.7.0",
     "react-router": "7.9.2",
     "react-router-dom": "7.9.2",
     "react": "18.3.1",
     "react-dom": "18.3.1"
   },
   "devDependencies": {
     "@shopify/mini-oxygen": "4.0.0",
     "@shopify/cli": "3.83.3",
     "@react-router/dev": "7.9.2",
     "@react-router/fs-routes": "7.9.2"
   },
   "removeDependencies": [
     "@shopify/hydrogen",
     "@shopify/remix-oxygen",
     "@remix-run/react",
     "@remix-run/server-runtime",
     "react-router",
     "react-router-dom",
     "react",
     "react-dom",
     "@react-router/node"
   ],
   "removeDevDependencies": [
     "@remix-run/dev",
     "@remix-run/fs-routes",
     "@remix-run/route-config",
     "@react-router/fs-routes",
     "@react-router/dev"
   ],
   "dependenciesMeta": {
     "@shopify/cli": {
       "required": true
     },
     "react-router": {
       "required": true
     },
     "@react-router/dev": {
       "required": true
     },
     "@react-router/fs-routes": {
       "required": true
     },
     "@shopify/mini-oxygen": {
       "required": true
     },
     "@shopify/remix-oxygen": {
       "required": false
     },
     "@remix-run/react": {
       "required": false
     },
     "@remix-run/server-runtime": {
       "required": false
     },
     "@remix-run/dev": {
       "required": false
     },
     "@remix-run/fs-routes": {
       "required": false
     },
     "@remix-run/route-config": {
       "required": false
     }
   },
   "fixes": [
     {
       "title": "Stabilize Customer Account API development flag",
       "info": "The --customer-account-push flag is now stable, enabling tunneling for local development with Customer Account API OAuth flows.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3082",
       "id": "3082-flag"
     },
     {
       "title": "Fix defer/streaming in development & preview",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039"
     },
     {
       "title": "Fix GraphQL client development warnings",
       "info": "Remove sourcemap warnings and page reloads during development.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3108",
       "id": "3108"
     },
     {
       "title": "Fix Money component compatibility with USDC currency",
       "info": "Updates Money component to handle unsupported currency codes like USDC from Customer Account API.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3082",
       "id": "3082-money"
     },
     {
       "title": "Fix parseMetafield money type currency handling",
       "info": "Transform currency_code (from Storefront API) to currencyCode (expected by MoneyV2 type).",
       "pr": "https://github.com/Shopify/hydrogen/pull/3072",
       "id": "3072"
     },
     {
       "title": "Fix TypeScript enum compatibility between APIs",
       "info": "Updated codegen to reference Storefront API's LanguageCode and CurrencyCode enums for Customer Account API types.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3139",
       "id": "3139"
     },
     {
       "title": "Add TypeScript ESLint rules for promise handling",
       "info": "Add TypeScript ESLint rules for promise handling to avoid deployment errors on Oxygen/Cloudflare Workers.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3146",
       "id": "3146"
     },
     {
       "title": "Fix environment variable quoting in env pull command",
       "info": "Properly handles shell metacharacters in environment variables.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3050",
       "id": "3050"
     },
     {
       "title": "Add --force-client-sourcemap flag to deploy command",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-sourcemap"
     },
     {
       "title": "Add Vite v7 exports support",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-vite"
     },
     {
       "title": "Fix and upgrade GraphiQL route",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-graphiql"
     },
     {
       "title": "Replace deprecated faker.internet.color()",
       "info": "Updated to use faker.color.rgb() instead.",
       "pr": "https://github.com/Shopify/hydrogen/pull/2985",
       "id": "2985"
     }
   ],
   "features": [
     {
       "title": "Migrate to React Router 7.9.x",
       "info": "Migrates Hydrogen to React Router 7.9.x with automatic type generation and improved type safety. Removes @shopify/remix-oxygen package.",
       "breaking": true,
       "steps": [
         {
           "title": "Run the automated migration codemod",
           "info": "This codemod will automatically update most imports and references from Remix to React Router",
           "code": "YGBgZGlmZgpucHggQGNvZGVtb2QuY29tL2NvZGVtb2QgcmVtaXgvMi9yZWFjdC1yb3V0ZXIvdXBncmFkZQpgYGAK"
         },
         {
           "title": "Update @shopify/remix-oxygen imports",
           "info": "Replace @shopify/remix-oxygen imports with react-router equivalents",
           "code": "YGBgZGlmZgotIGltcG9ydCB7cmVkaXJlY3QsIHR5cGUgTG9hZGVyRnVuY3Rpb25BcmdzfSBmcm9tICJAc2hvcGlmeS9yZW1peC1veHlnZW4iOworIGltcG9ydCB7cmVkaXJlY3R9IGZyb20gInJlYWN0LXJvdXRlciI7CisgaW1wb3J0IHR5cGUge0xvYWRlckZ1bmN0aW9uQXJnc30gZnJvbSAiQHNob3BpZnkvaHlkcm9nZW4vb3h5Z2VuIjsKYGBgCg=="
         },
         {
           "title": "Update @remix-run/react imports",
           "info": "Replace @remix-run/react imports with react-router equivalents",
           "code": "YGBgZGlmZgotIGltcG9ydCB7dXNlTG9hZGVyRGF0YSwgdHlwZSBNZXRhRnVuY3Rpb259IGZyb20gIkByZW1peC1ydW4vcmVhY3QiOworIGltcG9ydCB7dXNlTG9hZGVyRGF0YX0gZnJvbSAicmVhY3Qtcm91dGVyIjsKYGBgCg=="
         },
         {
           "title": "Add React Router 7 route type imports",
           "info": "Import route-specific types from React Router 7's new type generation system",
           "code": "YGBgZGlmZgorIGltcG9ydCB0eXBlIHtSb3V0ZX0gZnJvbSAiLi8rdHlwZXMvcm91dGUtbmFtZSI7CmBgYAo="
         },
         {
           "title": "Add .react-router to .gitignore",
           "info": "React Router 7 generates type files that should not be committed to version control",
           "code": "YGBgZGlmZgplY2hvICIucmVhY3Qtcm91dGVyLyIgPj4gLmdpdGlnbm9yZQpgYGAK"
         },
         {
           "title": "Update applicable package.json scripts to use react-router typegen",
           "code": "YGBgZGlmZgplY2hvICIucmVhY3Qtcm91dGVyLyIgPj4gLmdpdGlnbm9yZQpgYGAK"
         },
         {
           "title": "Verify your app starts and builds correctly",
           "info": "Test that your application runs without errors after the migration",
           "code": "YGBgZGlmZgpucG0gcnVuIGRldgpucG0gcnVuIGJ1aWxkCmBgYAo="
         }
       ],
       "pr": "https://github.com/Shopify/hydrogen/pull/3141",
       "id": "3141"
     },
     {
       "title": "Adopt new React Router context infrastructure and preset",
       "info": "Major infrastructure changes including new createRequestHandler, hydrogenPreset configuration, enhanced context patterns, and React Context hydration fixes.",
       "breaking": true,
       "steps": [
         {
           "title": "Update server.ts to use new createRequestHandler",
           "info": "Replace @shopify/remix-oxygen import with @shopify/hydrogen/oxygen for enhanced functionality",
           "code": "YGBgZGlmZgovLyBzZXJ2ZXIudHMKLSBpbXBvcnQge2NyZWF0ZVJlcXVlc3RIYW5kbGVyfSBmcm9tICJAc2hvcGlmeS9yZW1peC1veHlnZW4iOworIGltcG9ydCB7Y3JlYXRlUmVxdWVzdEhhbmRsZXJ9IGZyb20gIkBzaG9waWZ5L2h5ZHJvZ2VuL294eWdlbiI7CmBgYAo="
         },
         {
           "title": "Add react-router.config.ts with hydrogenPreset",
           "info": "Create configuration file with Hydrogen's optimized React Router settings",
           "code": "YGBgdHlwZXNjcmlwdAovLyByZWFjdC1yb3V0ZXIuY29uZmlnLnRzCmltcG9ydCB0eXBlIHtDb25maWd9IGZyb20gIkByZWFjdC1yb3V0ZXIvZGV2L2NvbmZpZyI7CmltcG9ydCB7aHlkcm9nZW5QcmVzZXR9IGZyb20gIkBzaG9waWZ5L2h5ZHJvZ2VuL3JlYWN0LXJvdXRlci1wcmVzZXQiOwoKZXhwb3J0IGRlZmF1bHQgewogIHByZXNldHM6IFtoeWRyb2dlblByZXNldCgpXSwKfSBzYXRpc2ZpZXMgQ29uZmlnOwpgYGEK"
         },
         {
           "title": "Update entry.server.tsx type annotations",
           "info": "Replace AppLoadContext with HydrogenRouterContextProvider for enhanced type safety",
           "code": "YGBgZGlmZgovLyBhcHAvZW50cnkuc2VydmVyLnRzeAotIGltcG9ydCB0eXBlIHtBcHBMb2FkQ29udGV4dH0gZnJvbSAiQHNob3BpZnkvcmVtaXgtb3h5Z2VuIjsKaW1wb3J0IHtTZXJ2ZXJSb3V0ZXJ9IGZyb20gInJlYWN0LXJvdXRlciI7CmltcG9ydCB7CiAgY3JlYXRlQ29udGVudFNlY3VyaXR5UG9saWN5LAorIHR5cGUgSHlkcm9nZW5Sb3V0ZXJDb250ZXh0UHJvdmlkZXIsCn0gZnJvbSAiQHNob3BpZnkvaHlkcm9nZW4iOwppbXBvcnQgdHlwZSB7RW50cnlDb250ZXh0fSBmcm9tICJyZWFjdC1yb3V0ZXIiOwoKZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmVxdWVzdCgKICByZXF1ZXN0OiBSZXF1ZXN0LAogIHJlc3BvbnNlU3RhdHVzQ29kZTogbnVtYmVyLAogIHJlc3BvbnNlSGVhZGVyczogSGVhZGVycywKICByZWFjdFJvdXRlckNvbnRleHQ6IEVudHJ5Q29udGV4dCwKLSBjb250ZXh0OiBBcHBMb2FkQ29udGV4dCwKKyBjb250ZXh0OiBIeWRyb2dlblJvdXRlckNvbnRleHRQcm92aWRlciwKKSB7CiAgLy8gUmVzdCBvZiBpbXBsZW1lbnRhdGlvbiB1bmNoYW5nZWQKfQpgYGAK"
         }
       ],
       "pr": "https://github.com/Shopify/hydrogen/pull/3142",
       "id": "3142"
     },
     {
       "title": "Adopt new NonceProvider in entry client",
       "breaking": true,
       "steps": [
         {
           "title": "Update entry.client.tsx to include NonceProvider wrapper",
           "info": "Wrap your app with NonceProvider during hydration to avoid 'Cannot read properties of null (reading 'useContext')' errors",
           "code": "YGBgZGlmZgovLyBhcHAvZW50cnkuY2xpZW50LnRzeAppbXBvcnQge0h5ZHJhdGVkUm91dGVyfSBmcm9tICJyZWFjdC1yb3V0ZXIvZG9tIjsKaW1wb3J0IHtzdGFydFRyYW5zaXRpb24sIFN0cmljdE1vZGV9IGZyb20gInJlYWN0IjsKaW1wb3J0IHtoeWRyYXRlUm9vdH0gZnJvbSAicmVhY3QtZG9tL2NsaWVudCI7CisgaW1wb3J0IHtOb25jZVByb3ZpZGVyfSBmcm9tICJAc2hvcGlmeS9oeWRyb2dlbiI7CgppZiAoIXdpbmRvdy5sb2NhdGlvbi5vcmlnaW4uaW5jbHVkZXMoIndlYmNhY2hlLmdvb2dsZXVzZXJjb250ZW50LmNvbSIpKSB7CiAgc3RhcnRUcmFuc2l0aW9uKCgpID0+IHsKKyAgIC8vIEV4dHJhY3Qgbm9uY2UgZnJvbSBleGlzdGluZyBzY3JpcHQgdGFncworICAgY29uc3QgZXhpc3RpbmdOb25jZSA9IGRvY3VtZW50CisgICAgIC5xdWVyeVNlbGVjdG9yPEhUTUxTY3JpcHRFbGVtZW50Pigic2NyaXB0W25vbmNlXSIpCisgICAgID8ubm9uY2U7CisKICAgIGh5ZHJhdGVSb290KAogICAgICBkb2N1bWVudCwKICAgICAgPFN0cmljdE1vZGU+Ci0gICAgICAgPEh5ZHJhdGVkUm91dGVyIC8+CisgICAgICAgPE5vbmNlUHJvdmlkZXIgdmFsdWU9e2V4aXN0aW5nTm9uY2V9PgorICAgICAgICAgPEh5ZHJhdGVkUm91dGVyIC8+CisgICAgICAgPC9Ob25jZVByb3ZpZGVyPgogICAgICA8L1N0cmljdE1vZGU+LAogICAgKTsKICB9KTsKfQpgYGAK"
         }
       ],
       "pr": "https://github.com/Shopify/hydrogen/pull/3142",
       "id": "3142"
     },
     {
       "title": "Updated Storefront API and Customer Account API version 2025-07",
       "breaking": false,
       "pr": "https://github.com/Shopify/hydrogen/pull/3082",
       "id": "3082"
     },
     {
       "title": "Added countryCode parameter to Customer Account API login",
       "info": "Add countryCode parameter to Customer Account API login method.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3148",
       "id": "3148"
     },
     {
       "title": "Add support for removing individual gift cards from cart",
       "info": "Add cartGiftCardCodesRemove mutation to remove specific gift cards by their IDs.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3128",
       "id": "3128"
     },
     {
       "title": "Upgrade Miniflare from v2 to v3",
       "info": "Internal MiniOxygen API refactored to work with Miniflare v3's new architecture, improving development server performance and compatibility.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039"
     },
     {
       "title": "Add order filtering support to Customer Account API orders route",
       "info": "Add order filtering support to /account/orders route in skeleton template.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3125",
       "id": "3125"
     },
     {
       "title": "Add fulfillmentStatus to Customer Account API order query",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-fulfillment"
     },
     {
       "title": "Add @inContext language support to Customer Account API mutations",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-incontext"
     },
     {
       "title": "Add GraphQL @defer directive support to storefront client",
       "pr": "https://github.com/Shopify/hydrogen/pull/3039",
       "id": "3039-defer"
     },
     {
       "title": "Include cdn.shopify.com by default in CSP connectSrc",
       "info": "Improves Content Security Policy defaults for Shopify CDN resources.",
       "pr": "https://github.com/Shopify/hydrogen/pull/3172",
       "id": "3172"
     }
   ]
 }

3. Upgrade your existing project to the "next" (2025.7.0) version: (inside the monorepo)

npm i
cd ./packages/cli && npm run build
npx shopify plugins link ./
cd ../../ && FORCE_CHANGELOG_SOURCE=local shopify hydrogen upgrade --path ../test-next-upgrade --version=next

FORCE_CHANGELOG_SOURCE=local is the default when running from inside the monorepo.

Screenshot 2025-09-26 at 11 00 18 AM

4. Validate upgrade:

Upgrade should complete without installation errors.

Check git status for package.json, package-lock.json and a migration guide md. Check next version is installed. next in this case is the unreleased 2025.7.0.

Screenshot 2025-09-26 at 5 23 59 PM

5. Improved e2e upgrade-flow tests

5.1 With the changelog release provided above still in place e2e upgrade flow tests should:
cs /packages/cli && npm test src/commands/hydrogen/upgrade-flow.test.ts
Screenshot 2025-09-26 at 4 30 48 PM

When the last release in the changelog e.g 2025.7.0 is not yet in NPM, we run an upgrade using --version next to test all dependency upgrades.

5.2 Without the changelog release (discard changelog.json) changes the upgrade flow tests should:
Screenshot 2025-09-26 at 4 44 22 PM

When the last release is published to npm the next test is skipped and the the Latest test is ran instead with the exact versions in the release entry.

6. --version=next does not work outside the monorepo

Screenshot 2025-09-29 at 7 15 01 PM

7. Confirmation of pasing e2e upgrade test for unpublished 2025.7.0 / next

Screenshot 2025-09-29 at 8 40 23 PM

Expected Behavior

  • ✅ No confirmation prompt (auto-proceeds)
  • ✅ Installs next versions for @Shopify packages (not shopify/cli)
  • ✅ Creates migration guide with breaking change instructions
  • ✅ Completes without npm ERESOLVE errors

Test Coverage

  • Unit Tests: 314 tests passing with --version=next functionality
  • Integration Tests: Full E2E upgrade validation with conditional execution

- Enable upgrade command to handle 'next' versions for @shopify/* packages
- Add comprehensive test coverage for next version scenarios
- Add snapshot version validation for upgrade success
- Export validateUpgrade function for testing
- Fix integration test validation logic for remove+reinstall packages
- Remove debugging artifacts and clean up test names

Enables testing unreleased Hydrogen versions by setting HYDROGEN_UPGRADE_ALLOW_NEXT=1
- Replace HYDROGEN_UPGRADE_ALLOW_NEXT environment variable with intuitive --version=next flag
- Enable direct upgrades to latest @shopify/hydrogen and @shopify/mini-oxygen snapshot versions
- Add runtime package transformation: override @shopify/* packages to 'next' while preserving other dependencies
- Implement synthetic release creation from latest changelog entry with next version overrides
- Add snapshot version validation for upgrade success verification
- Skip confirmation prompts for streamlined --version=next user experience
- Generate migration guides from latest changelog features and fixes
- Add comprehensive test coverage for --version=next functionality
- Update integration tests with conditional execution based on npm package availability
- Fix instruction generation to include breaking changes in migration guides

Enables testing unreleased Hydrogen versions with: npx shopify hydrogen upgrade --version=next
- Minor version bump for @shopify/cli-hydrogen
- Comprehensive documentation with usage examples
- Code samples showing before/after workflow
@juanpprieto juanpprieto requested a review from a team as a code owner September 26, 2025 20:45
@shopify
Copy link
Contributor

shopify bot commented Sep 26, 2025

Oxygen deployed a preview of your test/upgrade branch. Details:

Storefront Status Preview link Deployment details Last update (UTC)
Skeleton (skeleton.hydrogen.shop) ✅ Successful (Logs) Preview deployment Inspect deployment September 30, 2025 3:44 AM

Learn more about Hydrogen's GitHub integration.

@juanpprieto juanpprieto marked this pull request as draft September 26, 2025 20:45
@juanpprieto juanpprieto changed the title Add --version=next support for upgrading to unpublished versions Add --version=next support to upgrade command Sep 26, 2025
- Extract getPackageVersion helper to eliminate code duplication in buildUpgradeCommandArgs
- Simplify validateUpgrade logic with clearer validation comments
- Remove debugging artifacts from upgradeNodeModules function
- Restructure upgrade-flow.test.ts with better organization and helper functions
- Add comprehensive unit tests for --version=next functionality
- Fix TypeScript type errors and remove unused variables
- Add valuable debug logging for test execution visibility

The --version=next feature is now working correctly with clean, maintainable code.
@juanpprieto juanpprieto changed the title Add --version=next support to upgrade command Add --version=next support to upgrade command & improve e2e upgrade tests Sep 27, 2025
@juanpprieto juanpprieto marked this pull request as ready for review September 27, 2025 00:38
@juanpprieto juanpprieto changed the title Add --version=next support to upgrade command & improve e2e upgrade tests Add --version=next support to upgrade command & improve e2e upgrade tests to validate 2025.7.0 Sep 27, 2025
@juanpprieto juanpprieto changed the title Add --version=next support to upgrade command & improve e2e upgrade tests to validate 2025.7.0 Add --version=next support to upgrade command & improve upgrade e2e tests to validate 2025.7.0 Sep 27, 2025
@juanpprieto
Copy link
Contributor Author

/snapshot

…edback

- Add monorepo detection based on project path using isProjectInHydrogenMonorepo()
- Allow --version=next in tests and CI environments using isCI() from cli-kit
- Skip confirmation prompts for --version=next to enable CI automation
- Add comprehensive unit tests for monorepo detection and access controls
- Remove debug logging for clean production code
- Address all maintainer feedback from PR review

The --version=next feature now properly restricts access to monorepo/CI contexts while
maintaining full functionality for testing unreleased Hydrogen versions.
- Add early validation to block --version=next if @shopify/hydrogen or @shopify/mini-oxygen are already 'next'
- Addresses maintainer feedback about confusing 'upgrade next to next' logic
- Provides clear error message explaining why upgrade is blocked
- Eliminates the scenario that caused reviewer confusion

This ensures --version=next is only used for upgrading stable versions to snapshots,
never for refreshing existing next versions.
@github-actions
Copy link
Contributor

We detected some changes in packages/*/package.json or packages/*/src, and there are no updates in the .changeset.
If the changes are user-facing and should cause a version bump, run npm run changeset add to track your changes and include them in the next release CHANGELOG.
If you are making simple updates to examples or documentation, you do not need to add a changeset.

@juanpprieto juanpprieto merged commit 537dbc4 into main Sep 30, 2025
24 checks passed
@juanpprieto juanpprieto deleted the test/upgrade branch September 30, 2025 03:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants