Skip to content

Run prisma deploy through alchemy/Alchemist in the prisma process - #405

Draft
wmadden-electric wants to merge 5 commits into
claude/alchemy-api-evaluation-5f1d17from
claude/alchemy-deploy-in-process
Draft

wmadden-electric wants to merge 5 commits into
claude/alchemy-api-evaluation-5f1d17from
claude/alchemy-deploy-in-process

Conversation

@wmadden-electric

@wmadden-electric wmadden-electric commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor
// packages/0-framework/3-tooling/cli/src/converge-in-process.ts (shape)
const outcome = await convergeInProcess({ operation: 'deploy', stack, stage, cwd, env, signal, onEvent });
// → { kind: 'applied', output } | { kind: 'interrupted' } | { kind: 'failed', reasons } | { kind: 'refused', … }

prisma deploy now runs Alchemy inside the prisma process through alchemy/Alchemist (plan, then apply). It no longer writes .prisma-composer/alchemy.run.ts or spawns the Alchemy CLI. destroy and dev are unchanged; dev moves in the next pull request.

Stacked on #404. Draft: do not merge before #404.

What changes for users

  • Deploy needs PRISMA_SERVICE_TOKEN in the environment. A prisma login session alone now fails early with DEPLOY.SERVICE_TOKEN_REQUIRED. @prisma/cli-engine gives a command no way to read the signed-in token; it only ever wrote it into a child's environment. CI and the e2e workflow already set the token. The code is marked temporary until the engine offers an in-process credentials need.
  • A failed deploy exits 2 with DEPLOY.ENGINE_FAILED, not the Alchemy child's exit status. Ctrl-C prints "The deploy was interrupted. Deploy again to finish." and exits 130 with the engine's CLI.ABORTED; the state-store lease is released, so the next deploy does not wait.
  • Each resource shows as a step under "plan and apply", in both human and --json output.

How it works

  1. The deploy operation checks the service token before preflight and before any container is created. The token and workspace always come from the same credential.
  2. It loads lower and convergeInProcess from the app's @prisma/composer install (new entry @prisma/composer/internal/converge), found from the directory of the app's prisma.config.ts, so the app's extensions and Alchemy share one copy of alchemy. If the entry cannot be loaded: DEPS.CONVERGE_UNRESOLVABLE. The host first reads the app's CONVERGE_CONTRACT number (@prisma/composer/internal/converge-contract) and refuses a different one with DEPS.CONVERGE_CONTRACT_MISMATCH. Package versions may differ, because the prisma CLI releases on its own schedule; the number changes only when the data passed between host and app changes.
  3. lower() takes containers and preflight results as values. Only the stack files that destroy and dev still generate read them from the environment, through one helper.
  4. convergeInProcess sets the deploy's environment and working directory for the run, sends Alchemy's own output to stderr, and restores everything on every exit path. A second concurrent converge in the same process is refused (DEPLOY.CONVERGE_RUNNING), even across two installs.
  5. Alchemy's events become engine events. Secrets are redacted from every message.

ADR-0064 records the decision. It supersedes ADR-0007 for deploy and amends ADR-0038, 0043, 0044, 0049 and 0062.

Alternatives considered

  • Keep a child process running a small Composer-owned runner. Rejected: an extra process and IPC with nothing the in-process path lacks.
  • Keep generating alchemy.run.ts and load it with Alchemist.importStack. Rejected: writing code only to import it back is a detour.
  • Alchemy's SigilRenderer for output. Rejected: it would give deploy a second output format and nothing in --json mode.

Manual test

Against real Prisma Cloud with examples/bucket: deploy (27s), Ctrl-C during a second deploy (exit 130), a third deploy straight after (23s, no lease wait), --json output (every line valid JSON), destroy (still the child path).

Known gaps

  • Interactive prisma login deploys, above.
  • Two imports use Alchemy's wildcard export (alchemy/Util/LogRecord, alchemy/Interaction). We will ask Alchemy to expose them from alchemy/Alchemist.

Agent: maat-73

🤖 Generated with Claude Code

wmadden-electric and others added 2 commits October 31, 2026 10:23
prisma deploy and the deploy operation now lower the app and call
Alchemist.plan and Alchemist.apply in process. No alchemy.run.ts is written
and no Alchemy child is spawned. destroy and prisma dev keep the stack file.

