* Provision container: create, sync project, checkout branch. * Throws on error (does not call logComplete - caller handles that). * Used by postCreateSetup() for streaming logs before initWorkspace().
(params: {
containerName: string;
projectPath: string;
workspacePath: string;
branchName: string;
trunkBranch: string;
initLogger: InitLogger;
abortSignal?: AbortSignal;
env?: Record<string, string>;
trusted?: boolean;
})
| 673 | * Used by postCreateSetup() for streaming logs before initWorkspace(). |
| 674 | */ |
| 675 | private async provisionContainer(params: { |
| 676 | containerName: string; |
| 677 | projectPath: string; |
| 678 | workspacePath: string; |
| 679 | branchName: string; |
| 680 | trunkBranch: string; |
| 681 | initLogger: InitLogger; |
| 682 | abortSignal?: AbortSignal; |
| 683 | env?: Record<string, string>; |
| 684 | trusted?: boolean; |
| 685 | }): Promise<void> { |
| 686 | const { |
| 687 | containerName, |
| 688 | projectPath, |
| 689 | workspacePath, |
| 690 | branchName, |
| 691 | trunkBranch, |
| 692 | initLogger, |
| 693 | abortSignal, |
| 694 | env, |
| 695 | } = params; |
| 696 | |
| 697 | // 1. Create container (with image pull if needed) |
| 698 | initLogger.logStep(`Creating container from ${this.config.image}...`); |
| 699 | |
| 700 | if (abortSignal?.aborted) { |
| 701 | throw new Error("Workspace creation aborted"); |
| 702 | } |
| 703 | |
| 704 | // Create and start container with streaming output for image pull progress |
| 705 | const runResult = await streamDockerRun(containerName, this.config.image, initLogger, { |
| 706 | abortSignal, |
| 707 | shareCredentials: this.config.shareCredentials, |
| 708 | }); |
| 709 | if (runResult.exitCode !== 0) { |
| 710 | await runDockerCommand(`docker rm -f ${containerName}`, 10000); |
| 711 | throw new Error(`Failed to create container: ${runResult.stderr}`); |
| 712 | } |
| 713 | |
| 714 | // Detect container's default user (may be non-root, e.g., codercom/enterprise-base runs as "coder") |
| 715 | const containerUser = await this.detectContainerUser(containerName, abortSignal); |
| 716 | this.storeContainerUserInfo(containerUser); |
| 717 | |
| 718 | // Create /src directory and /var/mux/plans in container. |
| 719 | // /var/mux is used instead of ~/.mux because /root has 700 permissions, |
| 720 | // which makes it inaccessible to VS Code Dev Containers (non-root user). |
| 721 | initLogger.logStep("Preparing workspace directory..."); |
| 722 | const mkdirResult = await this.prepareWorkspaceDirectories( |
| 723 | containerName, |
| 724 | containerUser, |
| 725 | abortSignal |
| 726 | ); |
| 727 | if (mkdirResult.exitCode !== 0) { |
| 728 | await runDockerCommand(`docker rm -f ${containerName}`, 10000); |
| 729 | throw new Error(`Failed to create workspace directory: ${mkdirResult.stderr}`); |
| 730 | } |
| 731 | |
| 732 | initLogger.logStep("Container ready"); |
no test coverage detected