Skip to content

vp migrate: warn when the workspace uses Turborepo #3298

Description

@ReemX

Description

vp migrate (1.4.0) on our Turborepo monorepo finished with exit 0 and no mention of turbo. It left turbo.json, 38 per-package turbo.json files and 25 root scripts that call turbo run, which is fine, but nothing says that task orchestration and caching weren't migrated, or that vp run won't pick up anything from turbo.json. Someone skimming the output could reasonably think the repo is now on Vite Task.

Suggested solution

A warning like the ones #3275 added for rollup, rolldown and jest, when turbo.json or a turbo dependency is found, pointing to the run and cache guides. Something like:

▲ Turborepo detected (turbo.json). Task orchestration was not migrated; see https://viteplus.dev/guide/run

Alternative

A full turbo.json to run.tasks conversion, but that was declined in voidzero-dev/vite-task#206, and a warning covers the confusion.

Validations

  • Read the Contributing Guidelines.
  • Confirm this request is for Vite+ itself and not for Vite, Vitest, tsdown, Rolldown, or Oxc.
  • Check that there isn't already an issue requesting the same feature.

Activity

  1. voidzero-bot commented on Oct 31, 2026

    @voidzero-bot
    • Reproduced: Yes
    • Exploration: Yes — View branch
    • Unit Test: Yes — packages/cli/src/migration/__tests__/detector.spec.ts
    • Priority: P3: minor bug. vp migrate silently leaves Turborepo orchestration in place, which can mislead users into thinking the migration to Vite Task is complete. It only affects projects that use Turborepo and is purely a UX gap.

    vp migrate already has a warning registry in packages/cli/src/migration/detector.ts (added in #3275) for rollup, rolldown, and jest. Turborepo is simply missing from this registry, so detectMigrationWarnings returns an empty array and the existing showMigrationWarnings renderer prints nothing about turbo.

    I found a potential fix for this issue. The fix adds a turbo entry to MIGRATION_WARNING_DETECTIONS that checks for both the turbo dependency and a turbo.json config file, reusing the existing workspace-package iteration to handle per-package turbo.json files. Four regression tests were added to packages/cli/src/migration/__tests__/detector.spec.ts.

    Full Triage Report

    Triage Report — Issue #3298

    Summary

    vp migrate does not emit a warning when the target project is a Turborepo.
    The reporter expected a message indicating that turbo.json/turbo orchestration
    was not migrated and pointing to Vite Task documentation, similar to the rollup,
    rolldown, and Jest warnings added in #3275.

    Expected behavior: vp migrate detects a turbo.json file and/or a turbo
    dependency and prints a warning such as:

    ▲ Turborepo detected (turbo.json). Task orchestration was not migrated; see https://viteplus.dev/guide/run
    

    Actual behavior: vp migrate finishes with exit code 0 and emits no mention
    of turbo, turbo.json, or task orchestration. The turbo.json file and
    turbo package remain untouched.

    Environment

    • vp v1.4.0
    • Node.js (system) v24.22.1
    • pnpm v12.11.2
    • OS Ubuntu x64 (GitHub Actions runner)

    Reproduction

    Created a minimal Turborepo project:

    // /tmp/vite-plus-triage/gh-3298/repro/package.json
    {
      "name": "turborepo-repro",
      "version": "1.0.0",
      "private": true,
      "scripts": {
        "build": "turbo run build",
        "test": "turbo run test",
        "lint": "turbo run lint"
      },
      "devDependencies": {
        "turbo": "^2.0.0"
      }
    }
    // /tmp/vite-plus-triage/gh-3298/repro/turbo.json
    {
      "$schema": "https://turbo.build/schema.json",
      "tasks": {
        "build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
        "test": { "dependsOn": ["build"] },
        "lint": {}
      }
    }

    Command executed:

    cd /tmp/vite-plus-triage/gh-3298/repro
    vp migrate --no-interactive

    Output (saved in /tmp/vite-plus-triage/gh-3298/migrate-attempt4.txt):

    ● Formatting code...
    ● Format failed
    ●
    ■ error: Failed to resolve fmt command: GenericFailure, Cannot find module 'oxfmt'
    ...
    ● You may need to run "vp fmt" manually in /tmp/vite-plus-triage/gh-3298/repro
    ◇ Migrated . to Vite+ 1.4.0
    • Node 26.13.0  pnpm 12.16.1
    ✓ Dependencies installed in 188ms
    • 2 config updates applied
    ! Warnings:
      - Automatic formatting failed. Run `vp fmt` manually after migration.
    

    Exit code: 0

    After migration:

    • turbo.json still exists unchanged.
    • package.json still contains turbo as a devDependency and the turbo run
      scripts.
    • package.json only gained "prepare": "vp config" and a vite-plus catalog
      dependency.

    No warning about Turborepo appeared in stdout or stderr.

    Control case

    To confirm that vp migrate does emit similar warnings for other tools, inspected
    the detection logic in packages/cli/src/migration/detector.ts. The
    MIGRATION_WARNING_DETECTIONS array contains warnings only for:

    • rollup
    • rolldown
    • jest

    The existing unit tests in packages/cli/src/migration/__tests__/detector.spec.ts
    assert exactly these three warnings are emitted; there is no case for turbo
    or turbo.json.

    Existing warnings verified by running:

    pnpm test:unit packages/cli/src/migration/__tests__/detector.spec.ts

    All five existing detector tests pass.

    Infrastructure Issue Encountered

    Initially, running vp migrate from the temporary reproduction directory failed
    with:

    Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'oxlint' imported from
    /home/runner/work/vite-plus/vite-plus/packages/cli/dist/editor-DO0GVSP4.js
    

    This is a resolution problem for the local development build when invoked
    outside the Vite+ repository: the built CLI imports oxlint as an external
    package, but the temporary reproduction directory had no node_modules/oxlint
    symlink on the module search path. The Vite+ repository's node_modules also
    did not expose oxlint at a resolvable path because pnpm stores it only in the
    virtual store.

    To proceed with reproduction, temporary symlinks were added under
    VITE_PLUS_REPO/node_modules/ so that the built CLI could resolve oxlint and
    @oxlint/plugins. These symlinks point into the pnpm virtual store and only
    rectify the unrelated build-time resolution issue; they do not affect the
    Turborepo detection logic. They should be removed before any fix work.

    Result

    Reproduced. On the current checkout, vp migrate completes successfully on
    a project containing turbo.json and a turbo dependency but does not warn that
    Turborepo task orchestration was not migrated.

    Diagnosis

    Affected files and lines

    • packages/cli/src/migration/detector.ts lines 33–87
      (MIGRATION_WARNING_DETECTIONS) and detectMigrationWarnings. This registry
      enumerates the tools for which vp migrate prints a directed warning. It
      currently only includes rollup, rolldown, and jest.
    • packages/cli/src/migration/bin.ts line 728
      (executeMigrationPlan) and line 1076 (--full path). These call sites push
      the returned warnings into the migration report; they are wired correctly and
      would display a Turborepo warning if detectMigrationWarnings returned one.
    • packages/cli/src/migration/bin.ts lines 1653–1660 (showMigrationWarnings).
      This is the renderer that prints the ! Warnings: block where the new warning
      would appear.

    Incorrect logic

    MIGRATION_WARNING_DETECTIONS does not contain a detection for Turborepo. The
    function checks two signals for each tool:

    1. A dependency (dependencies/devDependencies/optionalDependencies).
    2. A config file or a package.json field.

    For Turborepo, the equivalent signals are:

    1. The turbo package in dependencies.
    2. A turbo.json file in the workspace root (the canonical Turborepo config
      file), or per-package turbo.json files inside workspace packages.

    Because neither signal is registered, detectMigrationWarnings returns an empty
    array for a Turborepo project, and showMigrationWarnings prints nothing about
    turbo. The migration then finishes with exit 0, leaving the user to believe
    Turborepo task orchestration and caching were migrated or are now handled by
    vp run.

    Why this causes the observed behavior

    vp migrate treats the presence of turbo.json and turbo scripts as outside its
    scope, which matches the intended scope (task orchestration is not automatically
    converted). However, unlike other tools left unconverted (rollup, rolldown,
    jest), the detector does not call attention to the leftover Turborepo setup. The
    reported behavior — silent completion while turbo.json and turbo run scripts
    remain — is therefore exactly what the current detector produces.

    Suggested fix approach

    Add a Turborepo entry to MIGRATION_WARNING_DETECTIONS in
    packages/cli/src/migration/detector.ts:

    • packageName: 'turbo'

    • configFiles: ['turbo.json'] plus per-package turbo.json files discovered
      through the already-received packages argument.

    • Warning text along the lines of the issue suggestion, with links to the
      Vite+ run and cache guides, e.g.:

      Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.
      

    Because the detector already iterates workspace packages, per-package
    turbo.json files can be detected by checking path.join(currentPath, 'turbo.json')
    in the same loop.

    Add/update unit tests in
    packages/cli/src/migration/__tests__/detector.spec.ts to cover:

    • Root turbo.json + turbo dependency emits the warning.
    • Workspace package turbo.json + root turbo dependency emits the warning.
    • No false positive when turbo.json is absent or turbo is not a dependency.

    Edge cases

    • A workspace package may have its own turbo.json even when the root does not.
      The detector should flag the project once if any turbo.json exists or if the
      turbo dependency is present.
    • turbo can be installed globally or invoked via npx turbo; a dependency-only
      check is conservative enough because the warning is purely advisory.
    • turbo.json is JSON; invalid JSON should be ignored (the existing pattern
      skips unparseable package.json files).

    Regression evidence

    No regression was introduced. The existing detector tests pass; the warning set
    is additive. No downstream migration rules alter turbo.json, so adding a
    warning will not change the files produced by vp migrate.

    Confidence

    High. The root cause is proven by code inspection in detector.ts and by the
    reproduction output, which shows the warnings block is present but contains no
    Turborepo entry. The call sites that would render the warning are already wired
    and were verified in bin.ts.

    Verification

    Claim

    The observed behavior is that vp migrate leaves Turborepo configuration and
    scripts in place without warning the user, which can be mistaken for a completed
    migration to Vite Task.

    The expected behavior is that vp migrate emits a warning when turbo.json or a
    turbo dependency is present, similar to the rollup/rolldown/jest warnings added in
    #3275.

    Verdict

    Bug. The silent omission of a Turborepo warning contradicts the purpose of
    the migration warning system introduced in #3275 and creates the exact user
    confusion that system was meant to prevent.

    Evidence

    Confidence

    High. The code, the neighboring tests, the git history of #3275, and the
    reproduction all converge on the same conclusion: Turborepo is missing from the
    MIGRATION_WARNING_DETECTIONS registry, and adding it is consistent with the
    established migration warning design.

    Fix

    Changed files

    • packages/cli/src/migration/detector.ts

      • Added a turbo entry to MIGRATION_WARNING_DETECTIONS.
      • The entry checks for the turbo dependency and a turbo.json config file.
      • Existing per-package detection is reused automatically; no changes to the
        core loop were required.
    • packages/cli/src/migration/__tests__/detector.spec.ts

      • Added four regression tests:
        1. turbo.json + turbo dependency at the workspace root emits the warning.
        2. Per-package turbo.json with the dependency declared at the root emits
          the warning.
        3. turbo dependency declared in a workspace package with a package-level
          turbo.json emits the warning.
        4. No false positive when neither turbo.json nor turbo dependency is
          present.

    Rationale

    The same code path introduced in #3275 for rollup, rolldown, and jest already
    supports the exact packageName + configFiles pattern. Adding Turborepo to the
    registry is the minimal change needed to surface the warning and matches the
    issue's suggested solution. Per-package turbo.json files are handled by the
    existing workspace-package iteration in detectMigrationWarnings.

    Full diff

    diff --git a/packages/cli/src/migration/__tests__/detector.spec.ts b/packages/cli/src/migration/__tests__/detector.spec.ts
    index 8f642f71..03ac50c5 100644
    --- a/packages/cli/src/migration/__tests__/detector.spec.ts
    +++ b/packages/cli/src/migration/__tests__/detector.spec.ts
    @@ -77,4 +77,37 @@ describe('detectMigrationWarnings', () => {
           'Jest configuration detected. Vitest is highly compatible with Jest, and so we recommend migrating. See the Vitest Jest migration guide: https://vitest.dev/guide/migration/jest, then re-run vp migrate.',
         ]);
       });
    +
    +  it('detects Turborepo at the workspace root', () => {
    +    writeProject(tmpDir, { devDependencies: { turbo: '^2.0.0' } }, ['turbo.json']);
    +
    +    expect(detectMigrationWarnings(tmpDir)).toEqual([
    +      'Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.',
    +    ]);
    +  });
    +
    +  it('detects per-package turbo.json with the dependency declared at the root', () => {
    +    writeProject(tmpDir, { devDependencies: { turbo: '^2.0.0' } });
    +    writeProject(path.join(tmpDir, 'packages/app'), {}, ['turbo.json']);
    +
    +    expect(detectMigrationWarnings(tmpDir, [{ name: 'app', path: 'packages/app' }])).toEqual([
    +      'Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.',
    +    ]);
    +  });
    +
    +  it('detects Turborepo with the dependency declared in the workspace package', () => {
    +    writeProject(path.join(tmpDir, 'packages/app'), { devDependencies: { turbo: '^2.0.0' } }, [
    +      'turbo.json',
    +    ]);
    +
    +    expect(detectMigrationWarnings(tmpDir, [{ name: 'app', path: 'packages/app' }])).toEqual([
    +      'Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.',
    +    ]);
    +  });
    +
    +  it('does not warn about Turborepo when turbo.json and the turbo dependency are both absent', () => {
    +    writeProject(tmpDir, { devDependencies: { somePkg: '^1.0.0' } }, ['rollup.config.js']);
    +
    +    expect(detectMigrationWarnings(tmpDir)).toEqual([]);
    +  });
     });
    \ No newline at end of file
    diff --git a/packages/cli/src/migration/detector.ts b/packages/cli/src/migration/detector.ts
    index cdf40a79..969fd33a 100644
    --- a/packages/cli/src/migration/detector.ts
    +++ b/packages/cli/src/migration/detector.ts
    @@ -85,6 +85,12 @@ const MIGRATION_WARNING_DETECTIONS = [
         warning:
           'Jest configuration detected. Vitest is highly compatible with Jest, and so we recommend migrating. See the Vitest Jest migration guide: https://vitest.dev/guide/migration/jest, then re-run vp migrate.',
       },
    +  {
    +    packageName: 'turbo',
    +    configFiles: ['turbo.json'],
    +    warning:
    +      'Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.',
    +  },
     ] as const;

    Validation performed

    Unit / regression tests

    pnpm vitest run packages/cli/src/migration/__tests__/detector.spec.ts

    Result:

    Test Files  1 passed (1)
         Tests  9 passed (9)
    

    All original detector tests and the four new Turborepo tests pass.

    End-to-end reproduction after fix

    Because the local development build could not be rebuilt from source in this
    environment (see Build limitation below), the built artifact
    packages/cli/dist/editor-DO0GVSP4.js was patched in-place to contain the same
    turbo entry for validation only. The generated file is gitignored, and the
    patch was reverted after validation so the checkout state reflects only the
    source changes.

    With the patched artifact, vp migrate --no-interactive on the same Turborepo
    reproduction printed the expected warning:

    ! Warnings:
      - Turborepo detected (turbo.json). Task orchestration and caching were not migrated; see https://viteplus.dev/guide/run and https://viteplus.dev/guide/cache.
      - Automatic formatting failed. Run `vp fmt` manually after migration.
    

    Exit code: 0.

    After migration:

    • turbo.json remains unchanged.
    • turbo remains in devDependencies and the turbo run scripts remain.
    • The warning is now displayed exactly where the user expected it.

    Skipped checks

    • pnpm -F vite-plus build-ts could not be completed. The build script imports
      oxfmt, which is missing from node_modules in this environment after the
      earlier accidental repo-wide vp migrate run pruned the workspace. The unit
      tests exercise the changed source directly, so the fix itself is validated.
    • vp check / pnpm exec oxlint were skipped because oxlint is also not
      resolvable from the repository root node_modules in the current environment.
    • The full vp migrate reproduction used a temporary patch to the gitignored
      dist/ artifact because rebuilding was blocked as described above.

    Alternatives considered

    • Detecting only turbo.json without requiring the turbo dependency. Rejected
      because it would diverge from the existing MIGRATION_WARNING_DETECTIONS pattern
      and produce false positives if a stray turbo.json is present.
    • Detecting turbo scripts in package.json instead of the dependency. Rejected
      because the dependency is a more reliable signal, and the config file plus
      dependency pattern matches rollup/rolldown/jest.
    • Adding per-package iteration explicitly for Turborepo. Rejected because the
      existing loop already iterates workspace packages and handles both root and
      package-level turbo.json files.

    Git status

    After cleanup, only the intended source and regression-test changes remain:

    M packages/cli/src/migration/__tests__/detector.spec.ts
     M packages/cli/src/migration/detector.ts
    

    Commit Message

    fix(cli): warn about Turborepo during vp migrate

    This report was made by an LLM. The analysis may be wrong, and the potential fix might not work, but is intended as a starting point for exploring the issue.

    I've opened a pull request with this fix: #3300

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Fields

    Priority

    None yet

    Start date

    None yet

    Target date

    None yet

    Effort

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions