CI
ermite runs the .github/workflows/*.yml of a repository, like GitHub Actions. Each job shows as a check on the commit, the branch list and the merge request.
See also: events, OIDC, artifacts.
Runners
Jobs run on ermite-runner hosts: a Firecracker microVM per job when KVM is available, else a container.
ermite token create runner-1 --preset runner # register the runner with this token
ermite runner list # online or not
ermite runner remove <id>
- CI is on once a runner is registered. Before that, pushes make no run.
- The
runner preset can read the code and secrets of every repository. Use it only on runners you operate.
- A job goes to a runner that has every label of its
runs-on. A job no runner takes within 24 hours fails.
Control runs
ermite run list <repo>
ermite run view <repo> <id> [--log] [--summary]
ermite run watch <repo> <id>
ermite run cancel <repo> <id> # needs ci:write
ermite run rerun <repo> <id> [--failed]
The Actions tab of a repository shows the same. With failing_checks_block on (default), a merge waits for every check to pass. Turn it off with ermite repo edit <repo> --failing-checks-block=false.
Trust
A run is trusted (secrets, write token, OIDC) only when the owner caused it and the owner pushed the code it runs.
- ermite records who moved each branch and tag to its current commit. A ref with no record, or a record for another commit, is untrusted.
- An agent's push or merge request gets an untrusted run: no secrets, read-only token.
- The owner re-running or dispatching an agent's branch still gets an untrusted run.
- A job token starts no run (except
workflow_dispatch with actions: write).
Per-event rules are in ci-events.md.
Job token
Every job gets github.token (ermitegh_…). It reads the run's repository (even private) over Git and the REST subset below, writes nothing, and expires with the job. It is not listed in ermite token list.
Actions
ERMITE_OWNER/<repo> on this server wins over the same name on github.com. It resolves only if whoever pushed the run can read that repository; otherwise it answers repository not found.
- Other actions come from github.com (
git ls-remote, no credentials). If the server needs a proxy, set HTTPS_PROXY / NO_PROXY for ermite serve.
- The cache (
actions/cache, setup-* cache:) works. Trusted runs only restore entries saved by trusted runs.
REST API subset
Served at github.api_url (/-/github/api):
GET /repos/{owner}/{repo}
GET /repos/{owner}/{repo}/hash-algorithm
GET /repos/{owner}/{repo}/tarball[/{ref}]
GET /repos/{owner}/{repo}/pulls/{number}/files (for dorny/paths-filter; needs pull-requests: read)
Any other path is GitHub's 404, so an action that needs more fails as on a GitHub instance without that feature.
Concurrency
concurrency: works at workflow and job level, per repository, case-insensitive.
queue: single (default): one runs, one waits; a newer waiting entry cancels the older.
queue: max: up to 100 wait, first in first out.
cancel-in-progress also cancels the running one. It cannot be combined with queue: max.
- A held job shows as
pending.
Reusable workflows
jobs.<id>.uses accepts:
./.github/workflows/x.yml (same repository, same commit);
owner/repo/.github/workflows/x.yml@ref on this server, if the run's actor can read it;
- a public repository on github.com.
with:, secrets: (or secrets: inherit) and outputs work as on GitHub. Called jobs are named <caller> / <job>. Up to four levels deep. permissions can only be lowered.
Logs, summaries, annotations
- Logs:
$ERMITE_DATA_DIR/ci/logs. Summaries (GITHUB_STEP_SUMMARY): $ERMITE_DATA_DIR/ci/summaries. Both are removed with their run.
- Annotations (
::notice, ::warning, ::error) show on the run and job pages and in ermite run view.
- Retention:
ERMITE_CI_LOG_RETENTION (default 90 days).
Unsupported features
A workflow that uses a feature ermite does not support fails with not supported yet: <feature>, never silently.
source
1# CI
2
3ermite runs the `.github/workflows/*.yml` of a repository, like GitHub Actions. Each job shows as a check on the commit, the branch list and the merge request.
4
5See also: [events](ci-events.md), [OIDC](ci-oidc.md), [artifacts](ci-artifacts.md).
6
7## Runners
8
9Jobs run on [ermite-runner](https://github.com/bnema/ermite-runner) hosts: a Firecracker microVM per job when KVM is available, else a container.
10
11```sh
12ermite token create runner-1 --preset runner # register the runner with this token
13ermite runner list # online or not
14ermite runner remove <id>
15```
16
17- CI is on once a runner is registered. Before that, pushes make no run.
18- The `runner` preset can read the code and secrets of **every** repository. Use it only on runners you operate.
19- A job goes to a runner that has every label of its `runs-on`. A job no runner takes within 24 hours fails.
20
21## Control runs
22
23```sh
24ermite run list <repo>
25ermite run view <repo> <id> [--log] [--summary]
26ermite run watch <repo> <id>
27ermite run cancel <repo> <id> # needs ci:write
28ermite run rerun <repo> <id> [--failed]
29```
30
31The **Actions** tab of a repository shows the same. With `failing_checks_block` on (default), a merge waits for every check to pass. Turn it off with `ermite repo edit <repo> --failing-checks-block=false`.
32
33## Trust
34
35A run is **trusted** (secrets, write token, OIDC) only when the owner caused it **and** the owner pushed the code it runs.
36
37- ermite records who moved each branch and tag to its current commit. A ref with no record, or a record for another commit, is untrusted.
38- An agent's push or merge request gets an untrusted run: no secrets, read-only token.
39- The owner re-running or dispatching an agent's branch still gets an untrusted run.
40- A job token starts no run (except `workflow_dispatch` with `actions: write`).
41
42Per-event rules are in [ci-events.md](ci-events.md).
43
44## Job token
45
46Every job gets `github.token` (`ermitegh_…`). It reads the run's repository (even private) over Git and the REST subset below, writes nothing, and expires with the job. It is not listed in `ermite token list`.
47
48## Actions
49
50- `ERMITE_OWNER/<repo>` on this server wins over the same name on github.com. It resolves only if whoever pushed the run can read that repository; otherwise it answers `repository not found`.
51- Other actions come from github.com (`git ls-remote`, no credentials). If the server needs a proxy, set `HTTPS_PROXY` / `NO_PROXY` for `ermite serve`.
52- The cache (`actions/cache`, `setup-*` `cache:`) works. Trusted runs only restore entries saved by trusted runs.
53
54### REST API subset
55
56Served at `github.api_url` (`/-/github/api`):
57
58- `GET /repos/{owner}/{repo}`
59- `GET /repos/{owner}/{repo}/hash-algorithm`
60- `GET /repos/{owner}/{repo}/tarball[/{ref}]`
61- `GET /repos/{owner}/{repo}/pulls/{number}/files` (for `dorny/paths-filter`; needs `pull-requests: read`)
62
63Any other path is GitHub's `404`, so an action that needs more fails as on a GitHub instance without that feature.
64
65## Concurrency
66
67`concurrency:` works at workflow and job level, per repository, case-insensitive.
68
69- `queue: single` (default): one runs, one waits; a newer waiting entry cancels the older.
70- `queue: max`: up to 100 wait, first in first out.
71- `cancel-in-progress` also cancels the running one. It cannot be combined with `queue: max`.
72- A held job shows as `pending`.
73
74## Reusable workflows
75
76`jobs.<id>.uses` accepts:
77
78- `./.github/workflows/x.yml` (same repository, same commit);
79- `owner/repo/.github/workflows/x.yml@ref` on this server, if the run's actor can read it;
80- a public repository on github.com.
81
82`with:`, `secrets:` (or `secrets: inherit`) and `outputs` work as on GitHub. Called jobs are named `<caller> / <job>`. Up to four levels deep. `permissions` can only be lowered.
83
84## Logs, summaries, annotations
85
86- Logs: `$ERMITE_DATA_DIR/ci/logs`. Summaries (`GITHUB_STEP_SUMMARY`): `$ERMITE_DATA_DIR/ci/summaries`. Both are removed with their run.
87- Annotations (`::notice`, `::warning`, `::error`) show on the run and job pages and in `ermite run view`.
88- Retention: `ERMITE_CI_LOG_RETENTION` (default 90 days).
89
90## Unsupported features
91
92A workflow that uses a feature ermite does not support fails with `not supported yet: <feature>`, never silently.