Skip to content

feat(cli): a version id resolves its service in one request - #235

Merged
wmadden-electric merged 2 commits into
mainfrom
feat/deployment-owner-direct-lookup
Aug 25, 2026
Merged

feat(cli): a version id resolves its service in one request#235
wmadden-electric merged 2 commits into
mainfrom
feat/deployment-owner-direct-lookup

Conversation

@wmadden-electric

Copy link
Copy Markdown
Contributor

Purpose of change

Every command that names a version by id — prisma service version show|promote|start|stop|delete <id> — used to search the whole workspace for the service that owns it. Now it asks once:

// before: one request, then a search of unbounded size
const deployment = await sdk.showDeployment({ deploymentId });
const app = await findAppForDeployment(sdk, deploymentId); // scans every project → every service → every version

// after: two requests, always
const deployment = await sdk.showDeployment({ deploymentId });
const app = await sdk.showApp({ appId: deployment.value.serviceId });

Version ids are globally unique, so prisma service version show ver_abc123 needs no service, project, or branch parameter. But the CLI still had to know the owning service — it prints the service name, and the promoted URL is the service's address rather than the version's preview domain. Until now the API's version response carried no owner pointer, so the only way to find it was to look everywhere: list every project, list every service in each project, then check each service's versions for the id. A workspace with 15 projects of 4 services each cost up to 75 requests to answer "who owns this version?".

What's changed

The Management API now returns the owner, and this PR consumes it. GET /v1/deployments/{id} gained a serviceId field (pdp-control-plane#4983), @prisma/compute-sdk@0.42.0 exposes it as DeploymentDetail.serviceId (project-compute#174), and showDeployment in the app provider follows it straight to showApp.

  • The scan is deleted. findAppForDeployment and findServiceAppForDeployment are gone — 76 lines, and with them the file's noAwaitInLoops lint exemption, which existed only for those loops.
  • A missing owner now means one thing. The scan returned null for both "no such service" and "id not found anywhere", which is what SERVICE.VERSION_DETACHED reported. The direct lookup can only see one of those: a 404 from showApp, meaning the service was deleted between the two calls. Any other error propagates instead of being flattened into "detached", so a network failure no longer masquerades as a missing service.
  • Dependencies move together: @prisma/compute-sdk 0.39.0 → 0.42.0, and @prisma/management-api-sdk 1.55.0 → 1.69.0 across cli, prisma, and cli-engine — 1.69.0 is compute-sdk's peer floor and the first release whose types carry the field.

The test kit's version fixtures gained serviceId, which is what makes the new path honest: its fake GET /v1/apps/{appId} answers any id, so without a fixture carrying the real owner id the assertion would pass no matter which id the CLI looked up.

Verified: pnpm typecheck, pnpm --filter @prisma/cli test (934 passed), pnpm --filter @prisma/compute test (11 passed). The e2e suite needs PRISMA_E2E_SERVICE_TOKEN, which this machine does not hold — the pull_request run on this PR is the real check.

Alternatives considered

  • Keep the scan as a fallback when serviceId is absent. Rejected: the field is required in the API contract and the SDK types it non-optional, so the fallback would be unreachable code carrying 76 lines and a lint exemption. An older server is a version-skew problem, and the SDK peer floor is where that is already handled.
  • Report a 404 from showApp as an error rather than a detached version. Rejected: it would turn a routine race (deleting a service while a version command is in flight) into a failure with no actionable message. SERVICE.VERSION_DETACHED already describes exactly that state.
  • Rename the adapter's App/Deployment vocabulary to Service/Version while touching it. Deferred: ADR-012 renames every surface in one coordinated pass, and the deferred ledger records this adapter as the one file where both vocabularies may meet until then.

Closes the ledger entry "GET /v1/deployments/{id} omits the parent appId" in .drive/projects/prisma-cli-v8/deferred.md.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 24 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1f255197-8655-4e7b-b2e9-79054fa57c60

📥 Commits

Reviewing files that changed from the base of the PR and between 5468362 and c5efaf0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • .drive/projects/prisma-cli-v8/deferred.md
  • packages/cli/package.json
  • packages/cli/src/lib/app/app-provider.ts
  • packages/cli/tests/service-testkit.ts
  • packages/cli/tests/service-version-promote.test.ts
  • packages/prisma/package.json

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@wmadden-electric
wmadden-electric force-pushed the feat/deployment-owner-direct-lookup branch from 69c1af0 to df50db4 Compare August 25, 2026 15:13
@pkg-pr-new

pkg-pr-new Bot commented Aug 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@prisma/cli@235
npx https://pkg.pr.new/@prisma/cli-engine@235

commit: c5efaf0

wmadden-electric and others added 2 commits August 25, 2026 17:20
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden-electric
wmadden-electric force-pushed the feat/deployment-owner-direct-lookup branch from df50db4 to c5efaf0 Compare August 25, 2026 15:21
@wmadden-electric
wmadden-electric merged commit bc502d1 into main Aug 25, 2026
14 checks passed
@wmadden-electric
wmadden-electric deleted the feat/deployment-owner-direct-lookup branch August 25, 2026 15:25
wmadden pushed a commit that referenced this pull request Aug 26, 2026
…236)

