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/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

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

Add event, schedule and manual workflow triggers

eb07ff5696e0d83201215966e3ea1e6a24467581 · Keenan Nemetz · 8d ago · parent 1cde8b9e

Add event, schedule and manual workflow triggers

Workflows can now react to change requests, issues, comments, cron
schedules and manual runs, and a push trigger can filter by the paths it
changed. Branch and tag patterns gain ! exclusion.

Event runs are pinned with a JSON payload and the runner exposes it as
VOLE_EVENT, VOLE_EVENT_ACTION and VOLE_EVENT_PATH. Change-request runs
check out the base tip and carry the head and changed files, so an event
never executes an unapproved contributor commit.

Workflow dispatch resolves typed inputs and is available from the
workflows page and `vole workflow dispatch`. Deduplication now includes
an occurrence so the same commit can run for a later event or schedule
slot while a push remains idempotent.

Part of: #138

docs/reference/workflow-reference.md +191−14

@@ -25,6 +25,10 @@ Unknown keys are rejected. A workflow is validated when it is pushed and again b
25 25 | Maximum step command size | 64 KiB |
26 26 | Maximum display name | 80 bytes |
27 27 | Maximum description | 500 bytes |
28 | Maximum path filters | 20 per list |
29 | Maximum schedules | 5 |
30 | Maximum manual inputs | 10 |
31 | Maximum event payload | 64 KiB |
28 32 | Default step timeout | 10 minutes |
29 33 | Maximum step timeout | 1 hour |
30 34
@@ -35,9 +39,16 @@ Unknown keys are rejected. A workflow is validated when it is pushed and again b
35 39 | `version` | integer | yes | — | Schema version. Must be `1`. |
36 40 | `name` | string | no | the workflow file's base name | Display name on the workflows and run pages. |
37 41 | `description` | string | no | none | One-line summary of what the workflow is for. |
38 | `on` | mapping | no | — | Trigger configuration. Only `on.push` is supported. |
39 | `on.push.branches` | list of strings | no | `["*"]` when neither `branches` nor `tags` is present | Branch patterns that trigger the workflow. |
42 | `on` | mapping | no | — | Trigger configuration. |
43 | `on.push.branches` | list of strings | no | `["*"]` for a workflow with no other trigger | Branch patterns that trigger the workflow. |
40 44 | `on.push.tags` | list of strings | no | none | Tag patterns that trigger the workflow. |
45 | `on.push.paths` | list of strings | no | none | Path patterns a push must touch. |
46 | `on.push.paths-ignore` | list of strings | no | none | Path patterns a push must not change. |
47 | `on.change-request` | mapping or empty | no | none | Change-request actions that trigger the workflow. |
48 | `on.issue` | mapping or empty | no | none | Issue actions that trigger the workflow. |
49 | `on.comment` | mapping or empty | no | none | Comment actions that trigger the workflow. |
50 | `on.schedule` | list of mappings | no | none | Cron schedules, in UTC. |
51 | `on.workflow-dispatch` | mapping or empty | no | none | A manual run, optionally with typed inputs. |
41 52 | `jobs` | mapping | yes | — | One or more jobs, keyed by job ID. |
42 53
43 54 ### `version`
@@ -80,9 +91,13 @@ optional; an absent description shows nothing.
80 91
81 92 A list of branch patterns. The default depends on what else is present:
82 93
83 - Neither `branches` nor `tags`: the workflow runs on every branch.
94 - A workflow with no `on` trigger at all is an ordinary push ci and runs on every
95 branch.
84 96 - `branches` present: only matching branches trigger it.
85 97 - `tags` present without `branches`: the workflow runs only on matching tags.
98 - A workflow with only event triggers (`change_request`, `issue`, `comment`,
99 `schedule`, `workflow_dispatch`) does not run on a branch push.
100 - `push:` with neither `branches` nor `tags` runs on every branch.
86 101
87 102 Patterns use `path.Match` semantics with one special case: a lone `*` matches every
88 103 branch, including names containing `/`. Other patterns keep the one-segment rule,
@@ -91,12 +106,21 @@ so `release/*` does not match `release/1.0/hotfix`.
91 106 Patterns may contain letters, digits, `*`, `?`, `[`, `]`, `!`, `.`, `_`, `/` and
92 107 `-`. Empty patterns and patterns containing `..` are rejected.
93 108
109 A leading `!` excludes what an earlier pattern included. The last matching pattern
110 wins, so `["*", "!main"]` runs everywhere except `main`:
111
94 112 ```yaml
95 113 on:
96 114 push:
97 115 branches: [main, "release/*"]
98 116 ```
99 117
118 ```yaml
119 on:
120 push:
121 branches: ["*", "!main"]
122 ```
123
100 124 An explicitly empty list means no branches trigger the workflow.
101 125
102 126 ### `on.push.tags`
@@ -110,9 +134,163 @@ on:
110 134 tags: ["v*"]
111 135 ```
112 136
113 Patterns follow the same rules as branch patterns. A workflow with `tags` and no
114 `branches` runs on tags only. A workflow with both runs on matching branches and
115 matching tags.
137 Patterns follow the same rules as branch patterns, including `!` exclusion. A
138 workflow with `tags` and no `branches` runs on tags only. A workflow with both runs
139 on matching branches and matching tags.
140
141 ### `on.push.paths`
142
143 A push runs only when at least one changed path matches one of these patterns.
144 Patterns are relative to the repository root. `*` stays inside one path segment;
145 `**` spans zero or more segments, so `docs/**` covers `docs/` and everything under
146 it. At most 20 patterns may be declared.
147
148 ```yaml
149 on:
150 push:
151 paths: ["src/**", "cmd/**", "go.mod"]
152 ```
153
154 An empty pattern, an absolute path, or a pattern containing `..` is rejected. A
155 push that changes no files does not match a workflow with a path filter.
156
157 ### `on.push.paths-ignore`
158
159 Paths that do not trigger the workflow. An ignored path is removed before the
160 allow list is consulted, so an ignored file cannot make a workflow run:
161
162 ```yaml
163 on:
164 push:
165 paths-ignore: ["docs/**", "**/*.md"]
166 ```
167
168 `paths` and `paths-ignore` may be combined. When every changed path is ignored,
169 nothing runs. Both filters are evaluated against the range the push changed; a new
170 branch or tag has no previous tree, so every file counts as changed.
171
172 ### `on.change-request`
173
174 Runs when a change request changes. The run is checked out at the request's base
175 branch tip, not at the proposed head: an event run must not be a way to execute an
176 unapproved contributor commit. The proposed head and the changed files are in the
177 event payload.
178
179 ```yaml
180 on:
181 change-request:
182 types: [opened, updated, ready]
183 ```
184
185 | Action | Meaning |
186 |---|---|
187 | `opened` | A request was created. |
188 | `updated` | Its head, base, title, description, or followed branch changed. |
189 | `ready` | The required approvals for the exact base and head were reached. |
190 | `closed` | It was closed without landing. |
191 | `merged` | It landed. |
192
193 The default is `[opened, updated, ready]`. An empty value means the default:
194 `change-request:` and `change-request: {}` are the same.
195
196 ### `on.issue`
197
198 Runs when an issue changes, at the default branch tip.
199
200 ```yaml
201 on:
202 issue:
203 types: [opened, closed]
204 ```
205
206 Actions are `opened`, `edited`, `closed`, and `reopened`. The default is `[opened]`.
207 An empty value means the default.
208
209 ### `on.comment`
210
211 Runs when a comment on an issue or a change request is created, edited, or deleted.
212 The payload names the comment and the issue or change request it belongs to.
213
214 ```yaml
215 on:
216 comment:
217 types: [created]
218 ```
219
220 Actions are `created`, `edited`, and `deleted`. The default is `[created]`. An
221 empty value means the default.
222
223 ### `on.schedule`
224
225 Cron schedules in UTC. A schedule queues the workflow at the default branch tip.
226 The field syntax is five fields — minute, hour, day of month, month, day of week —
227 with `*`, lists, ranges, and a step on `*` or a range. Names and `@shorthands` are
228 not accepted.
229
230 ```yaml
231 on:
232 schedule:
233 - cron: "0 3 * * 1-5"
234 ```
235
236 At most 5 schedules may be declared. The run is queued once per matching minute;
237 a server that was not running for a slot does not replay it later.
238
239 ### `on.workflow-dispatch`
240
241 Marks a workflow as runnable by hand. The browser shows a **Run workflow** button
242 on the workflows page, and the CLI has `vole workflow dispatch`.
243
244 ```yaml
245 on:
246 workflow-dispatch:
247 inputs:
248 environment:
249 description: Where to deploy
250 type: choice
251 required: true
252 default: staging
253 options: [staging, production]
254 dry-run:
255 type: boolean
256 default: "true"
257 ```
258
259 | Input field | Meaning |
260 |---|---|
261 | `description` | One line shown beside the field. |
262 | `type` | `string`, `boolean`, `number`, or `choice`. Default `string`. |
263 | `required` | The run is refused when the input has no value and no default. |
264 | `default` | Value used when the input is omitted. |
265 | `options` | The allowed values for `choice`. |
266
267 At most 10 inputs may be declared. A value must be one line and at most 4 KiB.
268 `choice` inputs need at least one option, and the default must be one of them.
269 A manual run is available to maintainers and instance admins, and the selected
270 branch must exist.
271
272 ### Event data available to steps
273
274 Every run has a `trigger_kind` (`push`, `change_request`, `issue`, `comment`,
275 `schedule`, or `workflow_dispatch`) and an action. A run started by a non-push
276 trigger also gets three variables:
277
278 | Variable | Value |
279 |---|---|
280 | `VOLE_EVENT` | The trigger kind, such as `comment`. |
281 | `VOLE_EVENT_ACTION` | The action, such as `created`. |
282 | `VOLE_EVENT_PATH` | Path to a JSON file, `/run/vole/event.json`. |
283
284 The JSON is pinned when the run is queued. It is data: read it with `jq` or a
285 program, never by interpolating it into a shell command. Common fields are
286 `event`, `action`, `repository`, `ref`, `branch`, `commit`, `sender`, and for a
287 change request `base_sha`, `head_sha`, and `changed_files`. The entity is under
288 `issue`, `change_request`, or `comment`; a manual run puts its resolved values
289 under `inputs`. Long bodies are clipped at 16 KiB and the payload marks that with
290 `body_truncated`.
291
292 These variables are set by the runner and cannot be replaced by a workflow's
293 `env:`, the same rule as `CI` and `HOME`.
116 294
117 295 ### `jobs`
118 296
@@ -355,12 +533,10 @@ longer the newest commit on its branch. See [Workflows § Publish a website](../
355 533
356 534 ## What a workflow cannot express
357 535
358 The format deliberately supports only push triggers and jobs of shell steps. It
359 does not support:
536 The format deliberately supports push and event triggers with jobs of shell steps.
537 It does not support:
360 538
361 539 - a job graph: there is no `needs`, no job outputs, and no shared artifacts between jobs
362 - non-push triggers: no `on.change_request`, `on.schedule`, or `on.workflow_dispatch`
363 - path filters (`paths`, `paths-ignore`) or negated branch patterns (`!main`)
364 540 - a build matrix or per-step conditions (`strategy`, `if`, `continue-on-error`)
365 541 - secrets, secret masking, or an audit trail for secret use
366 542 - expressions or contexts (`${{ }}`); nothing outside the shell is interpolated
@@ -371,11 +547,12 @@ does not support:
371 547 - reusable workflows or composite actions (`uses:`); shell in an image is the
372 548 reuse mechanism
373 549 - environments, deployment approvals, per-job permissions, or OIDC
550 - event payloads larger than 64 KiB; a long body is clipped in the pinned event
374 551
375 Change-request results are produced automatically by the server for a commit
376 under review; they are not an `on:` trigger a workflow can declare. A local
377 `vole workflow run` ignores `on.push` and `runs-on`, publishes no artifacts, and
378 deploys no site.
552 Combined results for a commit under review are still produced automatically by the
553 server; `on.change-request` is the event trigger, not the combined-result scheduler.
554 A local `vole workflow run` ignores triggers and `runs-on`, publishes no artifacts,
555 deploys no site, and has no event payload.
379 556
380 557 ## Validation and pinning
381 558