### devcontainer.installCli() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Installs the Dev Container CLI globally using npm. It handles installation from a local directory for testing or from the npm registry. ```APIDOC ## devcontainer.installCli() ### Description Install the devcontainer CLI globally using npm. This function first checks for a local `_devcontainer_cli` directory for testing private builds, otherwise it installs the latest stable version from npm. ### Method ```typescript async function installCli(exec: ExecFunction): Promise ``` ### Parameters #### Exec Function (`exec`) - **exec** (ExecFunction) - Required - A function used to execute shell commands. This function should accept a command string and return a Promise resolving with the command's exit code. ### Returns `Promise` — True if the installation succeeded, false otherwise. ### Behavior - Checks for a local `_devcontainer_cli` directory. - If found, installs from the local directory using `npm install -g`. - Otherwise, installs `@devcontainers/cli@0` globally via npm. - Returns true only if all executed commands succeed (exit code 0). ### Example ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; import { exec } from './exec'; // your exec implementation const installed = await devcontainer.installCli(exec); if (!installed) { console.error('Failed to install DevContainer CLI'); process.exit(1); } ``` ``` -------------------------------- ### Start Dev Container Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Use this function to start a Dev Container. It takes container startup arguments and a logging callback. It can optionally update the container user's UID/GID to match the host. ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; const result = await devcontainer.up( { workspaceFolder: '/repo', configFile: '/repo/.devcontainer/devcontainer.json', env: ['MY_VAR=value', 'DEBUG=1'], skipContainerUserIdUpdate: false, }, (message) => console.log(message) ); if (result.outcome === 'success') { console.log(`Container started: ${result.containerId}`); console.log(`Workspace folder: ${result.remoteWorkspaceFolder}`); } else { console.error(`Failed to start container: ${result.message}`); } ``` -------------------------------- ### devcontainer.up() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Start a Dev Container and prepare it for command execution. This function invokes the `devcontainer up` command to create or start a container and logs its output. ```APIDOC ## devcontainer.up() ### Description Start a Dev Container and prepare it for command execution. This function invokes the `devcontainer up` command to create or start a container and logs its output. ### Method `async function devContainerUp(args: DevContainerCliUpArgs, log: (data: string) => void): Promise` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **args** (DevContainerCliUpArgs) - Required - Container startup arguments including workspace folder, config file, environment variables, and mounts * **log** ((data: string) => void) - Required - Callback function to log output ### Request Example ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; const result = await devcontainer.up( { workspaceFolder: '/repo', configFile: '/repo/.devcontainer/devcontainer.json', env: ['MY_VAR=value', 'DEBUG=1'], skipContainerUserIdUpdate: false, }, (message) => console.log(message) ); if (result.outcome === 'success') { console.log(`Container started: ${result.containerId}`); console.log(`Workspace folder: ${result.remoteWorkspaceFolder}`); } else { console.error(`Failed to start container: ${result.message}`); } ``` ### Response #### Success Response (200) On success, returns a `DevContainerCliUpResult` object containing `containerId`, `remoteUser`, and `remoteWorkspaceFolder`. On error, returns a `DevContainerCliError` object. #### Response Example ```json { "outcome": "success", "containerId": "some_container_id", "remoteUser": "user", "remoteWorkspaceFolder": "/workspace" } ``` ```json { "outcome": "error", "message": "Failed to start container" } ``` ``` -------------------------------- ### Install Dev Container CLI Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Install the Dev Container CLI globally using `installCli`. This function first checks for a local testing directory and then falls back to a global npm installation. ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; import { exec } from './exec'; // your exec implementation const installed = await devcontainer.installCli(exec); if (!installed) { console.error('Failed to install DevContainer CLI'); process.exit(1); } ``` -------------------------------- ### Check Docker Buildx Installation Source: https://github.com/devcontainers/ci/blob/main/_autodocs/docker.md Verifies if Docker buildx is installed and accessible on the system. Use this to ensure buildx is available before attempting to build images. ```typescript async function isDockerBuildXInstalled( exec: ExecFunction, ): Promise ``` ```typescript import * as docker from 'devcontainer-build-run-common/docker'; import { exec } from './exec'; const installed = await docker.isDockerBuildXInstalled(exec); if (!installed) { console.log('Docker buildx is not available'); } ``` -------------------------------- ### devcontainer.isCliInstalled() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Checks if the Dev Container CLI is installed and available in the system's PATH. It returns a boolean indicating the installation status. ```APIDOC ## devcontainer.isCliInstalled() ### Description Check if the devcontainer CLI is installed and available in PATH. This function is useful for verifying prerequisites before attempting to use other Dev Container CLI functionalities. ### Method ```typescript async function isCliInstalled(exec: ExecFunction): Promise ``` ### Parameters #### Exec Function (`exec`) - **exec** (ExecFunction) - Required - A function used to execute shell commands. This function should accept a command string and return a Promise resolving with the command's exit code. ### Returns `Promise` — True if the CLI is installed and available, false otherwise. ### Behavior - Runs `devcontainer --help` command with silent output. - Returns true only if the command exits with code 0. ### Example ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; import { exec } from './exec'; // your exec implementation const installed = await devcontainer.isCliInstalled(exec); if (!installed) { console.log('DevContainer CLI is not installed'); } ``` ``` -------------------------------- ### Example Usage of ExecFunction Source: https://github.com/devcontainers/ci/blob/main/_autodocs/exec.md Demonstrates how to use an ExecFunction to run a shell command and process its output. Ensure you have a concrete implementation of ExecFunction available. ```typescript import { exec } from './your-exec-implementation'; const result = await exec('npm', ['install'], { silent: false }); console.log(`Exit code: ${result.exitCode}`); console.log(`Output: ${result.stdout}`); if (result.exitCode !== 0) { console.error(`Error: ${result.stderr}`); } ``` -------------------------------- ### Start Dev Container Source: https://github.com/devcontainers/ci/blob/main/_autodocs/README.md Initiates a Dev Container instance using the specified configuration. It allows setting environment variables and provides the container ID upon successful startup. A callback function can be used to log progress messages. ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; const result = await devcontainer.up( { workspaceFolder: '/repo', configFile: '/repo/.devcontainer/devcontainer.json', env: ['MY_VAR=value'], }, (message) => console.log(message) ); if (result.outcome === 'success') { console.log(`Container ID: ${result.containerId}`); } ``` -------------------------------- ### Build, Run, and Push Dev Container Image Source: https://github.com/devcontainers/ci/blob/main/docs/github-action.md This example demonstrates how to build a dev container, run a command, and push the resulting image to a container registry like GitHub Container Registry for caching and reuse. It requires logging into the registry first. ```yaml name: 'build' on: # rebuild any PRs and main branch changes pull_request: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout (GitHub) uses: actions/checkout@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and run Dev Container task uses: devcontainers/ci@v0.3 with: # Change this to point to your image name imageName: ghcr.io/example/example-devcontainer # Change this to be your CI task/script runCmd: | # Add multiple commands to run if needed make install-packages make ci-build ``` -------------------------------- ### Build Multi-Platform Dev Container on GitHub Actions Source: https://github.com/devcontainers/ci/blob/main/docs/multi-platform-builds.md This workflow builds a multi-platform dev container image using QEMU emulation. It requires setup for QEMU and buildx, and logs into a container registry. ```yaml name: 'build' on: pull_request: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout (GitHub) uses: actions/checkout@v3 - name: Set up QEMU for multi-architecture builds uses: docker/setup-qemu-action@v3 - name: Setup Docker buildx for multi-architecture builds uses: docker/setup-buildx-action@v3 with: use: true - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and release devcontainer Multi-Platform uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/UserNameHere/ImageNameHere platform: linux/amd64,linux/arm64 ``` -------------------------------- ### Run CI Build in Dev Container with Cache Source: https://github.com/devcontainers/ci/blob/main/docs/github-action.md This example demonstrates using a pre-built dev container image as a cache source for a CI build. It sets `push: never` to avoid pushing the image again and specifies the command to run. ```yaml - name: Run make ci-build in dev container uses: devcontainers/ci@v0.3 with: # [Optional] If you have a separate workflow like the one above # to pre-build your container image, you can reference it here # to speed up your application build workflows as well! cacheFrom: ghcr.io/example/example-devcontainer push: never runCmd: make ci-build ``` -------------------------------- ### isSkopeoInstalled Source: https://github.com/devcontainers/ci/blob/main/_autodocs/skopeo.md Checks if the skopeo tool is installed and available in the system's PATH. It verifies this by attempting to run `skopeo --help`. ```APIDOC ## isSkopeoInstalled() ### Description Check if the skopeo tool is installed and available. ### Method async ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```typescript import * as skopeo from 'devcontainer-build-run-common/skopeo'; import { exec } from './exec'; const installed = await skopeo.isSkopeoInstalled(exec); if (!installed) { console.log('Skopeo is not installed'); } ``` ### Response #### Success Response - **boolean**: True if `skopeo --help` succeeds, false otherwise #### Response Example ```json { "installed": true } ``` ``` -------------------------------- ### Dev Container CLI Up Arguments Source: https://github.com/devcontainers/ci/blob/main/_autodocs/INDEX.md Defines the structure for arguments used when starting a container with the Dev Container CLI. ```typescript type DevContainerCliUpArgs = { "attach-shell-arg"?: string; "container-forward-ports"?: string; "container-name"?: string; "container-only"?: boolean; "copy"?: string; "copy-from"?: string; "copy-to"?: string; "docker-run-args"?: string; "exit-code-stdin"?: boolean; "forward-ports"?: string; "id-only"?: boolean; "mount"?: string; "no-mount-cache"?: boolean; "prebuild"?: boolean; "quiet-learning"?: boolean; "remove-existing"?: boolean; "remove-volumes"?: boolean; "skip-post-create"?: boolean; "skip-shutdown"?: boolean; "skip-update-check"?: boolean; "workspace-folder"?: string; }; ``` -------------------------------- ### Dev Container Configuration with localEnv Reference Source: https://github.com/devcontainers/ci/blob/main/docs/github-action.md Example of a devcontainer.json configuration that uses a `localEnv` reference for an environment variable. ```json { "remoteEnv": { "HELLO": "${localEnv:HELLO}" } } ``` -------------------------------- ### isDockerBuildXInstalled Source: https://github.com/devcontainers/ci/blob/main/_autodocs/docker.md Checks if Docker buildx is installed and available on the system. It verifies this by attempting to run `docker buildx --help` and checking for success. ```APIDOC ## isDockerBuildXInstalled() ### Description Check if Docker buildx is installed and available. ### Method `async function isDockerBuildXInstalled(exec: ExecFunction): Promise` ### Parameters #### Path Parameters - **exec** (ExecFunction) - Required - Function to execute shell commands ### Returns - **Promise** — True if `docker buildx --help` succeeds, false otherwise ### Example ```typescript import * as docker from 'devcontainer-build-run-common/docker'; import { exec } from './exec'; const installed = await docker.isDockerBuildXInstalled(exec); if (!installed) { console.log('Docker buildx is not available'); } ``` ``` -------------------------------- ### Dev Container Build and Run with Container Registry Caching Source: https://github.com/devcontainers/ci/blob/main/azdo-task/README.md Example showing how to log in to an Azure Container Registry, build, and run a Dev Container, utilizing cached images for faster builds. Pushes the image to the registry if the build is successful and not from a PR branch. ```yaml trigger: - main pool: vmImage: ubuntu-latest steps: # Replace the username and registry name here with your own details # This step also uses an ACR_TOKEN specified as a secret variable - script: | docker login -u test -p $ACR_TOKEN yourregistry.azurecr.io displayName: 'Log in to Container Registry' env: ACR_TOKEN: $(ACR_TOKEN) - task: DevcontainersCi@0 inputs: # Change this to point to your image name imageName: 'yourregistry.azurecr.io/example-dev-container' # Change this to be your CI task/script runCmd: 'make ci-build' # sourceBranchFilterForPush allows you to limit which branch's builds # are pushed to the registry sourceBranchFilterForPush: refs/heads/main ``` -------------------------------- ### Check Dev Container CLI Installation Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Verify if the Dev Container CLI is installed and accessible in the system's PATH using `isCliInstalled`. This function requires an `exec` function to run shell commands. ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; import { exec } from './exec'; // your exec implementation const installed = await devcontainer.isCliInstalled(exec); if (!installed) { console.log('DevContainer CLI is not installed'); } ``` -------------------------------- ### Check if Skopeo is Installed Source: https://github.com/devcontainers/ci/blob/main/_autodocs/skopeo.md Verifies if the skopeo command-line tool is accessible on the system. This is useful for ensuring that subsequent skopeo operations can be performed. ```typescript import * as skopeo from 'devcontainer-build-run-common/skopeo'; import { exec } from './exec'; const installed = await skopeo.isSkopeoInstalled(exec); if (!installed) { console.log('Skopeo is not installed'); } ``` -------------------------------- ### Basic Dev Container Build and Run Task Source: https://github.com/devcontainers/ci/blob/main/azdo-task/README.md A simple example demonstrating the basic usage of the DevcontainersCi task to run a CI build command. Each run rebuilds the Docker image. ```yaml trigger: - main pool: vmImage: ubuntu-latest steps: - task: DevcontainersCi@0 inputs: # Change this to be your CI task/script runCmd: 'make ci-build' ``` -------------------------------- ### Usage Example for Dev Containers CI Action Source: https://github.com/devcontainers/ci/blob/main/_autodocs/github-action.md This snippet demonstrates how to use the devcontainers/ci action in a GitHub workflow to build and test a Dev Container image. It includes common inputs like imageName, imageName, cacheFrom, push, runCmd, env, and inheritEnv. ```yaml - name: Pre-build and test in dev container uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/owner/myapp imageTag: v1.0,latest cacheFrom: ghcr.io/owner/myapp:main push: always runCmd: npm install && npm test env: | DEBUG=1 CI=true inheritEnv: true ``` -------------------------------- ### Get Host User Information Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Bash commands to retrieve user and group information from the host system, used for UID/GID alignment when building images with a specified remote user. ```bash id -u -n # Get username cat /etc/passwd # Get uid/gid cat /etc/group # Check for conflicts ``` -------------------------------- ### DevcontainersCi Task Usage Example Source: https://github.com/devcontainers/ci/blob/main/_autodocs/azure-devops-task.md Example of how to use the DevcontainersCi task within an Azure DevOps pipeline job. This snippet demonstrates setting various inputs for building and pushing a container image. ```yaml jobs: - job: BuildContainer pool: vmImage: 'ubuntu-latest' steps: - checkout: self - task: DevcontainersCi@0 inputs: imageName: 'ghcr.io/owner/myapp' imageTag: 'v1.0,latest' cacheFrom: 'ghcr.io/owner/myapp:main' push: 'always' runCmd: 'npm install && npm test' env: | DEBUG=1 CI=true inheritEnv: true - script: echo $(runCmdOutput) displayName: 'Show command output' ``` -------------------------------- ### DevContainerCliUpResult Interface Source: https://github.com/devcontainers/ci/blob/main/_autodocs/types.md Success result from `devcontainer up`. Contains details about the created or started container. ```typescript interface DevContainerCliUpResult extends DevContainerCliSuccessResult { containerId: string; remoteUser: string; remoteWorkspaceFolder: string; } ``` -------------------------------- ### Build Each Platform with Docker Buildx Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Commands to build Docker images for individual platforms (e.g., amd64, arm64) using Docker Buildx, outputting to OCI archives. ```bash docker buildx build \ --platform linux/amd64 \ --output type=oci,dest=/tmp/output.tar \ --tag ghcr.io/org/image:v1.0-linux-amd64 . docker buildx build \ --platform linux/arm64 \ --output type=oci,dest=/tmp/output.tar \ --tag ghcr.io/org/image:v1.0-linux-arm64 . ``` -------------------------------- ### Pre-build Image and Run CI Build in Dev Container Source: https://github.com/devcontainers/ci/blob/main/docs/github-action.md This snippet combines pre-building a dev container image, pushing it, and then running a CI command within that container. It utilizes caching and ensures the image is pushed after the build. ```yaml - name: Pre-build image and run make ci-build in dev container uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/example/example-devcontainer cacheFrom: ghcr.io/example/example-devcontainer push: always runCmd: make ci-build ``` -------------------------------- ### DevContainerCliUpArgs Interface Source: https://github.com/devcontainers/ci/blob/main/_autodocs/types.md Arguments for the `devcontainer up` command. Used to start or create a dev container. ```typescript interface DevContainerCliUpArgs { workspaceFolder: string; configFile: string | undefined; additionalCacheFroms?: string[]; cacheTo?: string[]; skipContainerUserIdUpdate?: boolean; env?: string[]; userDataFolder?: string; additionalMounts?: string[]; } ``` -------------------------------- ### Create Multi-Arch Manifest with Docker Buildx Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Command to create a multi-architecture manifest using Docker Buildx imagetools, consolidating platform-specific images under a single tag. ```bash docker buildx imagetools create \ -t ghcr.io/org/image:v1.0 \ ghcr.io/org/image:v1.0-linux-amd64 \ ghcr.io/org/image:v1.0-linux-arm64 ``` -------------------------------- ### Basic Dev Container Build and Run Source: https://github.com/devcontainers/ci/blob/main/docs/github-action.md This snippet shows the simplest way to use the action to build and run a command within a dev container. It rebuilds the Docker image on each run. ```yaml name: 'build' on: # rebuild any PRs and main branch changes pull_request: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout (GitHub) uses: actions/checkout@v3 - name: Build and run dev container task uses: devcontainers/ci@v0.3 with: # Change this to be your CI task/script runCmd: yarn test ``` -------------------------------- ### Get Dev Container Remote User Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Retrieves the username that will execute commands within the container. Defaults to 'root' if not specified in the configuration. ```typescript function getRemoteUser(config: DevContainerConfig): string ``` ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); const remoteUser = config.getRemoteUser(devcontainerConfig); console.log(remoteUser); // 'vscode' or 'root' ``` -------------------------------- ### Get Container User Information Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Commands to inspect user and group information within a Docker container, used for UID/GID alignment. ```bash docker run ${image} cat /etc/passwd docker run ${image} cat /etc/group ``` -------------------------------- ### Pre-build Image and Run Commands in Dev Container Source: https://github.com/devcontainers/ci/blob/main/README.md Combines pre-building a Dev Container image and running a command within it. This is useful for a complete CI workflow. It specifies image details, cache source, push behavior, and the command to execute. ```yaml - name: Pre-build image and run make ci-build in dev container uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/example/example-devcontainer cacheFrom: ghcr.io/example/example-devcontainer push: always runCmd: make ci-build ``` -------------------------------- ### Common Module Exports: dev-container-cli.ts Source: https://github.com/devcontainers/ci/blob/main/_autodocs/module-exports.md Exposes functions for interacting with the devcontainer CLI, including building, starting, and executing commands within development containers. ```APIDOC ## Module: dev-container-cli.ts ### Description Exposes functions for interacting with the devcontainer CLI, including building, starting, and executing commands within development containers. ### Exports - **`DevContainerCliError`** (Interface): Error result from CLI command. - **`DevContainerCliSuccessResult`** (Interface): Success result base type. - **`DevContainerCliBuildResult`** (Interface): Build command success result. - **`DevContainerCliBuildArgs`** (Interface): Arguments for build command. - **`DevContainerCliUpArgs`** (Interface): Arguments for up command. - **`DevContainerCliUpResult`** (Interface): Result from up command. - **`DevContainerCliExecArgs`** (Interface): Arguments for exec command. - **`devcontainer`** (Object): Namespace containing CLI functions. - **`devcontainer.build()`** (Function): Build Dev Container image. - **`devcontainer.up()`** (Function): Start Dev Container. - **`devcontainer.exec()`** (Function): Execute command in container. - **`devcontainer.isCliInstalled()`** (Function): Check if CLI is available. - **`devcontainer.installCli()`** (Function): Install devcontainer CLI globally. ### Dependencies - `ExecFunction` from `exec.ts` (injected) - `findWindowsExecutable()` from `windows.ts` ### Used by - All GitHub Action/Azure DevOps implementations - Docker module for build/run operations ``` -------------------------------- ### Run Commands in Dev Container for CI Source: https://github.com/devcontainers/ci/blob/main/README.md This snippet demonstrates running a command, like 'make ci-build', within a Dev Container. It can optionally use a pre-built image specified in 'cacheFrom' to speed up the process. 'push: never' indicates the image is not pushed. ```yaml - name: Run make ci-build in dev container uses: devcontainers/ci@v0.3 with: # [Optional] If you have a separate workflow like the one above # to pre-build your container image, you can reference it here # to speed up your application build workflows as well! cacheFrom: ghcr.io/example/example-devcontainer push: never runCmd: make ci-build ``` -------------------------------- ### Get Dev Container Dockerfile Path Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Retrieves the relative path to the Dockerfile used for building the Dev Container. Supports both 'build.dockerfile' and legacy 'dockerFile' properties. ```typescript function getDockerfile(config: DevContainerConfig): string | undefined ``` ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); const dockerfile = config.getDockerfile(devcontainerConfig); console.log(dockerfile); // 'Dockerfile' or undefined ``` -------------------------------- ### Build Multi-Platform Dev Container on Azure DevOps Source: https://github.com/devcontainers/ci/blob/main/docs/multi-platform-builds.md This pipeline builds a multi-platform dev container image using QEMU emulation. It includes steps for logging into a container registry, setting up QEMU, and configuring buildx. ```yaml trigger: - main pool: vmImage: ubuntu-latest jobs: - job: BuildContainerImage displayName: Build Container Image timeoutInMinutes: 0 steps: - checkout: self - task: Docker@2 displayName: Login to Container Registry inputs: command: login containerRegistry: RegistryNameHere - script: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes displayName: Set up QEMU - script: docker buildx create --use displayName: Set up docker buildx - task: DevcontainersCi@0 inputs: imageName: UserNameHere/ImageNameHere platform: linux/amd64,linux/arm64 ``` -------------------------------- ### Get Dev Container Workspace Folder Path Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Determines the path where the workspace will be mounted inside the container. Requires the parsed configuration and the host repository path. ```typescript function getWorkspaceFolder( config: DevContainerConfig, repoPath: string, ): string ``` ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); const workspaceFolder = config.getWorkspaceFolder(devcontainerConfig, '/repo'); console.log(workspaceFolder); // '/workspaces/repo' ``` -------------------------------- ### Get Docker Build Context Path Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Retrieves the relative path to the Docker build context from a parsed devcontainer configuration. Handles both 'build.context' and legacy 'context' properties. ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); const context = config.getContext(devcontainerConfig); console.log(context); // 'build' or undefined ``` -------------------------------- ### Pre-build Dev Container Image Source: https://github.com/devcontainers/ci/blob/main/README.md Use this snippet to pre-build a Dev Container image. It specifies the image name and a cache-from source for potential optimization. The 'push: always' ensures the image is pushed after building. ```yaml - name: Pre-build dev container image uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/example/example-devcontainer cacheFrom: ghcr.io/example/example-devcontainer push: always ``` -------------------------------- ### getDockerfile() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Gets the relative path to the Dockerfile used for building the Dev Container. This function considers both `build.dockerfile` and the legacy `dockerFile` properties in the configuration. It returns the path as a string or undefined if not specified. ```APIDOC ## getDockerfile() ### Description Get the path to the Dockerfile used to build the Dev Container. ### Method `function` ### Parameters #### Path Parameters - **config** (DevContainerConfig) - Yes - Parsed devcontainer configuration ### Returns `string | undefined` — Relative path to Dockerfile, or undefined if not specified (supports both `build.dockerfile` and legacy `dockerFile` properties) ### Example ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); const dockerfile = config.getDockerfile(devcontainerConfig); console.log(dockerfile); // 'Dockerfile' or undefined ``` ``` -------------------------------- ### Get Absolute Path Source: https://github.com/devcontainers/ci/blob/main/_autodocs/file.md Converts a given path to an absolute path. If the input path is already absolute, it is returned as is. Otherwise, it is joined with the reference path. Handles platform-specific path separators. ```typescript import * as file from 'devcontainer-build-run-common/file'; import path from 'path'; // Input is already absolute const abs1 = file.getAbsolutePath('/workspace/repo', process.cwd()); console.log(abs1); // '/workspace/repo' // Input is relative const abs2 = file.getAbsolutePath('./repo', '/workspace'); console.log(abs2); // '/workspace/repo' const abs3 = file.getAbsolutePath('config', '/app/src'); console.log(abs3); // '/app/src/config' // Works with parent directory references const abs4 = file.getAbsolutePath('../sibling', '/app/src'); console.log(abs4); // '/app/sibling' ``` -------------------------------- ### createMultiPlatformImage() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/docker.md Creates a multi-platform Docker manifest by combining platform-specific images. It takes an execution function, base image name, tag, and an array of platform suffixes. ```APIDOC ## createMultiPlatformImage() ### Description Create a multi-platform Docker manifest combining platform-specific images. ### Method Signature ```typescript async function createMultiPlatformImage( exec: ExecFunction, imageName: string, tag: string, platformSuffixes: string[], ): Promise ``` ### Parameters - **exec** (ExecFunction) - Required - Function to execute shell commands - **imageName** (string) - Required - Base image name without tag (e.g., 'ghcr.io/org/image') - **tag** (string) - Required - Tag for the manifest (e.g., 'latest') - **platformSuffixes** (string[]) - Required - Platform suffixes (e.g., ['linux-amd64', 'linux-arm64']) - must have at least one entry ### Throws Error if the manifest creation fails or if platformSuffixes is empty ### Behavior - Creates a Docker manifest using `docker buildx imagetools create` - Combines per-platform images with suffixes into a single manifest - Each platform image is referenced as `{imageName}:{tag}-{suffix}` ### Example ```typescript import * as docker from 'devcontainer-build-run-common/docker'; import { exec } from './exec'; await docker.createMultiPlatformImage( exec, 'ghcr.io/myorg/myapp', 'v1.0', ['linux-amd64', 'linux-arm64'] ); console.log('Multi-platform manifest created'); ``` ``` -------------------------------- ### buildImageNames() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/platform.md Constructs full Docker image name strings, optionally appending platform-specific suffixes to tags. ```APIDOC ## buildImageNames() ### Description Build full image name strings with optional platform suffixes. ### Method ```typescript function buildImageNames( imageName: string, imageTags: string[], platformSuffix?: string, ): string[] ``` ### Parameters #### Path Parameters - **imageName** (string) - Required - Base image name including registry (e.g., 'ghcr.io/org/image') - **imageTags** (string[]) - Required - Array of tag strings (e.g., ['v1.0', 'latest']) - **platformSuffix** (string) - Optional - Optional platform suffix to append to each tag (e.g., 'linux-amd64') ### Returns `string[]` — Array of full image references with tags ### Behavior - If no platformSuffix is provided, returns images in format `{imageName}:{tag}` - If platformSuffix is provided, returns images in format `{imageName}:{tag}-{platformSuffix}` - Creates one output entry for each input tag ### Example ```typescript import * as platform from 'devcontainer-build-run-common/platform'; const names1 = platform.buildImageNames( 'ghcr.io/myorg/myapp', ['v1.0', 'latest'] ); console.log(names1); // ['ghcr.io/myorg/myapp:v1.0', 'ghcr.io/myorg/myapp:latest'] const names2 = platform.buildImageNames( 'ghcr.io/myorg/myapp', ['v1.0', 'latest'], 'linux-amd64' ); console.log(names2); // ['ghcr.io/myorg/myapp:v1.0-linux-amd64', 'ghcr.io/myorg/myapp:latest-linux-amd64'] ``` ``` -------------------------------- ### GitHub Actions: Multi-Platform Build and Manifest Source: https://github.com/devcontainers/ci/blob/main/docs/multi-platform-builds.md This workflow builds and pushes Docker images for different platforms (amd64, arm64) and then merges them into a multi-arch manifest. It uses the devcontainers/ci action for building and pushing. ```yaml jobs: build: strategy: matrix: include: - runner: ubuntu-latest platform: linux/amd64 - runner: ubuntu-24.04-arm platform: linux/arm64 runs-on: ${{ matrix.runner }} steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/setup-buildx-action@v3 - uses: devcontainers/ci@v0.3 with: imageName: ghcr.io/example/myimage platform: ${{ matrix.platform }} useNativeRunner: true push: always manifest: needs: build runs-on: ubuntu-latest steps: - uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/setup-buildx-action@v3 - uses: devcontainers/ci/merge@v0.3 with: imageName: ghcr.io/example/myimage platforms: linux/amd64,linux/arm64 ``` -------------------------------- ### Azure DevOps Pipelines: Multi-Platform Build and Manifest Source: https://github.com/devcontainers/ci/blob/main/docs/multi-platform-builds.md This pipeline defines stages for building platform-specific Docker images and then merging them into a multi-arch manifest. It utilizes Azure DevOps tasks for Docker login, buildx setup, and the Devcontainers CI/Merge tasks. ```yaml stages: - stage: Build jobs: - job: BuildAmd64 pool: vmImage: ubuntu-latest steps: - task: Docker@2 displayName: Login to Container Registry inputs: command: login containerRegistry: RegistryNameHere - script: docker buildx create --use displayName: Set up docker buildx - task: DevcontainersCi@0 inputs: imageName: myregistry.azurecr.io/devcontainer platform: linux/amd64 useNativeRunner: true push: always - job: BuildArm64 pool: name: 'Self-Hosted-ARM64' steps: - task: Docker@2 displayName: Login to Container Registry inputs: command: login containerRegistry: RegistryNameHere - script: docker buildx create --use displayName: Set up docker buildx - task: DevcontainersCi@0 inputs: imageName: myregistry.azurecr.io/devcontainer platform: linux/arm64 useNativeRunner: true push: always - stage: Manifest dependsOn: Build jobs: - job: MergeManifest pool: vmImage: ubuntu-latest steps: - task: Docker@2 displayName: Login to Container Registry inputs: command: login containerRegistry: RegistryNameHere - script: docker buildx create --use displayName: Set up docker buildx - task: DevcontainersMerge@0 inputs: imageName: myregistry.azurecr.io/devcontainer platforms: linux/amd64,linux/arm64 ``` -------------------------------- ### Copy OCI Archive to Registry with Skopeo Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Command to copy a built OCI archive to a Docker registry using Skopeo, enabling distribution of platform-specific images. ```bash skopeo copy \ oci-archive:/tmp/output.tar:v1.0-linux-amd64 \ docker://ghcr.io/org/image:v1.0-linux-amd64 ``` -------------------------------- ### Push Image from Native Runner Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Command to push a Docker image built on a native runner to a registry. ```bash docker push ghcr.io/org/image:v1.0-linux-arm64 ``` -------------------------------- ### Build Image on Native Runner Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md Command to build a Docker image directly on a native runner, leveraging the runner's architecture without needing explicit platform flags. ```bash devcontainer build \ --image-name ghcr.io/org/image:v1.0-linux-arm64 \ (no --platform flag - uses native runner architecture) ``` -------------------------------- ### Copy Container Image using Skopeo Source: https://github.com/devcontainers/ci/blob/main/_autodocs/skopeo.md Copies a container image between different storage locations, such as OCI archives or Docker registries. Supports copying all layers and metadata when the 'all' flag is true. Ensure skopeo is installed and the source/destination references are correctly formatted. ```typescript import * as skopeo from 'devcontainer-build-run-common/skopeo'; import { exec } from './exec'; // Copy from OCI archive to Docker registry await skopeo.copyImage( exec, true, 'oci-archive:/tmp/output.tar:latest', 'docker://ghcr.io/myorg/myapp:latest' ); console.log('Image copied successfully'); // Copy between Docker registries await skopeo.copyImage( exec, true, 'docker://docker.io/library/alpine:latest', 'docker://ghcr.io/myorg/alpine:latest' ); ``` -------------------------------- ### loadFromFile() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/config.md Loads and parses a devcontainer.json file from the specified filepath. It returns a Promise that resolves to the parsed DevContainerConfig object. Errors are thrown if the file cannot be read or is not valid JSON. ```APIDOC ## loadFromFile() ### Description Load and parse a devcontainer.json file from the filesystem. ### Method `async function` ### Parameters #### Path Parameters - **filepath** (string) - Yes - Absolute path to the devcontainer.json file ### Returns `Promise` — Configuration object parsed from the JSON file ### Throws Error if the file cannot be read or is not valid JSON ### Example ```typescript import * as config from 'devcontainer-build-run-common/config'; const devcontainerConfig = await config.loadFromFile('/repo/.devcontainer/devcontainer.json'); console.log(devcontainerConfig.remoteUser); // 'vscode' ``` ``` -------------------------------- ### pushImage() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/docker.md Pushes a built Docker image to a container registry. It requires an execution function, the image name (including registry), and an optional image tag. ```APIDOC ## pushImage() ### Description Push a built image to a container registry. ### Method Signature ```typescript async function pushImage( exec: ExecFunction, imageName: string, imageTag: string | undefined, ): Promise ``` ### Parameters - **exec** (ExecFunction) - Required - Function to execute shell commands - **imageName** (string) - Required - Image name including registry (e.g., 'ghcr.io/org/image') - **imageTag** (string | undefined) - Optional - Image tag (defaults to 'latest') ### Throws Error if the push fails (non-zero exit code) ### Example ```typescript import * as docker from 'devcontainer-build-run-common/docker'; import { exec } from './exec'; await docker.pushImage(exec, 'ghcr.io/myorg/myapp', 'v1.0'); console.log('Image pushed successfully'); ``` ``` -------------------------------- ### buildImage Source: https://github.com/devcontainers/ci/blob/main/_autodocs/docker.md Builds a Dev Container image from a devcontainer.json specification. It handles loading the configuration, setting up build parameters, and optionally aligning user IDs. ```APIDOC ## buildImage() ### Description Build a Dev Container image from a devcontainer.json specification. ### Method `async function buildImage(exec: ExecFunction, imageName: string, imageTag: string | undefined, checkoutPath: string, subFolder: string, skipContainerUserIdUpdate: boolean, cacheFrom: string[], cacheTo: string[]): Promise` ### Parameters #### Path Parameters - **exec** (ExecFunction) - Required - Function to execute shell commands - **imageName** (string) - Required - Image name including registry (e.g., 'ghcr.io/org/image') - **imageTag** (string | undefined) - Optional - Image tag (defaults to 'latest' if undefined) - **checkoutPath** (string) - Required - Absolute path to the repository checkout - **subFolder** (string) - Required - Subfolder relative to checkoutPath containing .devcontainer - **skipContainerUserIdUpdate** (boolean) - Required - If true, skip aligning container user UID/GID with host - **cacheFrom** (string[]) - Required - Array of cache image references (can be empty) - **cacheTo** (string[]) - Required - Array of cache export destinations (can be empty) ### Returns - **Promise** — Name of the built image (may include -userfix suffix if UID/GID was updated) ### Throws Error if Docker build fails or if devcontainer.json is invalid/missing ### Behavior: - Loads devcontainer.json from the specified location - Extracts build parameters (Dockerfile, context, build args) - Builds using `docker buildx build` with layer caching - If remoteUser is specified and skipContainerUserIdUpdate is false, creates a derived image with aligned UID/GID - Returns the final image name (which may include -userfix suffix) ### Example ```typescript import * as docker from 'devcontainer-build-run-common/docker'; import { exec } from './exec'; const imageName = await docker.buildImage( exec, 'ghcr.io/myorg/myapp', 'v1.0', '/repo', '.', false, ['ghcr.io/myorg/myapp:main'], [] ); console.log(`Built image: ${imageName}`); ``` ``` -------------------------------- ### devcontainer.build() Source: https://github.com/devcontainers/ci/blob/main/_autodocs/dev-container-cli.md Build a Dev Container image using the devcontainer CLI. This function invokes the `devcontainer build` command with provided arguments and handles build output logging. ```APIDOC ## devcontainer.build() ### Description Build a Dev Container image using the devcontainer CLI. This function invokes the `devcontainer build` command with provided arguments and handles build output logging. ### Method `async function devContainerBuild(args: DevContainerCliBuildArgs, log: (data: string) => void): Promise` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **args** (DevContainerCliBuildArgs) - Required - Build arguments including workspace folder, config file, image names, and cache settings * **log** ((data: string) => void) - Required - Callback function to log build output ### Request Example ```typescript import { devcontainer } from 'devcontainer-build-run-common/dev-container-cli'; const result = await devcontainer.build( { workspaceFolder: '/repo', configFile: '/repo/.devcontainer/devcontainer.json', imageName: ['ghcr.io/org/image:latest'], platform: 'linux/amd64,linux/arm64', additionalCacheFroms: ['ghcr.io/org/image:main'], noCache: false, }, (message) => console.log(message) ); if (result.outcome === 'success') { console.log('Build succeeded'); } else { console.error(`Build failed: ${result.message}`); } ``` ### Response #### Success Response (200) On success, returns a `DevContainerCliBuildResult` object. On error, returns a `DevContainerCliError` object. #### Response Example ```json { "outcome": "success" } ``` ```json { "outcome": "error", "message": "Build failed" } ``` ``` -------------------------------- ### Build Image Names with Platform Suffix Source: https://github.com/devcontainers/ci/blob/main/_autodocs/platform.md Constructs full Docker image references by combining a base image name, an array of tags, and an optional platform suffix. Generates one reference per tag. ```typescript import * as platform from 'devcontainer-build-run-common/platform'; const names1 = platform.buildImageNames( 'ghcr.io/myorg/myapp', ['v1.0', 'latest'] ); console.log(names1); // ['ghcr.io/myorg/myapp:v1.0', 'ghcr.io/myorg/myapp:latest'] const names2 = platform.buildImageNames( 'ghcr.io/myorg/myapp', ['v1.0', 'latest'], 'linux-amd64' ); console.log(names2); // ['ghcr.io/myorg/myapp:v1.0-linux-amd64', 'ghcr.io/myorg/myapp:latest-linux-amd64'] ``` -------------------------------- ### Environment Variable Substitution in devcontainer.json Source: https://github.com/devcontainers/ci/blob/main/_autodocs/architecture.md JSON configuration showing how to substitute environment variables from the host or local environment into devcontainer.json build arguments. Supports `${env:VAR}` and `${localenv:VAR}`. ```json { "build": { "args": { "BASE_IMAGE": "${env:MY_BASE_IMAGE}", "VERSION": "${localenv:BUILD_VERSION}" } } } ```