v0.26.0 df1db36

ci.md RawHistoryFolder

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.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 42

↑↓ moveenter openesc close