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 start service containers beside it
c1929d2fceb5e9e65204d5eef907d0781b9a5391 · Keenan Nemetz · 5d ago · parent 1d06b008
docs/reference/workflow-reference.md +65−6
| @@ -411,6 +411,7 @@ letter. At least one job is required. | |||
| 411 | 411 | | `image-file` | string | one of `image` / `image-file` | — | Name of a definition under `.vole/images/`. | | |
| 412 | 412 | | `runs-on` | string or list of strings | no | any runner | Runner labels the job requires. | | |
| 413 | 413 | | `network` | `none` or `bridge` | no | the runner's setting | Whether the job's container has a network. | | |
| 414 | | `services` | mapping | no | none | Containers started beside the job, reached by name. | | ||
| 414 | 415 | | `secrets` | string or list of strings | no | none | Repository secrets the job reads, by name. Each name is also the variable a step finds it in. | | |
| 415 | 416 | | `acts-as` | account name | no | none | A bot account the job acts as, with a credential for that run. | | |
| 416 | 417 | | `env` | mapping | no | none | Environment every step of the job runs with. | | |
| @@ -554,6 +555,62 @@ A `vole workflow run` applies the same rule: the job's request wins over the | |||
| 554 | 555 | command line, and a `bridge` job is refused when the local run was started with | |
| 555 | 556 | `--container-network none`. | |
| 556 | 557 | ||
| 558 | ### `services` | ||
| 559 | |||
| 560 | Containers started beside the job, for the servers a test or a build talks to: | ||
| 561 | |||
| 562 | ```yaml | ||
| 563 | jobs: | ||
| 564 | test: | ||
| 565 | image: golang:1.27-bookworm | ||
| 566 | network: bridge | ||
| 567 | services: | ||
| 568 | db: | ||
| 569 | image: postgres:17 | ||
| 570 | env: | ||
| 571 | POSTGRES_PASSWORD: test | ||
| 572 | PGDATA: /tmp/pgdata | ||
| 573 | steps: | ||
| 574 | - run: | | ||
| 575 | DATABASE_URL=postgres://postgres:test@db:5432/postgres go test ./... | ||
| 576 | ``` | ||
| 577 | |||
| 578 | A service is a container, not a job: it has no steps, no checkout, no secrets, and | ||
| 579 | no host mount, and it runs the image's own command. The service's name is its | ||
| 580 | hostname on a private network the runner creates for the attempt. The job and its | ||
| 581 | services are the only members, so `db:5432` is the address a step uses and two | ||
| 582 | services may listen on the same port. | ||
| 583 | |||
| 584 | **A job with services must also declare `network: bridge`.** Without it the service | ||
| 585 | could only be reached by giving the job a network the workflow did not ask for, | ||
| 586 | which is the promise `network: none` exists to keep. A push that declares services | ||
| 587 | with `none` or with no `network:` is refused. A bridge job is already only leased to | ||
| 588 | a runner that advertises bridge, so no new runner capability is involved. | ||
| 589 | |||
| 590 | The runner starts the services after the job image is resolved and before the first | ||
| 591 | step. A service that is not running when the steps are about to start fails the job. | ||
| 592 | There is no health check: a step that needs a server to accept connections waits for | ||
| 593 | it, as `pg_isready` does in a postgres test. When the attempt fails, times out, or is | ||
| 594 | canceled, the last 256 KiB of each service's output is added to the log under | ||
| 595 | `=== service db ===`; a successful run does not carry it. The job stops first, then | ||
| 596 | the services, then the network. A runner killed mid-job leaves all three behind, and | ||
| 597 | its next start removes them by label. | ||
| 598 | |||
| 599 | | Constraint | Value | | ||
| 600 | |---|---| | ||
| 601 | | Maximum services per job | 3 | | ||
| 602 | | Service name | `^[a-z][a-z0-9-]{0,31}$`, and the hostname a step uses | | ||
| 603 | | Image | A registry reference, not `image-file:`. Pin it by digest for reproducibility. | | ||
| 604 | | Environment | At most 64 entries; the same name, value, and one-line rules as a job's `env` | | ||
| 605 | | Secrets | Not available to a service. A test credential is a literal in the workflow; a real one is for the job. | | ||
| 606 | | Isolation | The job's user, user namespace, capabilities, and resource limits; `/tmp` is a writable tmpfs | | ||
| 607 | |||
| 608 | The service image must run as the job's uid. A database image that expects to start | ||
| 609 | as root is not supported by this field; use an image that can run unprivileged, or | ||
| 610 | point its data directory at `/tmp` as the postgres example does. The resource flags | ||
| 611 | on `vole runner` apply to each container, so a job with services can use more than | ||
| 612 | one container's limit. | ||
| 613 | |||
| 557 | 614 | ### `env` | |
| 558 | 615 | ||
| 559 | 616 | Environment variables for every step of the job, on top of the image's own. Later | |
| @@ -874,7 +931,7 @@ It does not support: | |||
| 874 | 931 | in the workflow file; secrets are job-scoped and the instance holds the values | |
| 875 | 932 | - expressions or `${{ }}` contexts; the shell is the expression language and the | |
| 876 | 933 | event file is the context. See [Context and expressions](#context-and-expressions). | |
| 877 | - service containers, cache keys, or artifact downloads between jobs | ||
| 934 | - cache keys, or artifact downloads between jobs | ||
| 878 | 935 | - concurrency groups, or cancel-in-progress | |
| 879 | 936 | - workflow-level `env`, working directories, or shells; `env` is per job and every | |
| 880 | 937 | step runs through `/bin/sh -c` in the checkout | |
| @@ -887,17 +944,19 @@ Combined results for a commit under review are still produced automatically by t | |||
| 887 | 944 | server; `on.change-request` is the event trigger, not the combined-result scheduler. | |
| 888 | 945 | A local `vole workflow run` ignores triggers and `runs-on`, publishes no artifacts, | |
| 889 | 946 | deploys no site, and has no event payload. It applies a job's `network:` request, so a | |
| 890 | `bridge` job needs `--container-network bridge` here too. It reads the secrets its jobs declare from | ||
| 891 | the instance the checkout's remote names, and leaves the variables unset — with a | ||
| 892 | note — where it cannot. | ||
| 947 | `bridge` job needs `--container-network bridge` here too, and it starts the job's | ||
| 948 | services on the same kind of private network a runner would. It reads the secrets its | ||
| 949 | jobs declare from the instance the checkout's remote names, and leaves the variables | ||
| 950 | unset — with a note — where it cannot. | ||
| 893 | 951 | ||
| 894 | 952 | ## Validation and pinning | |
| 895 | 953 | ||
| 896 | 954 | - The whole file is validated before a push is accepted. | |
| 897 | 955 | - Unknown keys are errors; use the field names on this page. | |
| 898 | 956 | - `version` must be `1`. | |
| 899 | - The commit, workflow blob, image definition, display names, and descriptions are | ||
| 900 | pinned when a run is queued. Later edits do not change that run. | ||
| 957 | - The commit, workflow blob, image definition, display names, descriptions, steps, | ||
| 958 | environment, services, and artifact patterns are pinned when a run is queued. Later | ||
| 959 | edits do not change that run. | ||
| 901 | 960 | - `vole workflow check` and `vole workflow run` use the same validation as a push. | |
| 902 | 961 | A local run executes in the job's image and ignores `on.push` and `runs-on`; it does | |
| 903 | 962 | apply the job's `network:`, and refuses a `bridge` job when the run was started with | |