- lower() takes containers and preflight payloads as values; extensions read
  their payload as LowerContext.preflight. The env transports stay for the
  stack file.
- The report hook returns the summary as a value.
- Alchemy events become apply-resource steps under deploy.apply; log lines
  become messages.
- Failures are DEPLOY.ENGINE_FAILED with the cause; Ctrl-C is
  DEPLOY.INTERRUPTED and closes the scope, releasing the lease.
- prisma deploy needs PRISMA_SERVICE_TOKEN in the environment
  (DEPLOY.SERVICE_TOKEN_REQUIRED): cli-engine 0.9.0 has no public way to
  hand a command the active access token.
- convergeInProcess is the function slice 3 (dev) reuses.
- scratch-stack test harness rebuilt on alchemy/Alchemist.
- ADR-0064 supersedes ADR-0007 for deploy; amends ADR-0038/0043/0044.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…state

- Load lower and convergeInProcess from the app's own @prisma/composer
  (new @prisma/composer/internal/converge entry), resolved from the app
  directory; DEPS.ENGINE_UNRESOLVABLE when it cannot be loaded.
- lower() takes containers and preflight payloads as required values;
  transportedLowerInputs() reads both transports for the generated stack
  files. Core invariant 4 pins process.env to that helper.
- convergeInProcess refuses a second concurrent run
  (DEPLOY.CONVERGE_RUNNING) and a worker thread that would need chdir
  (DEPLOY.WORKER_THREAD); every process state change is inside the try;
  Alchemy interaction output goes to stderr; it takes the operation and
  returns typed failure reasons.
- The console redirect moved to the prisma deploy command.
- Messages, the engine failure and stack-building errors are redacted.
- The service-token check moved into the operation, before preflight and
  ensure. The command passes a token only for an environment credential,
  with that credential's workspace, and PRISMA_WORKSPACE_ID is removed
  when it names none. credentials carries the token; convergeEnv is gone.
- family/converge.ts is now family/dev-converge-child.ts.
- Docs: ADR-0044 registry, ADR-0064, ADR-0043, ADR-0049, ADR-0062,
  build-reporting.md, deploy-cli.md and the deploying guide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@prisma-gizmo

prisma-gizmo Bot commented Oct 31, 2026

Copy link
Copy Markdown

⏸️ Gizmo skipped the automatic review of bfa4539 because this pull request is a draft. It will review automatically once the PR is marked ready for review.

  • Check this box to request a one-time review of the current commit.

@coderabbitai

coderabbitai Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@pkg-pr-new

pkg-pr-new Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@prisma/composer@405
npm i https://pkg.pr.new/@prisma/composer-cli@405
npm i https://pkg.pr.new/@prisma/composer-prisma-cloud@405

commit: 686a1f8

wmadden-electric and others added 2 commits October 31, 2026 11:00
- Rename the app-loaded pair to AppConverge / loadAppConverge and the
  code to DEPS.CONVERGE_UNRESOLVABLE; add "converge" to the glossary.
- loadAppConverge refuses an app @prisma/composer at a version other
  than the host's (DEPS.CONVERGE_VERSION_MISMATCH, naming both), and
  resolves the install from the directory of prisma.config.ts.
- A rejected converge promise is DEPLOY.ENGINE_FAILED.
- The one-converge-per-process flag lives on globalThis under a
  Symbol.for key, so every install shares it.
- withProcessState restores the environment before the directory, and
  the running flag is set inside the try that clears it.
- An interrupted prisma deploy reports DEPLOY.INTERRUPTED as a message
  and ends with the engine abort, so it exits 130.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…on a failed chdir

- @prisma/composer/internal/converge-contract exports CONVERGE_CONTRACT;
  loadAppConverge reads it before loading the converge and refuses a
  different number with DEPS.CONVERGE_CONTRACT_MISMATCH, naming both
  contracts and both versions and saying which side to upgrade. Package
  versions may differ.
- A failed chdir back to a removed directory no longer replaces the
  converge outcome.
- ADR-0064, ADR-0044, the ADR index, deploy-cli.md, the glossary and the
  deploying guide follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…my-deploy-in-process

Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.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.

1 participant