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 | ||