fix: pass rootDirectory in projectSettings for monorepo deployments - #348
fix: pass rootDirectory in projectSettings for monorepo deployments#348Fetten wants to merge 11 commits into
Conversation
The root-directory input was only passed to @vercel/client's clientOptions but never included in the POST /v13/deployments body as projectSettings. Without this, Vercel's build might fail to detect the correct package manager and break e.g. with pnpm when using the `workspace:*` protocol. This adds `projectSettings.rootDirectory` and `sourceFilesOutsideRootDirectory` to the deployment options when `root-directory` is set.
There was a problem hiding this comment.
Code Review
This pull request introduces the source-files-outside-root-directory configuration option to better support monorepo deployments by including projectSettings in the Vercel API request. The changes span the action metadata, configuration parsing, type definitions, and the API client logic. A review comment identifies an inconsistency in a test helper where the default value for the new setting does not match the production default, which should be corrected to ensure tests accurately reflect the action's behavior.
There was a problem hiding this comment.
No issues found across 9 files
Requires human review: This PR modifies the core deployment request shape sent to the Vercel API by adding projectSettings. Changes to API request payloads in critical paths require human verification.
Architecture diagram
sequenceDiagram
participant Runner as GitHub Runner (Action)
participant Config as getActionConfig()
participant Client as VercelApiClient
participant SDK as @vercel/client
participant VercelAPI as Vercel API (POST /v13/deployments)
participant Builder as Vercel Build Server
Note over Runner,Builder: Monorepo Deployment Flow
Runner->>Config: Load Action Inputs
Config-->>Runner: rootDirectory, sourceFilesOutsideRootDirectory (NEW)
Runner->>Client: deploy(config)
Client->>Client: buildDeploymentOptions()
alt rootDirectory is set
Note over Client: NEW: Include projectSettings in API payload
Client->>Client: projectSettings.rootDirectory = config.rootDirectory
Client->>Client: projectSettings.sourceFilesOutsideRootDirectory = ...
end
Client->>SDK: createDeployment(path, options)
SDK->>VercelAPI: POST /v13/deployments
Note right of VercelAPI: CHANGED: Body now contains projectSettings
VercelAPI-->>SDK: 200 OK (Deployment Created)
SDK-->>Client: Deployment Events
Note over Builder: Build Lifecycle Starts
VercelAPI->>Builder: Trigger Build
alt projectSettings.rootDirectory provided
Builder->>Builder: Navigate to rootDirectory (e.g., apps/web)
Builder->>Builder: Detect Package Manager (e.g., pnpm)
Builder->>Builder: Run build (Correct workspace context)
else projectSettings.rootDirectory missing (Old Behavior)
Builder->>Builder: Fallback to repository root
Builder->>Builder: Default to npm (May fail pnpm workspaces)
end
Builder-->>VercelAPI: Build Status update
VercelAPI-->>Runner: Deployment Ready
There was a problem hiding this comment.
1 issue found across 9 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/vercel-api.ts">
<violation number="1" location="src/vercel-api.ts:121">
P2: `sourceFilesOutsideRootDirectory` is hardcoded to `true`, so the `source-files-outside-root-directory` input/config value is ignored whenever `rootDirectory` is set.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Runner as GitHub Action Runner
participant Client as @vercel/client (Local)
participant API as Vercel Deployment API
participant Builder as Vercel Build Server
Note over Runner,Client: Initialization & Config
Runner->>Runner: getActionConfig()
Note right of Runner: NEW: Read source-files-outside-root-directory
Runner->>Client: createDeployment(clientOptions)
Note right of Client: Uses root-directory for<br/>local file hashing/upload
Note over Runner,API: Deployment Creation Flow
Runner->>Runner: CHANGED: buildDeploymentOptions()
alt root-directory is provided
Runner->>Runner: NEW: Construct projectSettings object
Note right of Runner: Set rootDirectory & <br/>sourceFilesOutsideRootDirectory
else root-directory is empty
Runner->>Runner: Omit projectSettings
end
Runner->>API: POST /v13/deployments
Note right of API: Payload includes CHANGED:<br/>projectSettings.rootDirectory
API->>Builder: Trigger Remote Build
Note over Builder: Remote Execution Environment
alt projectSettings.rootDirectory present
Builder->>Builder: CHANGED: Switch context to rootDirectory
Builder->>Builder: Detect package manager (e.g., pnpm)
Builder->>Builder: Resolve workspace:* dependencies
else No projectSettings
Builder->>Builder: Fallback to repository root
Builder->>Builder: Default package manager (npm)
Note over Builder: May fail on monorepo structures
end
Builder-->>API: Build Status
API-->>Runner: Deployment Events (ready/error)
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request introduces support for monorepos by adding a new source-files-outside-root-directory input, which allows Vercel to resolve dependencies located outside the project's root directory. The changes include updates to the README, action configuration, and the Vercel API client to pass these settings. Additionally, the PR refactors test helpers to reduce code duplication across the test suite. Review feedback suggests making the projectSettings object in the API client conditional to avoid sending empty objects for standard deployments, which would also require updating the corresponding test expectations.
| }, | ||
| gitMetadata: buildGitMetadata(deployContext), | ||
| autoAssignCustomDomains: config.autoAssignCustomDomains, | ||
| projectSettings: {}, |
There was a problem hiding this comment.
Initializing projectSettings as an empty object means it will be sent in every deployment request, even for non-monorepo projects. It is safer to only include this optional field when monorepo settings are actually provided to avoid potential side effects with the Vercel API's handling of project-level overrides.
| if (config.rootDirectory) { | ||
| options.projectSettings!.rootDirectory = config.rootDirectory | ||
| } | ||
| if (config.sourceFilesOutsideRootDirectory) { | ||
| options.projectSettings!.sourceFilesOutsideRootDirectory = true | ||
| } |
There was a problem hiding this comment.
To avoid sending an empty projectSettings object for standard deployments, consider initializing it conditionally only when rootDirectory or sourceFilesOutsideRootDirectory are present.
if (config.rootDirectory || config.sourceFilesOutsideRootDirectory) {
options.projectSettings = {}
if (config.rootDirectory) {
options.projectSettings.rootDirectory = config.rootDirectory
}
if (config.sourceFilesOutsideRootDirectory) {
options.projectSettings.sourceFilesOutsideRootDirectory = true
}
}| { | ||
| name: 'empty when neither is set', | ||
| overrides: { rootDirectory: '', sourceFilesOutsideRootDirectory: false }, | ||
| expected: {}, |
|
Deploy preview for file ready!
Deployed with vercel-action |
|
Deploy preview for express-basic-auth ready!
Deployed with vercel-action |
|
Deploy preview for static ready!
Deployed with vercel-action |
…ect-settings # Conflicts: # dist/index.js # dist/index.js.map # src/__tests__/vercel-api.test.ts # src/__tests__/vercel.test.ts # src/vercel-api.ts
|



Summary
When deploying monorepos via the API, the
root-directoryinput is only passedto
@vercel/client'sclientOptions(local file hashing) but never includedin the
POST /v13/deploymentsbody asprojectSettings.rootDirectory.Without this, Vercel's build server falls back to the repo root, fails to detect
the correct package manager (e.g. pnpm), and uses npm — which breaks on
workspace:*protocol withEUNSUPPORTEDPROTOCOL.Changes
projectSettings.rootDirectoryin the deployment options whenroot-directoryis setsource-files-outside-root-directoryinput (default:true) tosupport monorepos where dependencies live outside the root directory
Test plan
Summary by cubic
Fixes monorepo deployments by sending
projectSettings.rootDirectoryand optionallysourceFilesOutsideRootDirectory, and adds anode-versioninput to control Vercel’s Node.js version.Bug Fixes
projectSettings.rootDirectoryinPOST /v13/deploymentsto avoid falling back to the repo root and mis-detecting the package manager.vercel.jsonexists; includerootDirectoryand/orsourceFilesOutsideRootDirectoryonly when set, and treat them independently.New Features
node-versioninput to setprojectSettings.nodeVersion; the input takes precedence, and when unset falls back topackage.jsonengines.node.source-files-outside-root-directoryinput (defaultfalse) for monorepos with shared packages outside the root.Written for commit 7fa3d7a. Summary will update on new commits. Review in cubic