Skip to content

Require explicit Project binding for Project-scoped CLI commands#51

Merged
luanvdw merged 5 commits into
mainfrom
feat/explicit-project-context-resolution
May 29, 2026
Merged

Require explicit Project binding for Project-scoped CLI commands#51
luanvdw merged 5 commits into
mainfrom
feat/explicit-project-context-resolution

Conversation

@luanvdw
Copy link
Copy Markdown
Member

@luanvdw luanvdw commented May 29, 2026

Summary

  • Require Project-scoped CLI commands to resolve Project scope only from explicit or durable bindings.
  • Change project show to inspect the directory binding and return unbound success with suggestions/candidates instead of selecting by package name.
  • Keep deploy setup explicit; app, domain, and project env commands now fail with PROJECT_SETUP_REQUIRED when unbound.

Review

  • Ran local thermonuclear review against origin/main...HEAD.
  • Fixed strict resolver duplication/type drift.
  • Fixed domain commands still entering deploy interactive setup.

Validation

  • corepack pnpm --filter @prisma/cli build
  • corepack pnpm --filter @prisma/cli test
  • git diff --check origin/main...HEAD
  • rg -n "PROJECT_UNRESOLVED|remembered-local|projectSource: \"package-name\"|source: package-name|resolved for this directory|re-bootstrap" packages/cli/src packages/cli/tests docs/product

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

Summary by CodeRabbit

Release Notes

  • New Features

    • Added explicit "unbound" project state; project show now clearly indicates when a directory lacks a project link, with suggested recovery options.
  • Bug Fixes

    • Improved project resolution: project-scoped commands now require explicit binding or durable state, eliminating unreliable package-name inference.
    • Enhanced error messages with clearer recovery guidance.
  • Documentation

    • Updated CLI style guide, command specifications, error conventions, and resource model documentation to reflect project binding behavior refinements.

Walkthrough

This PR refactors the Prisma CLI's project resolution and binding model. It removes implicit project selection via package-name or remembered-local context, replacing it with an explicit binding requirement or unbound success state. The error code PROJECT_UNRESOLVED is removed, and PROJECT_SETUP_REQUIRED replaces it to provide actionable guidance. Controllers now pass commandName through the resolution chain instead of using interactive selection, and the type model distinguishes between bound and unbound project results with setup suggestions.

Changes

Project Resolution and Binding Semantics

Layer / File(s) Summary
Documentation and Contract Definitions
docs/product/command-spec.md, docs/product/error-conventions.md, docs/product/output-conventions.md, docs/product/resource-model.md, docs/product/cli-style-guide.md
Command spec, error conventions, and resource model are rewritten to formalize the new resolution semantics: no implicit selection via package/directory name, unbound success with setup suggestions, and removal of PROJECT_UNRESOLVED error code.
Type Model for Bound and Unbound Results
packages/cli/src/types/project.ts
ProjectShowResult becomes a union of BoundProjectShowResult and UnboundProjectShowResult; ProjectSource removes remembered-local and gains created/prompt; new ProjectSetupSuggestion type carries suggested names and recovery commands.
Core Project Resolution Logic
packages/cli/src/lib/project/resolution.ts
Introduces resolveBoundProjectTarget that tries explicit project, environment variable, local pin validation, and durable mapping in order. New exports: buildProjectSetupSuggestion, projectSetupRequiredError, localStateStaleError. resolveProjectTarget throws setup-required errors on failure; inspectProjectBinding returns unbound results with suggestions.
Project Show Rendering and Command Metadata
packages/cli/src/presenters/project.ts, packages/cli/src/shell/command-meta.ts
renderProjectShow supports unbound state display (project: null) with suggested package name, match candidates, and recovery commands. formatProjectSource updated for created, prompt, unbound sources; command descriptor updated to reflect "directory's Project binding".
App-Env Command Integration
packages/cli/src/controllers/app-env.ts
runEnvAdd, runEnvUpdate, runEnvList, and runEnvRemove pass commandName to requireClientAndProject, removing interactive selection. Helper signature extended to forward commandName to resolveProjectTarget.
App Command Integration
packages/cli/src/controllers/app.ts
App commands (list-deploys, show, open, logs, promote, rollback, remove) and domain subcommands now pass commandName to their resolution helpers. Helper functions (requireProviderAndProjectContext, resolveProjectContext) accept and forward commandName/envProjectId, removing prior remember: true behavior and local-pin handling in domain logic.
Project Command Integration
packages/cli/src/controllers/project.ts
project show, git connect, and git disconnect refactored to use inspectProjectBinding and new required-project resolvers that pass explicit commandName. Local toProjectSummary helper removed in favor of imported version.
Test Suite Validation
packages/cli/tests/app-controller.test.ts, packages/cli/tests/app-env.test.ts, packages/cli/tests/app-env-vars.test.ts, packages/cli/tests/project-controller.test.ts, packages/cli/tests/project.test.ts
Tests prepopulate local pins and validate new semantics: successful unbound responses (project: null, resolution.projectSource: "unbound"), PROJECT_SETUP_REQUIRED rejection when binding is missing, and recovery command suggestions in errors. Removes expectations for PROJECT_UNRESOLVED and interactive selection prompts.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main objective: requiring explicit Project binding for Project-scoped CLI commands, which directly aligns with the primary changes across documentation and implementation files.
Description check ✅ Passed The PR description clearly relates to the changeset by explaining the core objectives (explicit Project binding, project show behavior changes, setup requirement failures) and includes validation steps demonstrating comprehensive testing.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/explicit-project-context-resolution
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/explicit-project-context-resolution

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/cli/tests/app-env.test.ts (1)

