Skip to content

Comments

test: update upgrade tests#3472

Open
itsjustriley wants to merge 2 commits intomainfrom
e2e-upgrade-tests
Open

test: update upgrade tests#3472
itsjustriley wants to merge 2 commits intomainfrom
e2e-upgrade-tests

Conversation

@itsjustriley
Copy link
Contributor

@itsjustriley itsjustriley commented Feb 17, 2026

WHY are these changes introduced?

Fixes https://github.com/Shopify/developer-tools-team/issues/1045

The existing upgrade flow tests were unreliable. Tests would intermittently fail in CI due to dev server flakiness (port conflicts, spawn/kill race conditions, HTTP timeouts), making it difficult to validate changelog.json entries/upgrade flow. This should reduce toil for future releases.

WHAT is this pull request doing?

This PR refactors the upgrade flow tests to be more focused, and fail faster to ensure that new changelog.json entries enable successful upgrades.

The test validates:

  • Scaffolds a project from the previous release
  • Runs actual h2 upgrade command to latest version
  • Dependencies and devDependencies are upgraded correctly
  • Dependencies are removed when specified (e.g., removeDependencies array)
  • Upgrade guide markdown is generated when release has manual steps
  • npm install succeeds without conflicts
  • npm run build succeeds (when no manual steps required)

Key Decisions:

  1. Remove dev server validation and validate build instead, which catches same errors aside from runtime (which we can trust other tests to catch)
  2. Testing only previous previous → latest
  3. Uses current skeleton with simulated old version (could investigate git history/tags, but it didn't seem functional in CI)
  4. Simplified schema validation to fail fast before integration tests
  5. Use actual h2 upgrade command
  6. Gracefully skips when packages aren't published yet
  7. Skip build when manual steps are required, but validate dependencies install/markdown is generated
  8. Only trigger on changelog.json changes

HOW to test your changes?

  1. Run test locally:

    cd packages/cli
    npm test upgrade-flow.test.ts

    Expected: Both tests pass

  2. Verify CI workflow:
    - Modify docs/changelog.json (add a comma or whitespace)
    - Push to a branch
    - The test-upgrade-flow.yml workflow should trigger automatically
    - Check that it passes

Checklist

  • I've read the Contributing Guidelines
  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've added a changeset if this PR contains user-facing or noteworthy changes
  • I've added tests to cover my changes
  • I've added or updated the documentation (workflow includes detailed comments)

@shopify
Copy link
Contributor

shopify bot commented Feb 17, 2026

Oxygen deployed a preview of your e2e-upgrade-tests branch. Details:

Storefront Status Preview link Deployment details Last update (UTC)
Skeleton (skeleton.hydrogen.shop) ✅ Successful (Logs) Preview deployment Inspect deployment February 23, 2026 6:26 PM

Learn more about Hydrogen's GitHub integration.

@itsjustriley itsjustriley force-pushed the e2e-upgrade-tests branch 10 times, most recently from 8df9450 to eed6a44 Compare February 17, 2026 15:01
@itsjustriley itsjustriley marked this pull request as ready for review February 17, 2026 15:16
@itsjustriley itsjustriley requested a review from a team as a code owner February 17, 2026 15:16
@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.

import {exec} from '@shopify/cli-kit/node/system';
import {execAsync} from '../../lib/process.js';
import * as upgradeModule from './upgrade.js';
import {spawn, ChildProcess} from 'node:child_process';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(threading)

Issue/bug: scaffolding only downgrades @shopify/hydrogen, not other dependencies


What: scaffoldHistoricalProject() copies the current skeleton and only changes version and dependencies['@shopify/hydrogen']. All other dependencies remain at HEAD
versions.

Why it matters: The upgrade command thinks it's upgrading from the previous version, but most dependencies are already at the latest version. This means the test can pass without going through the full upgrade flow that merchants experience. Also, this may cause issues down the line (eg: Remix --> RR7 is an example where this bug would've caused issues)

Fix: Use previousRelease.dependencies and previousRelease.devDependencies from the changelog to set ALL starting dependency versions, not just hydrogen:

