Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

392 commit(s) on main

Merge change request 01M70WES5ZZDJ6RP226WB11BBZ: Let people rename and remove their own passkeys keenan · 15m ago 4b8c9e1d
source preview history blame raw 7.2 KiB
1# Image reference
2
3This page lists every field Vole accepts in a `.vole/images/*.yaml` definition,
4with its defaults and limits. For how workflows reference these definitions, see
5[Workflow reference § image-file](workflow-reference.md#image-file). For the
6task-oriented introduction, see [Workflows § Images](../workflows.md#images).
7
8Unknown keys are rejected. Every definition under `.vole/images/` is parsed when a
9workflow is pushed, even if no job references it, so a broken definition fails the
10push that introduced it.
11
12## File location and limits
13
14| Item | Value |
15|---|---|
16| Location | Directly under `.vole/images/`; subdirectories are rejected |
17| Extension | `.yaml` or `.yml` |
18| Reference | `image-file: <name>`; the extension is optional in the reference |
19| Maximum file size | 64 KiB |
20| Schema version | `1` |
21| Maximum `env` entries | 64 |
22| Maximum `run` entries | 100 |
23| Maximum single command size | 64 KiB after trimming |
24| Maximum env value size | 8 KiB |
25
26A definition is named by its filename without the extension:
27
28```text
29.vole/images/go.yaml -> image-file: go
30.vole/images/go.yml -> image-file: go
31.vole/images/release.yaml -> image-file: release
32```
33
34Names are 1–64 characters: lowercase letters, digits, `.`, `_` and `-`, starting
35with a letter or digit. Two files for one name (`go.yaml` and `go.yml`) are
36rejected as ambiguous.
37
38## Top-level fields
39
40| Field | Type | Required | Default | Meaning |
41|---|---|---|---|---|
42| `version` | integer | yes | — | Schema version. Must be `1`. |
43| `from` | string | yes | — | Base OCI image. A tag works; a digest (`image@sha256:...`) makes the build reproducible. |
44| `env` | mapping | no | none | Environment variables set in the image. |
45| `run` | list of strings | no | none | Build commands, applied in order. |
46
47```yaml
48version: 1
49from: golang:1.27-bookworm
50env:
51 CGO_ENABLED: "0"
52run:
53 - apt-get update && apt-get install -y --no-install-recommends jq
54 - go install example.com/tool@v1.2.3
55```
56
57### `version`
58
59The only supported value is `1`:
60
61```yaml
62version: 1
63```
64
65### `from`
66
67The base image for the definition. It uses the same image-reference validation as
68`image:` in a workflow:
69
70- Must be non-empty and at most 255 bytes.
71- Must start with a letter or digit.
72- May contain letters, digits, `.`, `_`, `/`, `:`, `@`, `+`, `~` and `-`.
73- A leading `-`, `..`, `://`, or a `file:` prefix is rejected.
74
75```yaml
76from: golang:1.27-bookworm@sha256:...
77```
78
79Pin the base image by digest when reproducibility matters. A mutable tag can
80change what a later build produces.
81
82### `env`
83
84A mapping of environment variable names to values, applied to the image:
85
86```yaml
87env:
88 CGO_ENABLED: "0"
89 MESSAGE: "hello world"
90```
91
92| Constraint | Value |
93|---|---|
94| Maximum entries | 64 |
95| Key syntax | `^[A-Za-z_][A-Za-z0-9_]*$` |
96| Maximum value size | 8 KiB |
97| Line endings | Values must be one line; `CR`/`LF` are rejected |
98
99Keys are emitted in sorted order, so the generated build is deterministic.
100
101### `run`
102
103Build commands, run in order after `from` and `env`:
104
105```yaml
106run:
107 - apt-get update && apt-get install -y --no-install-recommends jq
108 - go install example.com/tool@v1.2.3
109```
110
111| Constraint | Value |
112|---|---|
113| Maximum entries | 100 |
114| Empty commands | Rejected |
115| Maximum size | 64 KiB after trimming |
116| Line endings | One line; `CR`/`LF` are rejected |
117| Shell | Each command runs through `/bin/sh -c` |
118
119Chain commands with `&&` rather than using multiple lines:
120
121```yaml
122run:
123 - apt-get update && apt-get install -y --no-install-recommends git make
124```
125
126`run` entries are rendered as Dockerfile exec-form instructions:
127
128```dockerfile
129RUN ["/bin/sh", "-c", "apt-get update && apt-get install -y --no-install-recommends git make"]
130```
131
132That keeps the first word of a command from being interpreted as a Dockerfile
133build flag such as `--network=host`.
134
135## What the definition can and cannot express
136
137The format deliberately supports only `from`, `env`, and `run`. It does not
138support:
139
140- `COPY`, `ADD`, or a build context from the repository
141- multi-stage builds
142- `ARG`
143- `WORKDIR`, `USER`, `ENTRYPOINT`, `CMD`, `HEALTHCHECK`, or `SHELL`
144- build secrets or host mounts
145
146The runner controls the job's working directory (`/workspace`), user, entrypoint,
147and mounts. The image supplies the toolchain and the shell.
148
149The image build uses the runtime's default network. `--container-network` applies
150to the job container, not to the image build. The builder has no host mounts and
151no build secrets from Vole.
152
153## Execution and caching
154
155The runner renders the definition to a Dockerfile:
156
157```dockerfile
158FROM <from>
159ENV KEY="value"
160RUN ["/bin/sh", "-c", "<command>"]
161...
162```
163
164It builds that image with the configured OCI runtime and tags it by the SHA-256 of
165the exact definition file. A later job with the same definition reuses the tag.
166`--container-pull always` rebuilds a custom image even when the tag exists.
167
168An image definition is code: its build runs on the runner through the OCI builder,
169so approving a contributor tip that changes a definition also approves that build.
170Use rootless Podman where possible.
171
172The resulting job image must contain `/bin/sh` and a POSIX `sleep`, because Vole
173runs each step with `/bin/sh -c` and keeps the container alive between steps. If
174`run` is non-empty, the base image used for `from` must also provide `/bin/sh`,
175because build commands are rendered that way.
176
177Nothing a job writes inside the container survives the run, except what it puts in
178the cache: the runner mounts a directory at `/cache` and sets no variables for it,
179so `env` is where a definition opts in. Point the toolchain's own variables at it
180and its downloads are reused between jobs:
181
182```yaml
183env:
184 GOMODCACHE: "/cache/go-mod"
185 GOCACHE: "/cache/go-build"
186```
187
188A job may also set its own `env`, which is applied after the image's and wins; it
189is the way to point at `/cache` when the image is a registry reference rather than a
190definition. `/tmp` is a memory-backed tmpfs and `HOME` points there for everything
191else; the XDG convention (`XDG_CACHE_HOME: /cache/xdg`) covers tools that follow it.
192See [Runners § Caching](../runner.md#caching).
193Check that anything calling `getpwuid` has a passwd entry for the uid the job runs
194as — see [Runners § How a job runs](../runner.md#how-a-job-runs).
195
196## Validation and pinning
197
198- `version` must be `1`.
199- Unknown keys are errors.
200- The definition must live directly under `.vole/images/`, not in a subdirectory.
201- Both `.yaml` and `.yml` are accepted, but not two files for the same name.
202- Every definition is parsed at push time, even if unreferenced.
203- The exact definition text and its digest are pinned with each run.
204- `--container-pull always` rebuilds instead of reusing the digest tag.
205
206## Complete example
207
208```yaml
209# .vole/images/release-toolchain.yaml
210version: 1
211from: golang:1.27-bookworm@sha256:...
212env:
213 CGO_ENABLED: "0"
214 SOURCE_DATE_EPOCH: "0"
215run:
216 - apt-get update && apt-get install -y --no-install-recommends git make jq
217 - go install example.com/release-tool@v1.4.0
218```
219
220```yaml
221# .vole/workflows/release.yaml
222version: 1
223on:
224 push:
225 tags: ["v*"]
226jobs:
227 release:
228 runs-on: [linux, amd64]
229 image-file: release-toolchain
230 steps:
231 - name: build
232 run: make dist
233 artifacts:
234 - path: dist/*
235 release: true
236```
237