( options: DevcontainerUpOptions )
| 207 | * Parses the JSON output to extract container info. |
| 208 | */ |
| 209 | export async function devcontainerUp( |
| 210 | options: DevcontainerUpOptions |
| 211 | ): Promise<DevcontainerUpResult> { |
| 212 | const { |
| 213 | workspaceFolder, |
| 214 | configPath, |
| 215 | initLogger, |
| 216 | abortSignal, |
| 217 | additionalMounts, |
| 218 | remoteEnv, |
| 219 | timeoutMs = DEFAULT_UP_TIMEOUT_MS, |
| 220 | } = options; |
| 221 | |
| 222 | const baseArgs = ["up", "--log-format", "json", "--workspace-folder", workspaceFolder]; |
| 223 | |
| 224 | if (configPath) { |
| 225 | baseArgs.push("--config", configPath); |
| 226 | } |
| 227 | |
| 228 | // Add mounts for credential sharing |
| 229 | if (additionalMounts) { |
| 230 | for (const mount of additionalMounts) { |
| 231 | // Single formatting point — the devcontainer CLI only accepts type/source/target/external. |
| 232 | baseArgs.push("--mount", `type=bind,source=${mount.source},target=${mount.target}`); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | // Add remote env vars |
| 237 | if (remoteEnv) { |
| 238 | for (const [key, value] of Object.entries(remoteEnv)) { |
| 239 | baseArgs.push("--remote-env", `${key}=${value}`); |
| 240 | } |
| 241 | } |
| 242 | |
| 243 | const runUp = (args: string[]): Promise<DevcontainerUpResult> => { |
| 244 | const logArgs = redactDevcontainerArgsForLog(args); |
| 245 | initLogger.logStep(`Running: devcontainer ${logArgs.join(" ")}`); |
| 246 | |
| 247 | return new Promise((resolve, reject) => { |
| 248 | if (abortSignal?.aborted) { |
| 249 | reject(new Error("devcontainer up aborted")); |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | const proc = spawn("devcontainer", args, { |
| 254 | stdio: ["ignore", "pipe", "pipe"], |
| 255 | timeout: timeoutMs, |
| 256 | cwd: workspaceFolder, |
| 257 | }); |
| 258 | |
| 259 | let settled = false; |
| 260 | let lastResultLine: DevcontainerUpResultLine | null = null; |
| 261 | let stderrBuffer = ""; |
| 262 | let timeoutId: ReturnType<typeof setTimeout> | undefined; |
| 263 | |
| 264 | const settleSuccess = (result: DevcontainerUpResult) => { |
| 265 | if (settled) return; |
| 266 | settled = true; |
no test coverage detected