chore: add SDK command migration tooling#3723
Merged
tlowrimore-heroku merged 4 commits intoMay 22, 2026
Merged
Conversation
Adds a ts-morph–based codemod that mechanically migrates a single oclif command from raw this.heroku.<verb>(path) calls to @heroku/sdk platform resource methods. The codemod reverse-looks-up each (verb, path) pair against @heroku/types/3.sdk/routes (the SDK's generated route metadata), so the mapping table stays in sync with the SDK without hand curation. Cases the codemod cannot safely transform are flagged with TODO(sdk-migration) markers and the original call is preserved. Run with --dry-run to preview, then again without to apply in place. Adds ts-morph and tsx as devDependencies.
Adds a project-local Claude skill that orchestrates the SDK migration playbook for a single oclif command: pre-flight checks, source migration via the codemod (chore: previous commit), TODO-marker resolution, type-check, and test rewrite to stub @heroku/sdk directly instead of intercepting HTTP via nock. Adjusts .gitignore so that .claude/skills/ is tracked while the rest of .claude/ (settings.local.json, etc.) remains ignored.
…owing
The codemod now indexes both @heroku/types/3.sdk/routes (Platform) and
@heroku/types/data/routes (Postgres data API). Each route is tagged with
its service so the emitted call uses platform.* or data.* as appropriate,
and the SDK destructure at the top of run() only includes services the
file actually uses (e.g., {data, platform} when a command spans both).
For data routes, the codemod silently drops a sole {hostname: ...}
options arg and strips hostname from {body, hostname} payloads — the SDK
provides the data hostname automatically. Anything else in the options
object is still flagged.
Adds a non-blocking warning when a local variable in run() would shadow
a destructured SDK service name (e.g., a local `const data = ...`
colliding with the `data` service). Migration proceeds; the agent must
rename the local before merging.
Updates the README and the sdk-command-migration skill to document
data-route support and the new shadowing warning.
eablack
approved these changes
May 22, 2026
Contributor
eablack
left a comment
There was a problem hiding this comment.
yes, more of these please! ![]()
5e710b2
into
feat/heroku-sdk-integration
4 of 17 checks passed
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.
Summary
scripts/codemods/sdk-migration/, a ts-morph–based codemod that mechanically migrates a single oclif command from rawthis.heroku.<verb>(path)calls to@heroku/sdkresource methods..claude/skills/sdk-command-migration/, a project-local skill that orchestrates the full migration playbook (pre-flight, codemod, TODO resolution, type-check, test rewrite, verify)..gitignoreexception so.claude/skills/is tracked while other.claude/contents (settings.local.json, etc.) remain ignored.The codemod reverse-looks-up each
(verb, path)pair against@heroku/types/3.sdk/routes(the SDK's generated route metadata), so the mapping table stays in sync with the SDK without hand curation. Cases the codemod cannot safely transform (path not statically extractable, no SDK route, body shape ambiguity, etc.) are flagged with// TODO(sdk-migration): ...markers; the original call is preserved for manual resolution.Test plan
npx tsx scripts/codemods/sdk-migration/migrate-command.ts --dry-run src/commands/apps/join.tsand verify the diff replaces boththis.heroku.*calls withplatform.*equivalents, drops{body:}destructure, unwraps the http-call options shape, and preserves source formatting (single quotes, no semicolons, two-space indent).src/commands/apps/lock.tsand verify the codemod flags the ambiguous PATCH/teams/apps/{id}case with a TODO marker and exits non-zero.apps/join): codemod → resolve flagged calls → tsc → run + rewrite tests → verify..claude/settings.local.jsonremains gitignored after the.gitignorechange (git check-ignore .claude/settings.local.jsonreturns 0).