893-906: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Missing local pin setup will cause test failure.

The test expects a validation error ("requires --role or --branch"), but without calling await writeLocalPin(cwd); before line 898, the command will fail during project resolution with PROJECT_SETUP_REQUIRED instead of reaching the validation logic.

All similar validation tests in this file (lines 445, 464, 637) correctly set up the local pin before creating the test context.

🐛 Add missing local pin setup
   const cwd = await createTempCwd();
+  await writeLocalPin(cwd);
   const { context } = await createTestCommandContext({ cwd });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/tests/app-env.test.ts` around lines 893 - 906, The test is
missing the local pin setup so project resolution fails before validation; call
await writeLocalPin(cwd) after obtaining cwd from createTempCwd() and before
creating the test context (i.e., before await createTestCommandContext({ cwd }))
in the "rejects when --role is not provided (fail-fast on writes)" test so
controllers.runEnvRemove reaches its validation logic (use the existing
writeLocalPin helper used in other tests).
packages/cli/src/controllers/app.ts (1)

2224-2245: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing envProjectId in options type definition.

The resolveProjectContext function accesses options?.envProjectId at line 2242, but the options type (lines 2228-2231) does not declare this property. While TypeScript may not error on accessing an undeclared property, callers like requireProviderAndProjectContext pass envProjectId, expecting it to flow through to resolveProjectTarget.

🐛 Proposed fix
 async function resolveProjectContext(
   context: CommandContext,
   client: ManagementApiClient,
   explicitProject: string | undefined,
   options?: {
     branch?: ResolvedDeployBranch;
     commandName?: string;
+    envProjectId?: string;
   },
 ): Promise<ResolvedAppProjectContext> {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/controllers/app.ts` around lines 2224 - 2245, The options
parameter of resolveProjectContext is missing the envProjectId property, so add
envProjectId?: string (or the appropriate type) to the options type in the
resolveProjectContext signature so that options?.envProjectId is declared and
flows through to resolveProjectTarget; update the function signature near
resolveProjectContext and ensure callers like requireProviderAndProjectContext
that pass envProjectId continue to compile.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/cli/src/controllers/app.ts`:
- Around line 2224-2245: The options parameter of resolveProjectContext is
missing the envProjectId property, so add envProjectId?: string (or the
appropriate type) to the options type in the resolveProjectContext signature so
that options?.envProjectId is declared and flows through to
resolveProjectTarget; update the function signature near resolveProjectContext
and ensure callers like requireProviderAndProjectContext that pass envProjectId
continue to compile.

In `@packages/cli/tests/app-env.test.ts`:
- Around line 893-906: The test is missing the local pin setup so project
resolution fails before validation; call await writeLocalPin(cwd) after
obtaining cwd from createTempCwd() and before creating the test context (i.e.,
before await createTestCommandContext({ cwd })) in the "rejects when --role is
not provided (fail-fast on writes)" test so controllers.runEnvRemove reaches its
validation logic (use the existing writeLocalPin helper used in other tests).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9876881f-4638-4352-a793-5884d86612a0

📥 Commits

Reviewing files that changed from the base of the PR and between 6865caa and dd0c66a.

📒 Files selected for processing (17)
  • docs/product/cli-style-guide.md
  • docs/product/command-spec.md
  • docs/product/error-conventions.md
  • docs/product/output-conventions.md
  • docs/product/resource-model.md
  • packages/cli/src/controllers/app-env.ts
  • packages/cli/src/controllers/app.ts
  • packages/cli/src/controllers/project.ts
  • packages/cli/src/lib/project/resolution.ts
  • packages/cli/src/presenters/project.ts
  • packages/cli/src/shell/command-meta.ts
  • packages/cli/src/types/project.ts
  • packages/cli/tests/app-controller.test.ts
  • packages/cli/tests/app-env-vars.test.ts
  • packages/cli/tests/app-env.test.ts
  • packages/cli/tests/project-controller.test.ts
  • packages/cli/tests/project.test.ts

@luanvdw luanvdw merged commit 5daaa40 into main May 29, 2026
5 checks passed
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