test: upgrade flow testing#3507
Merged
itsjustriley merged 11 commits intomainfrom Mar 19, 2026
Merged
Conversation
Contributor
|
Oxygen deployed a preview of your
Learn more about Hydrogen's GitHub integration. |
9d5324c to
6b16405
Compare
This comment has been minimized.
This comment has been minimized.
|
🤖 Code Review · #projects-dev-ai for questions ✅ Complete - 1 findings 📋 History✅ 1 findings → ✅ 1 findings → ✅ 1 findings |
0eb58c7 to
737d1d2
Compare
62a9d08 to
ec2fc47
Compare
5 tasks
ce3c19c to
20c667c
Compare
The previous upgrade-flow.test.ts used mocked file system operations and upgrade logic, making it prone to false positives that didn't reflect real upgrade behavior. This replaces it with upgrade-e2e.test.ts, which scaffolds real skeleton projects from git history and runs the full upgrade command end-to-end. Key design decisions: - Uses git archive to extract skeleton templates at exact historical commits, ensuring the scaffolded project matches what merchants actually had at that version rather than a synthetic approximation - Builds a version matrix from the changelog (one upgrade path per major CalVer train per year, within a 365-day lookback window) so coverage scales automatically as new releases land - Skips build validation when manual steps or breaking changes are present, since developers must apply those steps before a project will build - Validates dependency versions in package.json after upgrade to catch changelog inaccuracies early Co-authored-by: Claude <claude@anthropic.com>
…er-deps consistently Three related fixes to the upgrade command's dependency management: 1. Accumulate removeDependencies and removeDevDependencies across all intermediate releases when upgrading across multiple versions. Previously only the target release's removals were applied, causing packages removed in intermediate releases (e.g. @shopify/remix-oxygen) to remain installed. 2. Add --legacy-peer-deps to npm install. npm v7+ strict peer dep resolution rejects installing packages that conflict with currently-installed versions, even when those old versions are being replaced in the same command. --legacy-peer-deps reverts to npm v6 behavior, which resolves correctly for upgrade scenarios where peer dep versions are changing. pnpm/yarn handle this without special flags. 3. Add --legacy-peer-deps to npm uninstall for the same reason. npm v7+ runs full peer dep resolution during uninstall too, which rejects the operation when old and new peer dep ranges conflict (e.g. vite@^5 from an old scaffold vs vite@^6 required by the new mini-oxygen). Co-authored-by: Claude <claude@anthropic.com>
Some changelog entries have hashes that point to blob objects rather than commits (e.g. all 2025.1.x versions), and CI's shallow clone can't find them via git log search either. Two compounding problems required a two-part fix: 1. resolveSkeletonCommit now walks back through all releases in the same major train (YYYY.M) rather than one step, stopping at the first valid commit. A major-train boundary guard (getMajorVersion) prevents silently crossing year boundaries, which would scaffold from a structurally different release and compromise test fidelity. The repeated hash-validate + git-search-fallback logic is extracted into resolveReleaseCommit, making the walk-back loop body a one-liner. 2. The test loop now catches ScaffoldNotFoundError (a typed class replacing the generic Error throw) and skips that upgrade path with a warning rather than aborting the full matrix. A testedCount guard ensures we fail loudly if no paths could be tested at all, preventing silent false greens. Co-authored-by: Claude <claude@anthropic.com>
c476055 to
98ed36d
Compare
Replace shell-interpolated execAsync calls with shell-free execFileAsync (promisify(execFile)) throughout the git commit search helpers, eliminating a shell injection vector where release.hash from changelog.json was interpolated into sh -c strings. Additional fixes surfaced during consensus review: - Replace findGitRepoRoot (fragile relative-path probe) with getRepoRoot using git rev-parse --show-toplevel for canonical repo root resolution - Remove git fetch origin from test execution (network call, mutates local state, already present from CI checkout) - Consolidate the two independent hardcoded repoRoot join(cwd, '../../') callsites in resolveSkeletonCommit and extractSkeletonTemplate to use getRepoRoot() with an explicit error when outside a git repo - Add console.warn when resolveSkeletonCommit falls back to a prior version's skeleton, making the substitution visible in test output - Remove unreachable toBeDefined() assertion from validateDependencyVersion (all callers guard with if (actualVersion) before calling) - Replace sequential npm view loop in arePackagesPublished with Promise.allSettled for concurrent package existence checks - Throw on empty UPGRADE_TEST_LAST_N result instead of silently returning an empty matrix (which would appear as a passing no-op test run) - Extend test-upgrade-flow.yml trigger paths to include upgrade*.ts so changes to the test or command files re-run CI without a changelog edit - Add changeset for @shopify/cli-hydrogen patch (runUpgrade/getChangelog are now exported as public API) Co-authored-by: Claude <claude@anthropic.com>
The upgrade E2E tests scaffold historical skeleton versions by calling git show <commit>:templates/skeleton/package.json and git log across the full commit history. actions/checkout defaults to depth=1 (shallow clone), which means all historical commits are unavailable — causing every scaffold attempt to fail and the entire test suite to report "no upgrade paths could be tested". fetch-depth: 0 fetches the complete history so git archive and git log can reach the release commits referenced in changelog.json. Co-authored-by: Claude <claude@anthropic.com>
The upgrade-e2e.test.ts was running in the regular pnpm test / turbo
test suite, which uses a shallow git clone in CI. All scaffolding
attempts failed with ScaffoldNotFoundError, causing the Unit tests
CI job to fail. The test belongs exclusively in test-upgrade-flow.yml
which already has fetch-depth: 0.
- Add **/*.e2e.test.ts to vitest test.exclude (spreading configDefaults
to preserve defaults like **/dist/**) so e2e tests only run in their
dedicated CI workflow
- Replace exec('mv', ...) with rename() from node:fs/promises for
cross-platform correctness and consistency with the rest of the file
- Remove misleading "defense-in-depth" comment and redundant toBeDefined()
check from validateDependencyVersion — TypeScript types already
guarantee the parameter is string; the comment implied undefined was
possible when it isn't
- Update changeset description to accurately describe the user-facing
changes: intermediate dep accumulation and --legacy-peer-deps for npm
…uns via dedicated workflow
The pattern **/*.e2e.test.ts uses a dot separator and does not match upgrade-e2e.test.ts which uses a hyphen. Changed to **/*-e2e.test.ts so the file is actually excluded from the regular unit test run.
…conflict vitest's exclude patterns take precedence over CLI file filters, so the **/*-e2e.test.ts exclusion in vitest.config.ts also blocked the dedicated test-upgrade-flow.yml workflow from running the test. Solution: a separate vitest.e2e.config.ts that explicitly includes src/**/*-e2e.test.ts (with its own timeout). The dedicated workflow now uses --config vitest.e2e.config.ts directly, bypassing the unit test exclusion entirely. Regular pnpm test continues to use vitest.config.ts which still excludes **/*-e2e.test.ts.
A change to vitest.e2e.config.ts (e.g. adjusting timeout or include pattern) would not previously trigger the workflow, meaning a broken config change would only be caught when changelog.json or upgrade*.ts next changed.
…e paths The post-upgrade npm install validation step now uses --legacy-peer-deps only for upgrade paths with manual steps or breaking changes, where the project is in an intermediate state with expected peer dep conflicts from old-era transitive dependencies. Clean upgrade paths retain strict peer dep resolution, which catches incomplete or inaccurate changelog entries that would otherwise be masked. This mirrors the production upgrade command's use of --legacy-peer-deps while being intentionally stricter for clean paths as a changelog accuracy check. Co-authored-by: Claude <noreply@anthropic.com>
kdaviduik
approved these changes
Mar 19, 2026
Contributor
kdaviduik
left a comment
There was a problem hiding this comment.
some comments/suggestions but I'd be happy to ship this and do any of these as a follow-up. imo not an urgent follow-up (we have bigger fish to fry and real issues to fix!). LGTM 🚀
Contributor
Author
|
cookie tests fail on main, all relevant tests pass. |
Merged
This was referenced Apr 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WHY are these changes introduced?
Fixes https://github.com/Shopify/developer-tools-team/issues/1045
Two problems:
Flaky E2E tests: The existing `upgrade-flow.test.ts` was unreliable. Tests would intermittently fail in CI due to dev server flakiness (port conflicts, spawn/kill race conditions, HTTP timeouts), creating toil for releases.
Broken multi-version upgrades: When upgrading across multiple versions (e.g. 2025.4.x → 2026.1.0), the upgrade command only applied the target release's dependency list — missing intermediate bumps. It also failed with ERESOLVE errors for npm users because npm v7+ strict peer dep resolution rejects installing packages that conflict with currently-installed versions being replaced in the same command.
WHAT is this pull request doing?
Replaces `upgrade-flow.test.ts` (1313 lines) with `upgrade-e2e.test.ts`:
Fixes production upgrade bugs in `upgrade.ts`:
Default E2E matrix behavior:
Explicit matrix controls:
HOW to test your changes?
E2E test scenarios
Tophatting commands
Verify CI
Post-merge steps
None required.
Checklist