fern icon indicating copy to clipboard operation
fern copied to clipboard

fix(cli): pass correct previous version to migration runner

Open devin-ai-integration[bot] opened this issue 1 month ago • 3 comments

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_VAR and runs migrations immediately
  • Added fallback to read target version from fern.config.json if TARGET_VERSION_ENV_VAR is 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.version before mutations and pass it as previousVersionBeforeUpgrade
  • Updated rerunFernCliAtVersion call to pass both FERN_PRE_UPGRADE_VERSION and FERN_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:

  1. Early return logic (lines 54-75):

    • Requires previousVersion to be set, but targetVersionForMigration has a fallback
    • Falls back to reading fern.config.json if TARGET_VERSION_ENV_VAR is missing
    • Guards against "0.0.0" target version
    • Question: What happens if previousVersion is set but we can't determine a valid target version? Currently returns without running migrations - is this correct?
  2. Environment variable propagation (lines 157-161):

    • Both FERN_PRE_UPGRADE_VERSION and FERN_POST_UPGRADE_VERSION are passed to re-run
    • Verify: Are there any other code paths that invoke rerunFernCliAtVersion that might need these env vars?
  3. Interaction with local-dev special case (lines 131-136):

    • The existing special case for packageVersion === "0.0.0" directly calls runPostUpgradeSteps
    • Verify: Does the early return logic interfere with this flow? (It shouldn't since env vars aren't set in this path)
  4. Fallback resilience:

    • If TARGET_VERSION_ENV_VAR is missing, falls back to reading fern.config.json
    • Question: Could this mask bugs where the env var should be set but isn't? Is the fallback too permissive?
  5. Version tracking (line 133):

    • Captures previousVersionBeforeUpgrade from projectConfig.version before writing new version
    • Verify: Is this the correct "from" version in all scenarios? What if projectConfig.version is "*"?

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

Swimburger avatar Nov 14 '25 20:11 Swimburger

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.