MCPcopy
hub / github.com/coder/mux / createMultiProject

Method createMultiProject

src/node/services/workspaceService.ts:3335–3719  ·  view source on GitHub ↗

* Scope note: unlike create(), this does not accept creation-time `tags` — * multi-project workspaces currently can't be tagged atomically (callers * would need a follow-up updateTags, reintroducing a crash-window gap). * Thread tags through here if orchestration loops ever target multi-pro

(
    projects: ProjectRef[],
    branchName: string,
    trunkBranch: string | undefined,
    title?: string,
    runtimeConfig?: RuntimeConfig
  )

Source from the content-addressed store, hash-verified

3333 * workspaces.
3334 */
3335 async createMultiProject(
3336 projects: ProjectRef[],
3337 branchName: string,
3338 trunkBranch: string | undefined,
3339 title?: string,
3340 runtimeConfig?: RuntimeConfig
3341 ): Promise<Result<FrontendWorkspaceMetadata>> {
3342 assert(projects.length > 1, "createMultiProject requires at least two projects");
3343 if (!this.isMultiProjectWorkspacesExperimentEnabled()) {
3344 return Err(MULTI_PROJECT_WORKSPACES_DISABLED_ERROR);
3345 }
3346
3347 let initLogger: ReturnType<WorkspaceService["createInitLogger"]> | null = null;
3348
3349 try {
3350 const validation = validateWorkspaceName(branchName);
3351 if (!validation.valid) {
3352 return Err(validation.error ?? "Invalid workspace name");
3353 }
3354
3355 const normalizedProjects = projects.map((project) => ({
3356 projectPath: stripTrailingSlashes(project.projectPath),
3357 projectName: project.projectName,
3358 }));
3359 const primaryProject = normalizedProjects[0];
3360 assert(primaryProject, "createMultiProject requires a primary project");
3361
3362 const configSnapshot = this.config.loadConfigOrDefault();
3363 for (const project of normalizedProjects) {
3364 const projectConfig = configSnapshot.projects.get(
3365 stripTrailingSlashes(project.projectPath)
3366 );
3367 if (projectConfig?.parentProjectPath) {
3368 return Err(
3369 `Sub-project ${project.projectName} cannot be added directly to a multi-project workspace. Add its parent project instead.`
3370 );
3371 }
3372 }
3373
3374 for (const project of normalizedProjects) {
3375 const projectConfig = configSnapshot.projects.get(
3376 stripTrailingSlashes(project.projectPath)
3377 );
3378 if (!projectConfig?.trusted) {
3379 return Err(
3380 `Project ${project.projectName} must be trusted before creating workspaces. Trust the project in Settings → Security, or create a workspace from the project page.`
3381 );
3382 }
3383 }
3384
3385 const workspaceId = this.config.generateStableId();
3386
3387 let finalRuntimeConfig: RuntimeConfig = runtimeConfig ?? {
3388 type: "worktree",
3389 srcBaseDir: this.config.srcDir,
3390 };
3391
3392 if (this.policyService?.isEnforced()) {

Callers 4

AppInnerFunction · 0.80
routerFunction · 0.80
server.test.tsFile · 0.80

Calls 15

getOrCreateSessionMethod · 0.95
createInitLoggerMethod · 0.95
createContainerMethod · 0.95
removeContainerMethod · 0.95
ErrFunction · 0.90
validateWorkspaceNameFunction · 0.90
stripTrailingSlashesFunction · 0.90
getSrcBaseDirFunction · 0.90
createRuntimeFunction · 0.90
hasSrcBaseDirFunction · 0.90

Tested by

no test coverage detected