if (previousRelease.dependencies) {
 for (const [dep, ver] of Object.entries(previousRelease.dependencies)) {
   packageJson.dependencies[dep] = ver;
 }
}
if (previousRelease.devDependencies) {
 for (const [dep, ver] of Object.entries(previousRelease.devDependencies)) {
   packageJson.devDependencies[dep] = ver;
 }
}

renderConfirmationPrompt: vi.fn(() => Promise.resolve(true)), // Always confirm
renderInfo: vi.fn(() => {}), // Mock renderInfo to silence output
renderSuccess: vi.fn(() => {}), // Mock renderSuccess to silence output
renderConfirmationPrompt: vi.fn(() => Promise.resolve(true)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(threading)

This also eliminates (without replacement) a few other validations/checks of the changelog.json file:

Image

I definitely think we should have these validations, though this test doesn't feel like the place to put it imo. I think we should just have a CI step that ensures the JSON formatting is correct.

Or even better but less trivial would be to use a Zod schema to validate this JSON file

Copy link
Contributor

@fredericoo fredericoo Feb 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree on the schema validation for the json file

but i think our tests were too flaky to begin with

what do we want to test?

my educated guess is:

  • whether changelog.json matches a specific format
  • whether we can read the package.json from a project
  • whether we can detect what "hydrogen packages" version a package.json has
  • whether we can detect if they are on the latest
  • whether we can modify package versions in a package.json
  • whether we can call the install command on behalf of the user

for none of those we need to fetch an external changelog from a backend

but our functions in upgrade.ts are so bound together and filesystem dependant, that makes testing really hard

pseudocode for what i imagine would be easy to test for all those cases:

function upgrade(packageJsonService, changelog) {
  const versions = getHydrogenPackageVersions(packageJsonService);
  const needUpgrading = getOutdatedPackageVersions(versions, changelog);
  if (needUpgrading.length === 0) return;
  await updatePackageVersions(packageJsonService);
  await installPackages();
  return;
}

(extra points if we use Effect, or at least errors as values)

maybe we should push a refactor of upgrade as tech debt?

);
}
}
process.env.FORCE_CHANGELOG_SOURCE = 'local';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these lines set FORCE_CHANGELOG_SOURCE, SHOPIFY_HYDROGEN_FLAG_FORCE, and CI on process.env but never restore them.

Why it matters: These leak to subsequent tests in the same worker. The sibling upgrade.test.ts handles this correctly with save/restore.

Fix: Use vi.stubEnv() (auto-restores on teardown) or save/restore in afterEach.

async function scaffoldHistoricalProject(commit: string): Promise<string> {
const tempDir = await mkdtemp(join(tmpdir(), 'hydrogen-upgrade-test-'));
const projectDir = join(tempDir, 'test-project');
const projectDir = await scaffoldHistoricalProject(fromVersion);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function no longer scaffolds a historical project — it copies the current skeleton and changes the version. I think we should rename this to something like scaffoldProjectAtVersion(version) or createTestProjectWithVersion(version).

}
}
async function scaffoldHistoricalProject(version: string): Promise<string> {
const tempDir = await mkdtemp(join(tmpdir(), 'hydrogen-upgrade-test-'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from Claude, seems reasonable

mkdtemp creates directories that are never cleaned up. Use inTemporaryDirectory from @shopify/cli-kit/node/fs (like the sibling test does) or add cleanup in afterAll.

if (!reinstalledDeps[dep]) {
expect(packageJson.dependencies?.[dep]).toBeUndefined();
}
if (!hasUpgradeSteps) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a comment here (explaining that projects with manual upgrade steps may not build until those steps are applied) about why we are doing this since it's not necessarily obvious. .

});
}
}
}, 180000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(threading)

If someone submitted a changelog.json PR before the package(s) being upgraded have been released, the upgrade tests would skip and CI would appear successful, but we would have zero guarantees the change actually works.

Imo this test should fail if any packages specified haven't been released yet. This could be due to a genuine bug/typo, or because our packages haven't been released yet. Either way, I think this test failing if the package version doesn't exist would be helpful

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