fix(cli): pass correct previous version to migration runner
Description
Fixes a critical bug where CLI migrations were not running during fern upgrade when version redirection occurs, particularly when running the CLI from source.
Root Cause: When the CLI re-runs after upgrade with version redirection, it may use packageVersion === "0.0.0" (when running from source via node dist/prod/cli.cjs). The initial fix attempted to use cliContext.environment.packageVersion as the target version, causing migrations from 0.84.1 → 0.0.0 to yield no migrations.
Impact: Users upgrading from pre-1.0.0 versions (e.g., 0.84.1 → 1.1.0) would see no migrations run when using the CLI from source, missing the critical 1.0.0 migration that sets backward-compatible flags.
Changes Made
- Added
TARGET_VERSION_ENV_VAR(FERN_POST_UPGRADE_VERSION) to explicitly pass the target version from the initial upgrade run to the re-run - Added early return logic (lines 54-75) that detects re-run scenario via
PREVIOUS_VERSION_ENV_VARand runs migrations immediately - Added fallback to read target version from
fern.config.jsonifTARGET_VERSION_ENV_VARis missing (for resilience) - Added guard against running migrations with
"0.0.0"as target version (local dev edge case) - Fixed version tracking to capture
projectConfig.versionbefore mutations and pass it aspreviousVersionBeforeUpgrade - Updated
rerunFernCliAtVersioncall to pass bothFERN_PRE_UPGRADE_VERSIONandFERN_POST_UPGRADE_VERSION - Updated versions.yml entry for 1.0.4 with more detailed description
Testing
- [x] Lint checks pass (biome)
- [x] All CI checks pass (71/71)
- [ ] Manual testing with actual version upgrades from pre-1.0.0 versions
- [ ] Manual testing from source build (
node dist/prod/cli.cjs upgrade) - [ ] Unit tests for re-run scenario (not added)
Review Focus
⚠️ Critical: This fix cannot be fully verified without publishing because the version redirection flow requires actual published versions.
High-priority review areas:
-
Early return logic (lines 54-75):
- Requires
previousVersionto be set, buttargetVersionForMigrationhas a fallback - Falls back to reading
fern.config.jsonifTARGET_VERSION_ENV_VARis missing - Guards against
"0.0.0"target version - Question: What happens if
previousVersionis set but we can't determine a valid target version? Currently returns without running migrations - is this correct?
- Requires
-
Environment variable propagation (lines 157-161):
- Both
FERN_PRE_UPGRADE_VERSIONandFERN_POST_UPGRADE_VERSIONare passed to re-run - Verify: Are there any other code paths that invoke
rerunFernCliAtVersionthat might need these env vars?
- Both
-
Interaction with local-dev special case (lines 131-136):
- The existing special case for
packageVersion === "0.0.0"directly callsrunPostUpgradeSteps - Verify: Does the early return logic interfere with this flow? (It shouldn't since env vars aren't set in this path)
- The existing special case for
-
Fallback resilience:
- If
TARGET_VERSION_ENV_VARis missing, falls back to readingfern.config.json - Question: Could this mask bugs where the env var should be set but isn't? Is the fallback too permissive?
- If
-
Version tracking (line 133):
- Captures
previousVersionBeforeUpgradefromprojectConfig.versionbefore writing new version - Verify: Is this the correct "from" version in all scenarios? What if
projectConfig.versionis"*"?
- Captures
Known limitations:
- No unit tests added for the re-run scenario
- Cannot be fully tested without publishing to npm
- Complex interaction between version redirection and migration execution may have edge cases not covered by CI
Session Info:
- Requested by: Niels Swimberghe ([email protected]) / @Swimburger
- Devin session: https://app.devin.ai/sessions/fcf342a6c09b47c79f2a5e1cabe822ec
🤖 Devin AI Engineer
I'll be helping with this pull request! Here's what you should know:
✅ I will automatically:
- Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
- Look at CI failures and help fix them
Note: I can only respond to comments from users who have write access to this repository.
⚙️ Control Options:
- [ ] Disable automatic comment and CI monitoring
Now no migration runs at all:
node --enable-source-maps ~/fern/packages/cli/cli/dist/prod/cli.cjs upgrade Upgrading from 0.84.1 → 1.1.0
changed 1 package in 855ms
With no version redirect, it still works tho:
FERN_NO_VERSION_REDIRECTION=true node --enable-source-maps ~/fern/packages/cli/cli/dist/prod/cli.cjs upgrade Upgrading from 0.0.0 → 1.1.0
changed 1 package in 175ms ? Some migrations need to be run: ◦ update-1_0_0-defaults The defaults of the API spec settings have changed. This migration will explicitly set the old defaults to maintain backwards compatibility. ◦ ensure-1.0.0-migration-runs Ensures 1.0.0 migration runs for users upgrading from pre-1.0.0 versions due to previous off-by-one error Do you wish to continue? Yes 1.0.0 update-1_0_0-defaults Setting 'title-as-schema-name' to 'true' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'type-dates-as-strings' to 'true' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'object-query-parameters' to 'false' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'idiomatic-request-names' to 'false' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'respect-nullable-schemas' to 'false' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'wrap-references-to-nullable-in-optional' to 'true' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'coerce-optional-schemas-to-nullable' to 'true' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Setting 'inline-path-parameters' to 'false' to maintain backwards compatibility. 1.0.0 update-1_0_0-defaults Updated /Users/niels/fern-demo/auth0-fern-config/fern/generators.yml ┌─ │ ✓ 1.0.0 update-1_0_0-defaults │ ✓ 1.0.5 ensure-1.0.0-migration-runs
Fixed! The issue was that when running from source (node --enable-source-maps ~/fern/packages/cli/cli/dist/prod/cli.cjs), cliContext.environment.packageVersion is "0.0.0", so the early return was trying to run migrations from 0.84.1 → 0.0.0, which yields no migrations.
The solution: Added TARGET_VERSION_ENV_VAR to explicitly pass the target version from the initial upgrade run to the re-run. Now both environment variables are passed:
FERN_PRE_UPGRADE_VERSION: the original version before upgrade (e.g., 0.84.1)FERN_POST_UPGRADE_VERSION: the target version after upgrade (e.g., 1.1.0)
This ensures migrations run from the correct version range regardless of whether the CLI is running from source or from an installed package.
All CI checks pass (71/71). The fix is ready for testing.