feat(migrate): Add migrate command and JS v10 -> v11 migration - #1499
feat(migrate): Add migrate command and JS v10 -> v11 migration#1499msonnb wants to merge 2 commits into
migrate command and JS v10 -> v11 migration#1499Conversation
Adds `sentry migrate`, which upgrades a project across a Sentry SDK major version, plus the framework migrations are written against. No migration is registered yet, so the command currently refuses every project and says what it would need to find. A migration is a named set of tasks. Each task decides for itself whether it applies, by parsing the project and looking for the thing it knows how to change, and mutates an in-memory workspace through the injected `TaskApi` rather than touching the filesystem. That makes `--dry-run` and a real run the same code path, makes every task testable as "files in, files out", and means a task that throws cannot leave a half-migrated tree on disk. Which migration runs is detected, not assumed. This CLI is one binary for every language Sentry ships an SDK for, so `migrate` asks every registered migration whether it recognises the project. When none does it says what each one looks for, rather than leaving a dead end. Edits are byte ranges rather than a mutable AST, so only touched bytes change and a migrated 400-line config reads as the four lines it altered. `@babel/parser` does the parsing: none of this needs type information, and it bundles to 0.29 MB against the TypeScript compiler API's 3.40 MB. Rewriting source in place needs an undo, so the command refuses to run outside a git repository or with a dirty tree unless `--dry-run` or `--allow-dirty` is passed. Dependency manifests are edited but never installed, so `git checkout` is a complete undo and no lockfile churn buries the diff. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Registers the first migration: `@sentry/*` 10.x to 11.x. It applies every breaking change that can be made mechanically, annotates the call sites that need a human, and writes SENTRY-JAVASCRIPT-V11-MIGRATION.md describing what is left. That file is the handoff to a coding agent, which then runs last and only over work the codemod has already proven it cannot do. Tasks come in three kinds. Most rewrite code: dependency moves, import redirects, removed `Sentry.init()` options, the `sourceMapsUploadOptions` hoist, `sendDefaultPii` to `dataCollection`. Detector tasks find a call site exactly and refuse to fix it, because the right replacement depends on what the code means: splitting a `beforeSendTransaction` needs to know whether the callback was dropping events or scrubbing them. Check tasks match text for changes that live outside anything this migration parses, such as a Wrangler compatibility flag or a Lambda layer ARN. No task consults a catalog to decide whether it is relevant. A task that finds nothing emits nothing, which is the answer a relevance check would have given anyway, reached by reading the project rather than by guessing a framework from a dependency name. The minimum-version checks read the range the manifest declares and stay quiet when it already clears the floor, so a project on Next.js 15 is not told to upgrade Next.js. The report carries only what was found in this project and links the full guide for the rest. Every task names its own guide section, so nothing has to be kept in step with a document in another repository. Refuses a project below v10: skipping a major would rewrite v9-era code against v11 expectations and exit 0, which reads as success. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This looks great for specialized migrations. One thing I’d suggest adding is a generic fallback for upgrades without a dedicated migration: detect the SDK/version, read the relevant changelog or migration guide, and surface the important breaking changes for an agent to act on. Agents should still be able to pick this stuff up when we haven’t built a bespoke codemod, especially changes that could surprise users. |
BYK
left a comment
There was a problem hiding this comment.
Preemptively blocking.
I like the idea but I don't like the specific implementation:
CLI cannot be a dumping ground for all SDKs all migrations. All it can have can be a harness, or a run-time etc. The actual logic should live in the respective SDK's repo and should be dynamically imported as we also cannot afford shipping all this code at all times.
Moreover, I think this should use the same smart backend with sentry init. I think @betegon would have better ideas how to achieve that.
sentry migrate— upgrade a project across a Sentry SDK majorUpgrading across an SDK major currently means reading the migration guide and finding every renamed option, moved import and removed export by hand. This adds a command that does the mechanical part and hands you a list of what's left.
TODO.*_MIGRATION.mdlisting what's left, with afile:lineper item. Hand that file to a coding agent and it only works on what the codemod already proved it can't do.git checkoutis the undo.--allow-dirtyoverrides.package.jsonbut installs nothing, so no lockfile churn buries the diff. Safe to re-run.The engine is generic and the JS v11 knowledge is a plugin under
migrations/sentry-javascript-v11/. A migration is a list of small tasks, each of which decides for itself whether it applies by looking for the thing it knows how to change. Nothing consults a catalog of what's relevant. A task that finds nothing writes nothing, one failing task can't take down the run, and--only/--skipaddress any of them by id.