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.

Let a job budget its whole run

e7aa0785cb69ace8c1338cc0b924113ea52a7abb · Keenan Nemetz · 6d ago · parent 2bc0ae74

Let a job budget its whole run

A step was capped at an hour and a job was not capped at all, so a job of
several slow steps held a runner for as long as they took, with no number saying
what the job was allowed to spend. And one long step — a session, a soak test, a
slow suite — could not be expressed, because the only clock was per step and its
ceiling was an hour.

A job may now declare `timeout: 2h`: a wall clock its steps share, starting with
the first step. A step that declares its own timeout is cut short when the budget
ends first, and a step that declares none runs with whatever is left, so one long
step needs only the job's number. A budget spent before a step starts stops the
job there instead of running the step on its own cap.

The budget is optional, pinned with the run, and spent by a local run the same
way, so nothing changes for a workflow that does not declare one. The step
ceiling rises from one hour to four to make a single long step possible; the
default stays ten minutes. The image build is not charged to the budget — it has
its own cap, so a slow pull cannot eat the time the steps were given.

A step timeout longer than its job's budget is refused at push time: the budget
would end first, so the step could never use what it asked for.

Closes #161.

# Conflicts:
#	ci/agent/agent.go
#	cmd/vole/workflowrun.go
#	docs/reference/workflow-reference.md

docs/workflows.md +29−9

@@ -65,6 +65,24 @@ executes the selected jobs in that order.
65 65 can run anywhere. See [Runners § Start a runner](runner.md#start-a-runner) for what the
66 66 labels mean on the machine.
67 67
68 A job can budget its whole run instead of each step separately. `timeout:` on a job
69 is the clock its steps share, so one long step is one number to write:
70
71 ```yaml
72 jobs:
73 test:
74 image: golang:1.27-bookworm
75 timeout: 2h
76 steps:
77 - run: go test ./...
78 ```
79
80 A step with no timeout of its own runs with what is left of the budget, and a budget
81 that runs out stops the job at the next step. Without the field, each step keeps its
82 own cap and the job has no total. See
83 [Workflow reference § timeout](reference/workflow-reference.md#timeout), which
84 also says why the image build is not part of the budget.
85
68 86 A job's network is closed by default: the container gets whatever the runner can
69 87 offer, and a runner with no network is the normal case. `network: bridge` asks for
70 88 one, which a job that downloads dependencies needs, and only a runner that can
@@ -388,15 +406,17 @@ variables: the image's `env:` (or the step) decides whether `/cache` is used. Se
388 406
389 407 A local run still ignores triggers and `runs-on`, publishes no artifacts,
390 408 and deploys no site. It does apply the job's `network:` request, so a `bridge` job
391 needs `--container-network bridge` here too (the default). It sets `CI=true` and `VOLE_CI=1`, gives each step its
392 declared timeout, and reads no standard input. It reads the secrets its jobs declare
393 from the instance the checkout's remote names, with your own credential, so a job
394 that deploys behaves the same here as it does on a runner. Where it cannot — no
395 remote, or no value stored — the variable is unset and the note says which one. Jobs run in declaration order and
396 share the working tree, so a later job sees files an earlier one wrote; a pushed
397 run queues each job separately, starts it from a clean checkout, and has no
398 ordering between jobs. A local run is not an event, so it sets no `VOLE_EVENT*`
399 variables and has no event payload.
409 needs `--container-network bridge` here too (the default), and it spends the job's
410 `timeout:` the way a runner does. It sets `CI=true` and `VOLE_CI=1`, gives each step
411 whatever the job's budget and its own timeout leave it, and reads no standard input.
412 It reads the secrets its jobs declare from the instance the checkout's remote names,
413 with your own credential, so a job that deploys behaves the same here as it does on
414 a runner. Where it cannot — no remote, or no value stored — the variable is unset
415 and the note says which one. Jobs run in declaration order and share the working
416 tree, so a later job sees files an earlier one wrote; a pushed run queues each job
417 separately, starts it from a clean checkout, and has no ordering between jobs. A
418 local run is not an event, so it sets no `VOLE_EVENT*` variables and has no event
419 payload.
400 420
401 421 ## Artifacts
402 422