Why
The workflow format is deliberately small: ci/workflow.go defines only version, on.push (branches/tags), and jobs made of shell steps with an image, runner labels, env, artifacts, and pages. That keeps the push-time checker small and the queue payload bounded, but it also means the format cannot describe several things ordinary CI needs. This issue is the single place to record the gaps, decide which are intended non-goals, and link the work that closes them.
The immediate user-visible gap is that a workflow has no name or description. The workflows page shows the file path (.vole/workflows/verify.yaml) and job IDs, so a reader has to open the YAML comments to learn what a workflow is for.
Current shape
- Schema:
ci/workflow.go; reference:docs/reference/workflow-reference.md. - Docs:
docs/workflows.md; UI:server/web/workflows.go,server/web/templates/workflows.html. - Each job is queued as its own run (
server/ci.go), so CI jobs are independent and unordered. - Only a push is a trigger; change requests get combined-result runs automatically.
- The runner’s
/cache, network, and resource limits arevole runnerflags, not workflow fields.
Scope
1. Identity and description
- Add top-level
name:anddescription:; show them on the workflows page and run pages. - Add a job
name:for display, and optionally a jobdescription:. - Add a “What a workflow cannot express” section to
docs/reference/workflow-reference.md, matching the existing section indocs/reference/image-reference.md. - State in
docs/workflows.mdthat CI jobs are independent and unordered (only a local run uses declaration order).
2. Triggers
-
on.change_request(opened/updated/ready), with the base commit and changed files available to steps. -
on.schedule(cron). -
on.workflow_dispatchwith typed inputs, plus a manual-run button and CLI command. -
on.push.pathsandpaths-ignore. - Negated branch/tag patterns (
!main), or document that they are not supported.
3. Job graph and execution
-
needs:with job-level dependencies and cycle detection. - Job
outputs:and step outputs, so a later job can consume a value. -
strategy.matrix, including fail-fast behavior. - Step
if:,continue-on-error, and a retry policy. - Job-level
timeout; today only steps are capped, at one hour each. - Concurrency groups and cancel-in-progress. A push now only cancels queued runs for the commit it replaced, and never stops a running job.
- Reusable workflows or composite steps (
uses:), or an explicit decision that shell in an image is the reuse mechanism. - Workflow-level
envand defaults (shell, working directory); step-levelenv,working-directory, andshell.
4. Inputs, state, and containers
- Secrets: a store, injection at job or step scope, masking in logs, and an audit trail. This is the biggest blocker for deploy and publish jobs.
- Expressions/contexts (
${{ }}) or a smaller documented interpolation syntax: rejected as a non-goal; the shell is the expression language and the event file is the context. - Service containers or sidecars, such as a database for tests.
- Artifact download between jobs, plus artifact names and a retention setting.
- Cache key, restore keys, and save policy.
/cacheis ambient today and keyed by repository, trust, and image. - Run summaries and annotations, so a job can report a result without a log read.
5. Deployment and policy
- Environments, protection rules, and approvals for deploys; a tag currently publishes automatically.
- Per-workflow or per-job permissions/tokens, and OIDC, instead of relying on the runner’s key.
- A way for a job to declare network and resource needs (
network: bridge, cpu/memory) instead of making them runner flags. - Failure notifications or webhooks.
6. Documentation and parity
- Document rerun, cancel, and attempt semantics on the workflow and run pages; queue behavior currently lives only in
docs/runner.md. - Document the local-run parity gaps in one place:
vole workflow runignoreson.push,runs-on, artifacts, and sites. - Link the five-attempt requeue rule from
docs/workflows.mdrather than only fromdocs/runner.md.
Acceptance criteria
- Every scope item above has a decision: adopt (with a sub-issue), defer (with a reason), or reject as a non-goal.
- Adopted items are split into sub-issues linked from this one, in priority order. Suggested first slice: secrets, service containers,
needs/outputs, and change-request/path triggers. - The cheap metadata item (
name/description) is either implemented or explicitly deferred. -
docs/reference/workflow-reference.mddocuments the current limits, including the absence ofneeds, secrets, matrix, and non-push triggers. - The workflows page shows a human name and description when the workflow declares them.
Related
- #11 hardened the runner trust boundary; secrets and service containers must preserve that model.
- #17 and #18 built the run metadata and log UI this would extend.
- #64 added combined-result runs for change requests; an
on.change_requesttrigger should reuse that path instead of adding a second scheduler.