Skip to main content

Continuous Integration

Continuous Integration

devsy ci builds an ephemeral devcontainer, runs a command inside it, and tears the workspace down afterwards. It lets you verify that your devcontainer.json still builds.

How it works

  1. Resolves an workspace from the current directory (or a given source).
  2. Builds and starts the devcontainer (equivalent to devsy up, without launching an IDE or touching your SSH config).
  3. Runs the given command inside the running container.
  4. Deletes the workspace — always, even when the command fails — unless --keep is passed.

A non-zero exit from the command propagates as the exit code of devsy ci, so a failing test or build fails the CI job.

Usage

devsy ci [flags] [workspace-path|workspace-name] -- <cmd> [args...]

Run the test suite inside the devcontainer for the current project:

devsy ci -- make test

Target a specific project folder and pass environment variables:

devsy ci ./service -- npm test
devsy ci --remote-env CI=true --remote-env NODE_ENV=test -- npm test

Select a specific devcontainer config (e.g. a named .devcontainer/<name> profile):

devsy ci --devcontainer id:ci -- make test

Keep the workspace around for debugging when the command fails:

devsy ci --keep -- ./run-integration-tests.sh

Common flags

FlagDescription
--run-cmdShell command run inside the container via sh -c (alternative to an explicit argv after --).
--remote-env KEY=VALUESet an environment variable in the container at run time. Repeatable.
--keepKeep the workspace instead of tearing it down.
--devcontainerSelect the devcontainer config source: none, image:<ref>, id:<name>, or a path to a devcontainer.json.
--no-cacheBuild without using the cache.
--cache-fromReuse a pre-built image as a build cache source. Repeatable.
--platformRun the container under a specific platform via emulation (e.g. linux/amd64).
--workspace-env KEY=VALUEEnv variables available at build and lifecycle time (not just at run time). Repeatable.
--workspace-env-fileFile(s) of KEY=VALUE build/lifecycle env variables.
--init-env KEY=VALUEEnv variables injected during workspace initialization. Repeatable.
--secrets-fileJSON file ({"KEY":"value"}) of secrets injected into lifecycle commands.
--feature-secrets-fileJSON file of secret values for features.
--secretStored Devsy secret to inject, as NAME[,type=env|mount][,target=X]. Repeatable.
--envStored Devsy env var to inject, as NAME[=TARGET]. Repeatable.
--build-secretStored Devsy secret exposed to the build via BuildKit. Repeatable.
--git-tokenStored Devsy secret with an access token for cloning a private HTTP repository.
--git-token-usernameUsername for --git-token (default inferred from the repo host).

Pre-building and pushing images

devsy ci focuses on running a command. To pre-build and publish a devcontainer image for reuse as a build cache, use devsy build:

devsy build --repository ghcr.io/my-org/my-devcontainer --tag latest --push

Downstream CI jobs can then reference that image via --cache-from to speed up builds.

GitHub Actions

Install the CLI, configure the docker provider, then run devsy ci:

name: Devcontainer CI
on:
push:
branches: [main]
pull_request:

jobs:
devcontainer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Devsy
run: |
curl -fsSL https://github.com/devsy-org/devsy/releases/latest/download/devsy-linux-amd64 -o /usr/local/bin/devsy
chmod +x /usr/local/bin/devsy
- name: Run CI in devcontainer
run: |
devsy provider add docker && devsy provider use docker
devsy ci -- make test