## Purpose of change

`@prisma/cli-engine` hands the shell a Management API client through
`ctx.api`, and re-exports the SDK's type for it:

```ts
// packages/cli-engine/src/management-api.ts
/** The SDK's typed client, re-exported so consumers never import
 *  @prisma/management-api-sdk directly. */
export type ManagementApiClient = SdkClient;
```

That type belongs to `@prisma/management-api-sdk`, and until now the
engine held that package as an ordinary dependency at an exact version —
as did `packages/cli` and `packages/prisma`, each independently:

```
cli-engine  dependencies: @prisma/management-api-sdk = 1.55.0
cli         dependencies: @prisma/management-api-sdk = 1.55.0
prisma      dependencies: @prisma/management-api-sdk = 1.55.0
```

A package whose public API carries another package's types has a shared
type surface. Held as three private copies, the three pins can disagree
— and when they disagree, the types stop being the same type. Moving
only the shell to a newer SDK produces this, roughly fifteen times over:

```
src/commands/branch/list.ts(80,9): error TS2345:
  Argument of type 'Client<paths@1.55.0>' is not assignable to
  parameter of type 'Client<paths@1.69.0>'
```

So the SDK version could only ever move in all three manifests at once.
One of the three is the engine, and a changed engine needs a new engine
version, and both `@prisma/composer-cli` and `@prisma/orm-toolchain`
peer-pin the engine **exactly** — so an SDK bump, a routine act, cost a
three-repo release sequence every time. That is what blocked #235 from
taking `@prisma/management-api-sdk@1.69.0`, the version
`@prisma/compute-sdk@0.42.0` asks for.

## What's changed

The engine now declares the SDK the way a shared type surface should be
declared:

- **`cli-engine`**: `@prisma/management-api-sdk` moves from
`dependencies` to `peerDependencies` at `^1.55.0` — a range, not a pin,
because the consumer chooses. It stays in `devDependencies` at the
version the workspace supplies so the package still builds and tests
standalone.
- **`cli` and `prisma`** keep it as a real dependency and move to
`1.69.0`. They are the binaries; they install the one copy everyone
binds to. All three packages now resolve
`@prisma+management-api-sdk@1.69.0`, and `pnpm peers check` no longer
reports compute-sdk's unmet peer.
- **Engine `0.2.3` → `0.3.0`**, the pre-1.0 breaking slot: consumers of
the published engine must now supply the SDK themselves.

After this, moving the SDK touches the two app manifests and nothing
else — no engine version, no family republish.

## The transition this starts

The engine must publish before a family can peer it, so both families
still declare `0.2.3` and conformance reports six pin mismatches.
`packages/cli/scripts/conformance.ts` has a place for exactly this, and
its comment prescribes the sequence; both entries are filled in with a
`removeWhen`:

```
0 failing, 6 allowed, 5 subject(s) checked
```

Every one prints in full with its reason, including the two copies of
the engine that resolve in the sandbox install — the expected shape of a
transition rather than a defect. The remaining steps, recorded in the
deferred ledger: engine 0.3.0 publishes → both families republish
peering 0.3.0 → a release PR here pins them and deletes the two
exceptions, restoring the empty list.

Verified: `pnpm typecheck`, `pnpm --filter @prisma/cli test` (958
passed), `pnpm check:conformance` (0 failing), `node
scripts/check-engine-version.mjs`.

## Alternatives considered

- **Relax `@prisma/compute-sdk`'s peer floor back to `^1.44.0`.** This
was my first proposal and it was wrong. That floor is the one peer
dependency in the picture that already works: it correctly reported that
this repo was pinned behind. Widening it would have silenced an accurate
warning and left the actual cause — three private copies of a shared
type — in place.
- **Bump all three manifests to 1.69.0 and take the release chain.**
Fixes today's mismatch and leaves the next one to cost exactly the same.
The same engine bump buys the structural fix instead.
- **A `pnpm` override forcing one SDK version.** Makes the workspace
green while the published engine still declares a version it does not
get, so anyone installing `@prisma/cli-engine` alongside
`@prisma/compute-sdk` reproduces the two-copy break. It hides the
problem precisely where it would be felt.
- **An exact peer (`1.69.0`) rather than a range.** Recreates the
lockstep-bump problem one layer up: every SDK release would force an
engine release again.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants