Giving stages the tools they need
Declare the tools, system packages and setup script your stages run with, preview changes before you save, and fix a stage waiting on a build.
An agent can only use the tools its device has. If your project needs jq, a Go toolchain, or a Postgres client, you can declare them once and CodeHerder makes sure each stage has them. That declaration is the environment. This page covers how to set one up, how to check what a stage gets, and what to do when a stage waits because no device can build it.
If you need a whole custom container image instead, see Running a stage in your own container image. The two don’t mix for system packages; see System packages below.
How an environment works
You pin each tool to an exact version. CodeHerder checks the pinned set once and records the result. Before a stage starts, the device that will run it installs those exact tools. Two stages with the same tools share one build, so the cost is paid once per device.
An environment is built from layers. From widest to narrowest:
- Group. A group workspace’s environment applies to every workspace below it.
- Workspace.
- Workflow. Applies to every stage of that workflow.
- Stage. Applies to one stage.
The rules are the same everywhere:
- Tools: the narrowest layer that names a tool wins. A workflow or stage can also remove a tool that a wider layer declared, for the stages it covers.
- Setup scripts: every layer’s script runs, in layer order, widest first. See Running a stage in your own container image for how a setup script behaves.
- System packages: the packages from all layers are added together. A narrower layer can’t remove a package a wider one declared.
Where to manage it
In the web app, go to Settings → Environment. The page shows these sections:
- Inherited from groups: tools from the groups above this workspace. Read only here.
- This layer: the tools this workspace or group declares.
- Setup script: the script this layer runs before the agent starts.
- Workflow and stage overrides: the layers narrower than the workspace.
- Effective environment: what a given stage ends up with.
- Resolve status and Version history: described below.
A group’s page leaves out the overrides, effective environment and resolve status, because they only make sense for a workspace.
A workflow’s own page and a stage’s own page (Settings → Stages) each have an Environment section for that layer.
Only a workspace admin who is a person can change an environment. An agent’s credential is refused. Everyone else sees the pages read only.
Add a tool
In the web app, open This layer, choose Add tool, then From registry. Search for the tool and pick a version from its releases. The Custom tool option is for a tool that isn’t in the registry; it asks for a name, version, download URL template, the binaries to put on the command path, a sha256 for at least one platform, and optional replacements.
From the CLI, find the tool and its releases first:
ch env search pup
ch env releases DataDog/pup
Then pin the version you want:
ch env tools add DataDog/pup 1.23.7
A tool name is one of:
- a registry name, such as
DataDog/pup; npm:<package>,pip:<package>orgo:<module>for a language package.
The version is always exact. A range, or latest, is refused. A custom tool can’t be added with ch env tools add; write it with ch env set instead, which replaces the whole workspace environment from a JSON file. Run ch env show --json to see the shape.
To remove a tool this layer declared:
ch env tools delete DataDog/pup
Per-workflow and per-stage layers
Add --workflow <key> or --stage <key> to put a tool in one workflow’s or one stage’s layer instead of the workspace layer:
ch env tools add --stage review jq 1.7
ch env tools add --workflow story docker/compose v2.29.7
To drop a tool that a wider layer declared, for one stage or workflow only, add --remove-inherited:
ch env tools delete --stage review --remove-inherited go
In the web app, the Add tool menu has Remove an inherited tool for the same job.
System packages
If a stage needs an operating system package, declare the Debian package name. You don’t pin a version.
ch env system add postgresql-client libvips42
ch env system delete libvips42
ch env system add --stage review jq
For more control, ch env system dockerfile --from-file system.Dockerfile sets a Dockerfile fragment for the layer. A fragment can’t start a new image with FROM, and it has a size limit of 16 KiB.
System packages build on the CodeHerder base image. A write is refused while a stage in scope sets its own container image, and the message names those stages. A device that can’t build the packages shows as ineligible in the device matrix described below.
Preview a change, then save
Before you save, review what the change reaches. In the web app, Save changes stays disabled until you choose Review changes. The review lists each stage the change reaches, its tool changes, and the devices that must build.
From the CLI, write your layer to a file and preview it. Nothing is saved:
ch env diff --from-file env.json
ch env diff --workflow story --from-file workflow-env.json
ch env diff --stage review --from-file stage-env.json
Without --workflow or --stage, the file is the workspace layer, in the same format as ch env set takes. With them, it’s the environment object that ch env show --json prints for that layer.
See what a stage gets
The Effective environment section picks a workflow and a stage and lists every tool, package and script with the layer it comes from, plus the build state on each device.
From the CLI:
ch env show --effective --task <taskId>
ch env show --effective --workflow story --stage review
With --task, the stage defaults to the task’s current stage. ch env show with no flags prints the workspace layer on its own.
Confirm a source change
After you save, CodeHerder checks each tool again in the background. If a tool’s source moved since the last check, such as a new repository or download host, a person has to confirm it. This stops a changed download location from reaching your devices unnoticed.
A tool set that already had a good result keeps using it until you confirm. A tool set that is new has nothing to fall back on, so its stages wait.
To see what is waiting and confirm it, use the Resolve status section, which shows each pending source change and a Confirm button. From the CLI:
ch env lock
ch env diff
ch env diff --confirm
ch env lock --resolve starts a fresh check now. Confirming is for workspace admins who are people. An agent’s credential is refused.
Check the build on each device
Each device builds the environments its stages need. In the web app, open Devices → Environments. The matrix has one row per environment and one column per device. Each cell shows one state:
| State | Meaning |
|---|---|
| ready | The device has the tools. |
| building | The device is installing them. |
| pending | The device hasn’t started. |
| failed | The build failed. The cell shows the reason and the time of the next retry. |
| ineligible | This device can’t run this environment, for example because of its platform. The cell shows why. |
A failed build retries by itself, with longer waits between tries. To read a failure, open its build log from the cell. To retry sooner, choose Rebuild on a failed or ready cell. The device must be online.
The same data is in the CLI:
ch env status
ch env status --device build-01
ch env log --device build-01 3f2a9c1d4b7e
ch env rebuild --device build-01 3f2a9c1d4b7e
The hash is from ch env status. A unique start of it is enough. Only a workspace admin who is a person can rebuild.
When a stage waits
If no device can run a stage’s tools, the task doesn’t start. Instead, CodeHerder puts a blocker on the task. The blocker starts with “No device can run this stage’s tools”, then names the tool and platform, or points at the failed build. Run ch task blockers <taskId> to read it. The task’s activity also shows a start refused entry. The blocker clears by itself when a device can run the tools. You don’t need to do anything to restart the task.
To fix it:
- Run
ch env statusor open Devices → Environments and find the failed or ineligible cells. - Read the reason, or the build log for a failure.
- Fix the cause. Common ones are a tool with no build for the device’s platform, or a download that fails. Then choose Rebuild, or link a device that can run it.
If the cause is an unconfirmed source change, confirm it as described above. For other start problems, see Why isn’t my task moving?.
Tools only reach stages that CodeHerder starts on a device. A dev session and a task you run on your own machine (see Run a task on your own machine) don’t get the workspace’s tools.
History and revert
Every save writes a new version. Version history on Settings → Environment lists them, and the workflow and stage pages show their own layer’s history.
ch env versions
ch env versions --stage review
ch env revert 1
ch env revert --workflow story 2
A revert doesn’t rewind history. It writes the old content as a new version, so you can see what happened. ch env revert --stage review 2 restores only that stage’s environment and leaves the rest of the stage as it is now.
If someone else saves while you edit, your save is refused. Reload and apply your change again.
Related guides
- Running a stage in your own container image: a custom image and the setup script
- Managing your devices: readiness, capacity and linking a device
- Why isn’t my task moving?: every reason a task waits
- Customising workflows: where workflow and stage settings live
Last updated