Workflow YAML syntax reference (v1)
Loom workflows are YAML files validated as schema v1. This document lists
the configuration options for the Loom .loom/workflow.yml file — the file where
you define the jobs that make up your workflow.
- Default location:
.loom/workflow.yml - Validate:
loom check - Compile (resolve includes + templates):
loom compile --workflow .loom/workflow.yml - Run (local):
loom run --local --workflow .loom/workflow.yml
When you are editing your workflow file, validate it with loom check.
Loom workflow configuration uses YAML formatting, so the order of keys is not important unless otherwise specified. Explicit YAML tags are rejected.
YAML composition
Anchors, aliases, and mapping merge keys can remove repetition within one workflow
file. Loom expands them into independent concrete values before it resolves
include, extends, or default.
.linux: &linux
target: linux
script: &checks
- go test ./...
unit:
<<: *linux
stage: test
race:
<<: *linux
stage: test
lint:
stage: test
target: linux
script: *checks
Mapping merge precedence is deterministic:
- An explicit key in the destination mapping overrides every merged value.
- For
<<: [*first, *second], the first source wins when both sources define the same key.
Anchors are file-local. An included file can declare and use its own anchors, but an alias cannot refer to an anchor in another file. Duplicate explicit keys, alias cycles, and merge sources that are not mappings are rejected. Loom also limits alias nesting to 32 levels and materialization to 100,000 expanded nodes across the root workflow and all included files.
Keywords
A Loom workflow configuration includes:
-
Global keywords that configure workflow structure and behavior:
Keyword Description versionSchema version. Must be v1.stagesThe names and order of the workflow stages. includeImport configuration from local template YAML files. workflowOptional workflow gate; non-empty rules are Experimental. fragmentsNamed reusable command values. defaultDefault values for job keywords. variablesDefine default variables for all jobs in the workflow. -
Jobs configured with job keywords:
Keyword Description stageThe stage a job belongs to. targetExecution target platform. before_scriptSetup commands to run before the main script. scriptList of shell commands to execute. after_scriptFinalization commands for the job. extendsInherit ordered hidden or executable parents. inheritSelect native defaults and root variables. rulesRun or skip this job from declared inputs. needsDeclare DAG-style dependencies between jobs. imageRun the job inside a Docker container. runner_poolSelect a runner pool for remote execution. variablesJob-scoped variables that override defaults. secretsDeclare secrets resolved at runtime. servicesSidecar containers that run alongside the job. invariantPolicy configuration for job-level checkpoints. cacheCache directories between runs for performance. artifactsExtract files from the workspace after execution.
Global keywords
Some keywords are not defined inside a job. These keywords control workflow structure or import additional configuration.
version
Use version to declare which schema version this workflow file conforms to.
The validator uses this value to select the correct set of validation rules.
Keyword type: Global keyword.
Supported values:
- Must be exactly the string
v1.
Example of version:
version: v1
Additional details:
versionis required. Omitting it produces a schema error.- Future schema versions will ship with explicit migration notes and will use a
different version string (e.g.
v2). Within v1, changes are intended to be additive and backwards-compatible.
stages
Use stages to define default dependency barriers. An executable job that omits
needs waits for every executable job in every earlier declared stage. The planner
lowers these barriers into ordinary dependency edges before execution.
Keyword type: Global keyword.
Supported values:
- A non-empty YAML sequence of stage name strings.
- Each stage name must match:
^[a-z][a-z0-9_-]{0,31}$(lowercase, starts with a letter, up to 32 characters, using only letters, digits, hyphens, and underscores). - Stage names must be unique — duplicates are rejected.
Example of stages:
stages:
- deps
- ci
When jobs omit needs:
- Jobs in
depsbecome ready without stage prerequisites. - Jobs in
cibecome ready only after every executabledepsjob succeeds. - Dependency-ready jobs may run concurrently within the configured limit.
If a job fails, jobs that require it remain blocked while independent jobs can continue.
Additional details:
stagesis required. Omitting it produces a schema error.- An explicit
needslist replaces the job's stage prerequisites. An explicit empty list permits immediate readiness, subject to additional artifact prerequisites. - A dependency that conflicts with another explicit dependency or an omitted-needs stage barrier fails compilation as a cycle.
- If a stage is defined but no jobs reference it, the stage is silently ignored.
- Stage names are validated against the regex pattern at schema time. Invalid names
produce an error like:
rename stage to match ^[a-z][a-z0-9_-]{0,31}$.
Related topics:
stage(job keyword) to assign a job to a stage.
include
Use include to import template YAML files into your workflow configuration.
You can split a large workflow into multiple files to increase readability or
reduce duplication across jobs.
Included files are merged with the main workflow file. Includes are resolved
before validation and before template extension (extends).
Keyword type: Global keyword.
Supported values: A YAML sequence of include entries. Each entry supports only
the include:local subkey.
Example of include:
include:
- local: .loom/templates/common.yml
- local: .loom/templates/languages/node.yml
Additional details:
- Include files can themselves contain
includeentries (nested includes). Cycles are detected and rejected with a descriptive error showing the include chain. - Included files are merged in order: earlier includes are applied first, then later includes, then the main workflow file. If the same key appears in multiple files, the last definition wins (for root-level scalars and sequences) or keys are merged recursively (for mappings).
- Loom resolves includes and command fragments, ordered
extendsparents, selecteddefaultvalues, then selected root variables. - Job/default caches merge by name; services replace as a complete declaration. See native composition for clearers and exact merge policies.
Related topics:
- Includes and templates for patterns and recommended directory structure.
include:local
Use include:local to include a template file from the same repository.
Keyword type: Global keyword.
Supported values:
- A file path string that:
- Is normalized and relative to the repository root
- Ends with
.ymlor.yamlfor a literal path; star patterns may use other suffixes - Does not contain
..(path traversal is rejected)
Local star patterns support *, ** and **/; other glob punctuation is
literal. Matches use ordered eligible snapshot sources in Git repositories,
including dirty and nonignored untracked files. See
includes and templates
for source-byte selection, self-inclusion and work limits.
Example of include:local:
include:
- local: .loom/templates/common.yml
Multiple includes:
include:
- local: .loom/templates/common.yml
- local: .loom/templates/languages/node.yml
- local: .loom/templates/jobs/lint.yml
Additional details:
- Rooted reads reject absolute paths, traversal and links that escape the repository.
Files may live in any repository directory;
.loom/templates/is an organizational choice. - Vendor external templates into the repository and review them like any other code change.
- Each include entry must be a mapping with only the key
local. Other keys (such asremote) are not yet supported and will produce an error.
Related topics:
- Includes and templates for recommended structure and debugging resolution.
workflow
Use workflow for workflow-wide conditional execution. Loom evaluates rules once
before provider setup, secret resolution, or execution. Non-empty rules and
their decision evidence are Experimental; see Rules.
Keyword type: Global keyword.
Supported values:
- A mapping with the optional key
rules. No other keys are allowed underworkflow.
Example of workflow:
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
Related topics:
- Rules for details on rule expression syntax and behavior.
workflow:rules
workflow:rules contains ordered conditions that determine whether the workflow
runs.
Keyword type: Global keyword.
Supported values:
- A YAML sequence. It may be empty; each non-empty entry must be a mapping with
exactly one non-empty string key,
if.
Accepted example:
workflow:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
Additional details:
- Rule-contract v1 accepts
$VARIABLE,$VARIABLE == "literal", and$VARIABLE != "literal". V2 additionally accepts RE2 matching with=~,&&,||, parentheses, and variable-to-variable equality or inequality. The planner emits the lowest capable contract version, so existing narrow workflows retain v1. - Rules are evaluated in order after all expressions pass syntax validation. The first match allows execution; no match skips the workflow.
- In v2,
&&binds tighter than||; both associate left and short-circuit from left to right. Only spaces and tabs separate expression tokens. String and regex operands are JSON double-quoted strings after YAML decoding. - Expressions requiring V2 syntax are limited to 4,096 source bytes, 32 group levels, 256 parsed nodes, 1,024 decoded regex bytes, and 65,536 bytes per accessed regex input. Complete V1 expressions retain V1 parsing inside V2 lists. See Rules for the exact grammar and behavior.
- Missing or non-string inputs and invalid expressions fail closed before any provider-capable work.
- Only predefined variables marked
Pipelineare available. Job, step, workflow-defined, and ambient environment variables are not rule inputs. - Unary negation,
!~, and slash-delimited regex are unsupported.
fragments
A mapping of names to reusable command values. Use exactly {fragment: name} in
command positions; fragments may refer to other fragments across local includes.
They create no graph nodes. See Command fragments
for forms, bounds and source diagnostics.
default
Use default to set default values for job keywords. Each default is applied to every
job that doesn't already define that keyword. This lets you avoid repeating the same
configuration across many jobs.
Selected default configuration is merged after parent resolution and before validation.
Use inherit to choose default keywords and root variables separately. Job values
override defaults. For nested mappings (like variables and cache), keys are merged
recursively — the job provides overrides and the default provides fallbacks.
Keyword type: Global keyword.
Supported values: A mapping. The following keys are allowed under default:
| Key | Description |
|---|---|
target | Default execution target for all jobs. |
before_script | Default setup commands for all jobs. |
after_script | Default finalization commands for all jobs. |
image | Default Docker image for all jobs. |
runner_pool | Default runner pool for all jobs. |
variables | Default variables merged into all jobs. |
rules | Default ordered rules for all jobs. |
cache | Default cache configuration for all jobs. |
services | Default sidecar services for all jobs. |
invariant | Default invariant policy for all jobs. |
Example of default:
default:
target: linux
image: alpine:3.20
before_script:
- echo "prepare"
variables:
PNPM_STORE_DIR: .pnpm-store
cache:
paths: [.pnpm-store, .nx/cache]
policy: pull-push
when: always
In this example:
- All jobs default to
target: linux, so individual jobs can omittarget. - All jobs default to
image: alpine:3.20unless they set their ownimage. - All jobs inherit the setup command unless they replace or clear
before_script. - All jobs inherit
PNPM_STORE_DIRunless they override it in their ownvariables. - All jobs inherit
rulesunless they replace the sequence or setrules: []. - All jobs inherit the cache configuration unless they override
cache.
Additional details:
defaultis optional. If omitted, jobs must specify all required keys themselves.default.targetcan satisfy the requiredtargetkey for non-template jobs. Ifdefault.targetis set tolinux, jobs may omittargetand inherit the default.- Default and job configuration do not concatenate — they merge. If the job already has a keyword defined, the job value takes precedence over the default for scalars and sequences. For mappings, keys merge recursively.
- Unknown keys under
defaultproduce an error:remove unknown default key; allowed keys are target, before_script, after_script, image, runner_pool, variables, invariant, cache, services, rules.
Related topics:
variables
Use variables to define default variables available to all jobs. Variables are
key/value string pairs that are injected into the job environment as shell
environment variables.
Variables defined at the top level act as defaults. Each default variable is available in every job, except when the job already has a variable defined with the same name — the job variable takes precedence.
Keyword type: Global keyword.
Supported values: A YAML mapping of variable name/value pairs:
- Variable names must match
^[A-Z_][A-Z0-9_]*$(uppercase letters, digits, and underscores; must start with a letter or underscore). - Values are bare scalars or rich mappings with
value,expand,descriptionandoptions. Bare values keep authored text, including null spellings. See rich values and literal expansion for metadata types, missing/null values and expansion controls.
Example of variables:
variables:
PNPM_STORE_DIR: .pnpm-store
NODE_ENV: production
Additional details:
- Top-level
variablesanddefault.variablesboth provide default values to jobs. The merge happens as part of thedefaultmerge process — seedefault. - Lists, mappings, and other non-scalar variable values produce a schema error. The validator checks scalar shape, not the scalar's implicit YAML type.
- Scalar values recursively expand native
$NAMEand${NAME}references after effective YAML/caller winners are known.$$escapes a literal dollar; escaped values are never reparsed through aliases. Cycles fail validation. See scalar references.
Related topics:
- Variables for precedence rules, provider behavior, and troubleshooting.
- Concepts → Variables for the conceptual model.
- Predefined CI/CD variables for
CI_*andLOOM_*variables injected by the runtime.
Jobs
Any top-level key that is not a global keyword (version, stages, include,
workflow, variables, default) is treated as a job definition. The key must
be a valid job name (see Job naming).
A Loom workflow must contain at least one job. Jobs define the actual work — the commands to run, the environment to run them in, and how they relate to other jobs.
Job naming
Job names must match ^\.?[a-z][a-z0-9_-]{0,63}$:
- Lowercase letters, digits, hyphens, and underscores only.
- Must start with a lowercase letter (or
.for template jobs). - Maximum 64 characters.
Names starting with . are template jobs. Template jobs are not executed
directly — they exist to provide reusable configuration via extends.
Example of job naming:
# Regular jobs (executed)
build-image:
stage: deps
target: linux
script:
- docker build -t myapp .
# Template job (not executed, used via extends)
.node-base:
image: node:20
variables:
NODE_ENV: production
Non-template job requirements
Non-template jobs (names that do not start with .) must include three required
keys:
| Required key | Description |
|---|---|
stage | Must reference a stage declared in stages. |
target | Must be linux or darwin; the selected provider must support it. |
script | A non-empty list of shell command strings. |
If default.target is set, jobs may omit target and inherit the default.
Example of a non-template job:
check:
stage: ci
target: linux
script:
- echo "running checks"
Template job requirements
Template jobs (names starting with .) may contain configuration only. They do
not need command sections or extends. Every authored field is still validated.
Executable jobs must have a valid stage, target and nonempty script after composition.
Job keywords
The keywords below are valid inside a job mapping. Each section describes what the schema validator enforces and how the keyword affects runtime behavior.
stage
Use stage to define which stage a job runs in. When needs is omitted,
the planner adds dependencies on all executable jobs in earlier declared stages.
The local executor can run dependency-ready jobs concurrently.
Keyword type: Job keyword. You can use it only as part of a job.
Supported values:
- A string that must match one of the stage names declared in
stages.
Example of stage:
stages:
- build
- test
compile:
stage: build
target: linux
script:
- make build
unit-tests:
stage: test
target: linux
script:
- make test
In this example, compile runs first (in the build stage). After it succeeds,
unit-tests runs (in the test stage).
Additional details:
stageis required for non-template jobs. Omitting it produces:add required key stage for this job.- If the value doesn't match a declared stage, the error is:
set stage to a declared stage from /stages; "xyz" is not declared. - Template jobs may omit
stage. The inheriting job must provide it.
target
Use target to specify the execution platform for a job.
Keyword type: Job keyword. You can use it only as part of a job or in the
default section.
Supported values:
- Must be exactly
linuxordarwin. Host jobs must match the local OS. - Docker jobs, including image builds, require
linuxon every host.
Example of target:
check:
stage: ci
target: linux
script:
- echo "running on linux"
Additional details:
targetis required for non-template jobs, unlessdefault.targetis set.- On macOS, use
darwinfor native host jobs without an image or image build. On Linux, uselinux. An OS mismatch fails before commands start. - Any other value produces:
set target to "linux" or "darwin". - Windows host execution is not supported. Loom does not infer or change targets to match the machine running the workflow.
before_script
Use before_script for optional setup commands that Loom compiles into the graph
node's setup phase.
Keyword type: Job, template, or default keyword.
Supported values:
- A nonempty string, nested command list (up to ten array levels), or exactly
{fragment: name}. nullor[]to clear inherited setup commands.
Commands retain their order and scalar content. Literal (|) and folded (>)
block scalars are supported.
script
Use script to specify the shell commands the runner executes for a job.
Keyword type: Job keyword. You can use it only as part of a job or in a template
that provides it via extends.
Supported values:
- A nonempty string, nested command list (up to ten array levels), or exactly
{fragment: name}. - The result must contain at least one nonempty string. Literal and folded block scalars retain their YAML-decoded content. See Command fragments.
Example of script:
check:
stage: ci
target: linux
script:
- pnpm install --frozen-lockfile
- pnpm nx run-many -t lint,test
- echo "all checks passed"
Additional details:
scriptis required for non-template jobs. Omitting it produces:add required key script as a non-empty string sequence.- Normalized commands are nonempty strings. Literal block scalars preserve embedded newlines; folded block scalars preserve their YAML-decoded folded content.
- Empty/whitespace-only strings, null, booleans, numbers and other mapping forms are rejected.
- Commands execute sequentially. If any command exits with a non-zero code, the job fails and remaining commands do not run.
after_script
Use after_script for optional finalization commands that Loom compiles into the
graph node's finalization phase.
Keyword type: Job, template, or default keyword.
Supported values:
- A nonempty string, nested command list (up to ten array levels), or exactly
{fragment: name}. nullor[]to clear inherited finalization commands.
Commands retain their order and scalar content. Literal (|) and folded (>)
block scalars are supported.
extends
Use extends to reuse configuration from hidden or executable mapping jobs.
Later parents override earlier parents; the child overrides all parents.
Keyword type: Job keyword. You can use it only as part of a job.
Supported values:
- A job name string or ordered list of job name strings, declared directly or via includes.
nullor[]to clear an include-provided parent declaration. False, empty names and malformed items are invalid. Executable parents retain their own graph identity.
Example of extends:
.node-base:
image: node:20
variables:
NODE_ENV: production
lint:
extends: .node-base
stage: ci
target: linux
script:
- npm run lint
test:
extends: .node-base
stage: ci
target: linux
script:
- npm test
In this example, both lint and test inherit image: node:20 and the NODE_ENV
variable from .node-base. Each job defines its own script.
Additional details:
- Merge behavior:
- Scalars and sequences (strings, numbers, lists): the child value replaces
the parent value entirely. For example, if the parent has
script: ["echo base"]and the child hasscript: ["echo child"], the result is["echo child"]. - Mappings (like
variables,cachein mapping form): keys merge recursively. The parent provides defaults; the child overrides specific keys.
- Scalars and sequences (strings, numbers, lists): the child value replaces
the parent value entirely. For example, if the parent has
- Job/default caches merge by name; services replace as a unit. See native merge semantics.
- Cycles are detected and rejected. If
.aextends.band.bextends.a, the validator reports an error. - Templates can extend other templates (chaining). The chain is resolved recursively.
- To verify the resolved configuration after template merging, run:
loom compile --workflow .loom/workflow.yml
Related topics:
- Includes and templates for patterns, merge semantics, and debugging tips.
rules
Use rules to decide whether an individual job runs. Loom evaluates job rules
before provider setup, secret resolution, services, or commands for that job.
Keyword type: Job keyword.
Supported values:
- A YAML sequence. It may be empty; each entry must be a mapping with exactly
one non-empty string field,
if.
Example of rules:
default:
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
test:
stage: ci
target: linux
script: [task test]
variables:
RUN_TESTS: "true"
rules:
- if: '$RUN_TESTS == "true"'
Additional details:
- Rules are evaluated in declaration order. The first match allows the job; no match skips it. An omitted or empty sequence allows the job.
- The complete v2 grammar supports truthiness,
==,!=,=~,&&,||, grouping, and variable-to-variable string or boolean comparison. - Inputs use job variables over default variables over workflow variables.
Loom also supplies reserved
LOOM_*job metadata; declarations cannot replace those reserved values. Job rules never read the ambient environment. - A job sequence replaces inherited or default rules as a whole. Use
rules: []to clear inherited rules. - Syntax, regex, and expression resource errors are reported by
loom checkat the rule's/rules/{index}/ifpath. Missing and wrong-type declared inputs fail that job closed at runtime. - A denied or invalid job blocks jobs that require it. Independent branches continue. State records retain the resulting job outcomes. The executor keeps decision details in memory without expressions or values.
See Rules for the exact grammar, context, and outcome behavior.
inherit
Select native default keywords and YAML root-variable defaults separately with
inherit: {default: true|false|[names], variables: true|false|[names]}. Omitted/null
controls select all; empty lists select none. Explicit parent/job values survive.
See inheritance filters.
needs
Use needs to replace a job's default stage prerequisites with explicit job
dependencies. The execution planner lowers both explicit dependencies and default
stage barriers into graph edges that the executor uses for readiness.
Keyword type: Job keyword. You can use it only as part of a job.
Supported values:
- A YAML sequence of job name strings.
Example of needs:
stages:
- deps
- ci
install:
stage: deps
target: linux
script:
- pnpm install
lint:
stage: ci
target: linux
needs:
- install
script:
- pnpm run lint
test:
stage: ci
target: linux
needs:
- install
script:
- pnpm test
In this example, install runs first. Then lint and test are both ready and may
run concurrently within the configured limit.
Additional details:
- Omitting
needsadds prerequisites from every executable job in every earlier declared stage. - An explicit list replaces those stage prerequisites.
needs: []adds no dependency edges and can make the job immediately ready. loom compilerejects missing targets, self-dependencies, and dependency cycles at the offendingneedsentry.needsorders jobs but does not transfer files. Useartifact_inputswhen the consumer needs a producer's declared artifacts. Artifact inputs remain additional prerequisites even whenneedsis empty.
artifact_inputs
Use artifact_inputs to restore artifacts from named producer jobs before the
consumer's first command. Producers must declare artifacts.
version: v1
stages: [build, test]
default:
target: linux
build:
stage: build
script:
- mkdir -p dist
- echo built > dist/app.txt
artifacts:
paths: [dist/app.txt]
test:
stage: test
artifact_inputs:
- job: build
availability: available
script:
- cat dist/app.txt
This example uses a Linux host; set default.target: darwin for a macOS host.
The value is a sequence of producer job ID strings or mappings with job and
optional availability. Strings and {job: build} default to required, which
blocks the consumer when no successful publication exists. available skips the
transfer only when no publication exists; invalid descriptors, deleted or malformed
archives, and restore failures remain errors. Availability does not change job
scheduling.
Without inherited inputs, omission transfers no files. With extends, omission
retains the inherited sequence and its policies. A job's own sequence replaces the
whole inherited sequence; artifact_inputs: [] clears it, while null is invalid.
Missing producers, self references, duplicates, producers without artifacts, and
dependency cycles are compile errors reported at the indexed input path. See the
artifact_inputs schema reference
for exact field validation and restore behavior.
image
Use image to run a job inside a Docker container. When image is set, Loom uses
the Docker provider instead of the Host provider, executing the job's script
commands inside the specified container image.
Keyword type: Job keyword. You can use it only as part of a job or in the
default section.
Supported values:
- A non-empty string specifying the Docker image name, including optional registry
path and tag:
<image-name>(useslatesttag)<image-name>:<tag>
- A mapping that names the image and optionally describes how to build it locally before execution.
The following subkeys are available in the image mapping:
| Subkey | Description |
|---|---|
image:name | Required in mapping form. Docker image reference to run for the job. |
image:pull_policy | Acquisition policy for a named prebuilt image. |
image:user | Username, UID, or UID:GID used to run commands in the container. |
image:build | Optional local build configuration to produce the image before job execution. |
Example of scalar image:
stages:
- ci
check:
stage: ci
target: linux
image: node:20-alpine
script:
- node --version
- npm test
This example runs the check job inside the node:20-alpine container.
Example without image (Host provider):
check:
stage: ci
target: linux
script:
- echo "runs directly on the host"
Mapping form:
check:
stage: ci
target: linux
image:
name: loom/nix-local
user: 1000
build:
context: .
dockerfile: Dockerfile.ci
output: type=docker,dest=loom.tar
script:
- echo "building and running in loom/nix-local"
name: non-empty Docker image reference (same semantics as the scalar form).pull_policy(optional): controls acquisition of a named prebuilt image. It defaults toif-not-present.user(optional): nonblank username, UID string, UID:GID string, or nonnegative integer UID used for processes in the job container.build(optional): describes a local build to run before the job.contextanddockerfilemust be non-empty strings. They are interpreted relative to the workflow file and mirrordocker build's context path and Dockerfile flag.outputis optional; when present it is passed through todocker build --output(e.g.type=docker,dest=/tmp/my-image.tar). The validator enforces the mapping shape; the Docker provider performs the build at runtime.
Additional details:
- When
imageis set, the Docker provider mounts the workspace into the container and executes commands there. Whenimageis not set, the Host provider runs commands directly on the machine. - The named image must be available locally or retrievable by the Docker daemon on
the machine running
loom run, according to its pull policy. For local images (not on a registry), build them first — see the Docker provider for details. - Named prebuilt images use
if-not-presentwhenpull_policyis omitted. Setalwaysto acquire before use orneverto require a locally present image. - String
uservalues are preserved exactly. Integer UIDs are normalized to unsigned base-10 text before they reach the provider. - An empty string for
imageindefaultproduces:set default image to a non-empty string. image.buildis supported in the Docker provider. The image is built locally before the job container starts.- The mapping shape is executor-neutral; future remote or Kubernetes executors can
adopt the same
name/buildspec when they start building container images.
Related topics:
- Docker provider for runtime behavior, workspace mounting, and troubleshooting.
- Host provider for behavior when
imageis not set.
image:name
Use image:name to specify the Docker image reference when image is written as a
mapping.
Keyword type: Job keyword (image subkey).
Supported values:
- A non-empty string using the same image reference rules as scalar
image.
Example of image:name:
image:
name: ghcr.io/acme/build:latest
Additional details:
nameis required whenimageuses the mapping form. Omitting it produces:add required key name for image mapping.- Use the scalar form when you only need an image reference and do not need
image:pull_policy,image:user, orimage:build.
image:user
Use image:user to select the identity for commands in the job container.
Keyword type: Job keyword (image subkey).
Supported values:
- A nonblank string such as
runner,1000, or1000:1000. Loom preserves the string exactly. - A nonnegative YAML integer UID. Loom normalizes it to unsigned base-10 text.
Example of image:user:
image:
name: ghcr.io/acme/build:latest
user: "1000:1000"
Additional details:
useris available only in the image mapping form; it is not a job-level key.- Omission leaves the image's configured runtime user unchanged.
- Blank strings, booleans, nulls, floats, sequences, mappings, and negative
integers are rejected at the job's
image/userpath.
image:pull_policy
Use image:pull_policy to control acquisition of a named prebuilt image before
the job container starts.
Keyword type: Job keyword (image subkey).
Supported values:
always: acquire the named image before use.if-not-present: use a local image when present and acquire it when absent.never: require the named image to be present locally.
Example of image:pull_policy:
image:
name: ghcr.io/acme/build:latest
pull_policy: always
Additional details:
- Omission defaults to
if-not-present, including scalarimageshorthand. pull_policycannot be combined withimage:build, because a built image is produced locally rather than acquired as a named prebuilt image.- Invalid values produce an error at the
image/pull_policypath listing all three supported values.
image:build
Use image:build to describe a local image build that runs before the job container
starts.
Keyword type: Job keyword (image subkey).
Supported values:
- A mapping with the following subkeys:
| Subkey | Description |
|---|---|
image:build:context | Required. Build context path passed to the Docker build. |
image:build:dockerfile | Required. Dockerfile path to use for the build. |
image:build:output | Optional build output configuration forwarded to the backend. |
Example of image:build:
image:
name: ghcr.io/acme/build:latest
build:
context: .
dockerfile: Dockerfile.ci
output:
type: registry
name: ghcr.io/acme/build:latest
Additional details:
buildmust be a mapping. Non-mapping values produce:set image build to a mapping with required keys context and dockerfile.- Unknown keys produce:
remove unknown image build key; allowed keys are context, dockerfile, output.
image:build:context
Use image:build:context to set the build context path for the local image build.
Keyword type: Job keyword (image build subkey).
Supported values:
- A non-empty string.
Example of image:build:context:
image:
name: loom/nix-local
build:
context: .
dockerfile: Dockerfile.ci
Additional details:
contextis required whenimage:buildis present. Omitting it produces:add required key context for image build.- The path is interpreted relative to the workflow file location.
image:build:dockerfile
Use image:build:dockerfile to choose which Dockerfile the local image build should
use.
Keyword type: Job keyword (image build subkey).
Supported values:
- A non-empty string.
Example of image:build:dockerfile:
image:
name: loom/nix-local
build:
context: .
dockerfile: Dockerfile.ci
Additional details:
dockerfileis required whenimage:buildis present. Omitting it produces:add required key dockerfile for image build.- The path is interpreted relative to the workflow file location.
image:build:output
Use image:build:output to pass build output configuration through to the image build
backend.
Keyword type: Job keyword (image build subkey).
Supported values:
- A non-empty string, or
- A YAML mapping.
Example of image:build:output:
image:
name: loom/nix-local
build:
context: .
dockerfile: Dockerfile.ci
output: type=docker,dest=loom.tar
Mapping form:
image:
name: ghcr.io/acme/build:latest
build:
context: .
dockerfile: Dockerfile.ci
output:
type: registry
name: ghcr.io/acme/build:latest
Additional details:
- Invalid values produce:
set image build output to either a non-empty string or mapping. - Loom validates only the top-level
outputshape. If you use the mapping form, nested output keys are backend-defined and are passed through as-is.