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.

Require an image for every CI job

70b702649b875d841e294f5a085ca784d43e5bc4 · Keenan Nemetz · 15d ago · parent 7da9111e

Require an image for every CI job

Runners now require an OCI runtime, and each workflow job must name either a registry image or an image-file definition under .vole/images. Definitions are validated at push time, pinned with the run, built locally by the runner, and cached by definition digest. Records and the run page carry the image and definition digest.

Split the CI guide into workflows and runners, and add reference pages for workflow and image definition fields.

docs/reference/workflow-reference.md +293

@@ -0,0 +1,293 @@
1 # Workflow reference
2
3 This page lists every field Vole accepts in `.vole/workflows/*.yaml`, with its
4 defaults and limits. For a task-oriented introduction, see [Workflows](../workflows.md).
5 For `.vole/images` definitions, see [Image reference](image-reference.md).
6
7 Unknown keys are rejected. A workflow is validated when it is pushed and again by
8 `vole workflow check`, so a typo fails before a job is queued.
9
10 ## File location and limits
11
12 | Item | Value |
13 |---|---|
14 | Location | Directly under `.vole/workflows/`; subdirectories are rejected |
15 | Extension | `.yaml` or `.yml` |
16 | Maximum file size | 256 KiB |
17 | Schema version | `1` |
18 | Maximum jobs per workflow | 50 |
19 | Maximum steps per job | 100 |
20 | Maximum artifact declarations per job | 32 |
21 | Maximum `runs-on` labels per job | 8 |
22 | Maximum step command size | 64 KiB |
23 | Default step timeout | 10 minutes |
24 | Maximum step timeout | 1 hour |
25
26 ## Top-level fields
27
28 | Field | Type | Required | Default | Meaning |
29 |---|---|---|---|---|
30 | `version` | integer | yes | — | Schema version. Must be `1`. |
31 | `on` | mapping | no | — | Trigger configuration. Only `on.push` is supported. |
32 | `on.push.branches` | list of strings | no | `["*"]` when neither `branches` nor `tags` is present | Branch patterns that trigger the workflow. |
33 | `on.push.tags` | list of strings | no | none | Tag patterns that trigger the workflow. |
34 | `jobs` | mapping | yes | — | One or more jobs, keyed by job ID. |
35
36 ### `version`
37
38 The only supported value is `1`:
39
40 ```yaml
41 version: 1
42 ```
43
44 ### `on.push.branches`
45
46 A list of branch patterns. The default depends on what else is present:
47
48 - Neither `branches` nor `tags`: the workflow runs on every branch.
49 - `branches` present: only matching branches trigger it.
50 - `tags` present without `branches`: the workflow runs only on matching tags.
51
52 Patterns use `path.Match` semantics with one special case: a lone `*` matches every
53 branch, including names containing `/`. Other patterns keep the one-segment rule,
54 so `release/*` does not match `release/1.0/hotfix`.
55
56 Patterns may contain letters, digits, `*`, `?`, `[`, `]`, `!`, `.`, `_`, `/` and
57 `-`. Empty patterns and patterns containing `..` are rejected.
58
59 ```yaml
60 on:
61 push:
62 branches: [main, "release/*"]
63 ```
64
65 An explicitly empty list means no branches trigger the workflow.
66
67 ### `on.push.tags`
68
69 A list of tag patterns. Tags have no default: a workflow runs on a tag only when
70 `tags:` is present and the tag matches.
71
72 ```yaml
73 on:
74 push:
75 tags: ["v*"]
76 ```
77
78 Patterns follow the same rules as branch patterns. A workflow with `tags` and no
79 `branches` runs on tags only. A workflow with both runs on matching branches and
80 matching tags.
81
82 ### `jobs`
83
84 A mapping of job IDs to job definitions. Job IDs must match:
85
86 ```text
87 ^[a-z][a-z0-9_-]{0,31}$
88 ```
89
90 That is 1–32 characters: lowercase letters, digits, `_` and `-`, starting with a
91 letter. At least one job is required.
92
93 ## Job fields
94
95 | Field | Type | Required | Default | Meaning |
96 |---|---|---|---|---|
97 | `image` | string | one of `image` / `image-file` | — | Registry image the job runs in. |
98 | `image-file` | string | one of `image` / `image-file` | — | Name of a definition under `.vole/images/`. |
99 | `runs-on` | string or list of strings | no | any runner | Runner labels the job requires. |
100 | `steps` | list | yes | — | Commands the job runs. At least one is required. |
101 | `artifacts` | list | no | none | Files the job publishes. |
102 | `pages` | mapping | no | none | Directory published as the repository's website. |
103
104 Exactly one of `image` and `image-file` must be present. Declaring both, or
105 neither, is an error.
106
107 ### `image`
108
109 An OCI image reference used exactly as written:
110
111 ```yaml
112 jobs:
113 build:
114 image: golang:1.27-bookworm@sha256:...
115 ```
116
117 The runner pulls and runs this image. Pin it by digest when reproducibility
118 matters; a mutable tag can change between runs.
119
120 References are limited to 255 bytes and must start with a letter or digit. They may
121 contain letters, digits, `.`, `_`, `/`, `:`, `@`, `+`, `~` and `-`. A leading `-`,
122 `..`, `://`, or a `file:` prefix is rejected. `file:` is reserved for
123 `image-file:`.
124
125 ### `image-file`
126
127 The name of a definition under `.vole/images/`:
128
129 ```yaml
130 jobs:
131 build:
132 image-file: go
133 ```
134
135 `image-file: go` resolves `.vole/images/go.yaml`. The `.yaml` or `.yml` extension
136 is optional in the reference; `image-file: go.yaml` is also accepted.
137
138 Names are 1–64 characters: lowercase letters, digits, `.`, `_` and `-`, starting
139 with a letter or digit. A definition must live directly under `.vole/images/`, not
140 in a subdirectory. Two files for the same name (`go.yaml` and `go.yml`) are
141 rejected as ambiguous.
142
143 The definition is validated and pinned when the run is queued. See
144 [Image reference](image-reference.md) for its fields and limits.
145
146 ### `runs-on`
147
148 A single label or a list of labels:
149
150 ```yaml
151 runs-on: linux
152 runs-on: [linux, arm64]
153 ```
154
155 A runner must carry every listed label to receive the job. An absent or empty
156 `runs-on` means any runner may take the job. Duplicate labels are ignored; at most
157 8 labels may be declared. Each label must match:
158
159 ```text
160 ^[a-z0-9][a-z0-9._-]{0,31}$
161 ```
162
163 That is 1–32 characters: lowercase letters, digits, `.`, `_` and `-`, starting
164 with a letter or digit.
165
166 See [Runners § Start a runner](../runner.md#start-a-runner) for how a machine
167 advertises labels.
168
169 ### `steps`
170
171 A non-empty list of shell steps, at most 100. Steps run in order. A step that exits
172 non-zero stops the job and becomes the job's exit code.
173
174 Steps run inside the job's image, in the disposable checkout. They share the
175 container and filesystem with the other steps in the same job.
176
177 #### Step fields
178
179 | Field | Type | Required | Default | Meaning |
180 |---|---|---|---|---|
181 | `name` | string | no | first line of `run` | Display name in the log. |
182 | `run` | string | yes | — | Shell command executed with `/bin/sh -c`. |
183 | `timeout` | duration string | no | `10m` | Maximum time for this step. |
184
185 ```yaml
186 steps:
187 - name: test
188 run: go test ./...
189 timeout: 20m
190 ```
191
192 `run` is trimmed and must not be empty. The maximum size is 64 KiB. `name` is
193 trimmed; when omitted it is derived from the first line of `run`, shortened to 60
194 characters.
195
196 `timeout` uses Go duration syntax (`90s`, `10m`, `1h`). It must be positive and no
197 more than `1h`. When a step times out, the job fails and its container is stopped.
198
199 ### `artifacts`
200
201 A list of file patterns to publish when the steps succeed. At most 32 declarations
202 are allowed.
203
204 | Field | Type | Required | Default | Meaning |
205 |---|---|---|---|---|
206 | `path` | glob string | yes | — | Files to publish, relative to the checkout. |
207 | `release` | boolean | no | `false` | Also attach the matches to the tag's release. |
208
209 ```yaml
210 artifacts:
211 - path: dist/*
212 - path: dist/checksums.txt
213 release: true
214 ```
215
216 `path` rules:
217
218 - Must be relative to the checkout; absolute paths and `..` segments are rejected.
219 - Maximum 256 bytes.
220 - Must name files, not a directory: a trailing `/` is rejected.
221 - Uses one-segment glob semantics. `dist/*` matches files directly in `dist/` but
222 not files in `dist/sub/`.
223 - `**` is rejected; use `dist/*` or declare more patterns.
224 - A pattern that matches nothing fails the job.
225 - Two matches with the same base name are refused because they would publish under
226 the same download name.
227 - `.git` is never published; symlinks and non-regular files are skipped.
228
229 `release: true` requires the workflow to declare `on.push.tags`. The job must run
230 for an annotated tag; a branch run or a lightweight tag cannot publish a release.
231 Release artifacts are attached to the tag's release in addition to being run
232 artifacts. See [Releases](../releases.md).
233
234 ### `pages`
235
236 Publishes one directory as the repository's website.
237
238 | Field | Type | Required | Default | Meaning |
239 |---|---|---|---|---|
240 | `path` | directory string | yes | — | Directory to publish, relative to the checkout. |
241
242 ```yaml
243 pages:
244 path: site/
245 ```
246
247 `path` must be relative, at most 256 bytes, and must not climb out of the
248 checkout with a `..` path segment or contain glob characters (`*`, `?`, `[`). A trailing `/` is accepted and trimmed. The directory
249 is published after the steps pass, using the same rules as
250 `vole pages deploy`.
251
252 Only one job in a workflow may declare `pages`. The target branch is set by the
253 instance (`pages_ref`), not by the workflow. The deploy is refused if the run is no
254 longer the newest commit on its branch. See [Workflows § Publish a website](../workflows.md#publish-a-website).
255
256 ## Validation and pinning
257
258 - The whole file is validated before a push is accepted.
259 - Unknown keys are errors; use the field names on this page.
260 - `version` must be `1`.
261 - The commit, workflow blob, and image definition are pinned when a run is queued.
262 Later edits do not change that run.
263 - `vole workflow check` and `vole workflow run` use the same validation as a push.
264 A local run ignores `on.push`, `runs-on`, and the image.
265
266 ## Complete example
267
268 ```yaml
269 version: 1
270 on:
271 push:
272 branches: [main, "release/*"]
273 tags: ["v*"]
274 jobs:
275 test:
276 runs-on: [linux, arm64]
277 image: golang:1.27-bookworm@sha256:...
278 steps:
279 - name: unit tests
280 run: go test ./...
281 timeout: 20m
282 artifacts:
283 - path: coverage/*
284 release:
285 runs-on: linux
286 image-file: release-toolchain
287 steps:
288 - name: build
289 run: make dist
290 artifacts:
291 - path: dist/*
292 release: true
293 ```