88 lines
5.6 KiB
Markdown
88 lines
5.6 KiB
Markdown
# CI: Gitea Actions
|
|
|
|
**Docs:** [README](../README.md) · [SPEC](../SPEC.md) · [ARCHITECTURE](ARCHITECTURE.md) · [RESEARCH](RESEARCH.md) · [COMPARISON](../COMPARISON.md) · [AGENTS](../AGENTS.md) · [CHANGELOG](../CHANGELOG.md) · [CI](CI.md)
|
|
|
|
The workflow is [`.gitea/workflows/ci.yml`](../.gitea/workflows/ci.yml). It needs two kinds of
|
|
runner, because the thing doos tests is the thing most CI containers are built to prevent: a
|
|
process creating its own user, mount and pid namespaces and an overlayfs mount.
|
|
|
|
## What runs where
|
|
|
|
| Job | Runner | Needs | Proves |
|
|
|---|---|---|---|
|
|
| `build` | any `docker://` runner (label `ubuntu-latest`) | a C++20 toolchain and CMake | the binary still compiles with `-Werror` and the documentation set is still fully cross-linked |
|
|
| `valgrind` | any `docker://` runner (label `ubuntu-latest`) | the above, plus `valgrind` | no new memory error or leak in doos's own code (see [valgrind/README.md](../valgrind/README.md)); this still gives a real answer even when the container's own AppArmor/seccomp policy blocks the user namespace doos tries to create, because `scripts/valgrind.sh` only fails on what valgrind itself reports, never on doos's own exit code |
|
|
| `test` | self-hosted, host mode, label `doos-host` | see below | the real end-to-end suite (`tests/run.sh`, currently 88 checks): real overlayfs, real namespaces, real downloads, real cgroup v2 limits |
|
|
| `audit` | self-hosted, host mode, label `doos-host` | see below | the named CVE regression set in [`audit/`](../audit/README.md) against the binary this run just built |
|
|
|
|
`build` and `valgrind` run in an ephemeral Docker-mode act_runner container and need nothing this
|
|
repository does not already ask of any build machine. `test` and `audit` need a real Linux host
|
|
(or VM) that act_runner reaches in *host mode* (a plain label, not a `docker://` one), because the
|
|
things under test are precisely the things a container runtime's own default policy restricts: an
|
|
unprivileged user namespace that creates an overlayfs mount, a systemd user manager with cgroup v2
|
|
delegated to it, and (on Ubuntu 24.04+) an AppArmor profile that permits user namespaces for this
|
|
one binary path. Running those two jobs inside another container would either need that container
|
|
privileged (defeating the point of isolating the runner) or would silently test less than it claims
|
|
to, the same vacuous-pass risk `review2.md` section 2 warns about for the audit script's own design.
|
|
|
|
## One-time host runner setup (by whoever administers the runner, not by the workflow)
|
|
|
|
The workflow never runs anything with `sudo`, on purpose (same rule as everywhere else in this
|
|
project: AppArmor and system changes are requested from a human, never done by an agent or a CI
|
|
job on its own). Before registering the `doos-host` runner:
|
|
|
|
```
|
|
sudo apt-get install -y build-essential cmake slirp4netns passt gnupg uidmap curl tar
|
|
# /etc/subuid and /etc/subgid must list the runner's own user; uidmap's postinst usually does this.
|
|
grep "^$(whoami):" /etc/subuid /etc/subgid
|
|
|
|
# cgroup v2 must be delegated to this user's systemd manager (loginctl enable-linger helps it
|
|
# survive without an interactive session):
|
|
loginctl enable-linger "$(whoami)"
|
|
cat /sys/fs/cgroup/user.slice/user-$(id -u).slice/user@$(id -u).service/cgroup.controllers
|
|
|
|
# Build doos once at the exact path the runner will use, then install its AppArmor profile
|
|
# (needed on Ubuntu 24.04+; see README's Troubleshooting table for the symptom this fixes):
|
|
cmake -S . -B build && cmake --build build
|
|
build/doos apparmor | sudo tee /etc/apparmor.d/doos-runner >/dev/null
|
|
sudo apparmor_parser -r /etc/apparmor.d/doos-runner
|
|
```
|
|
|
|
Then register the runner itself (see
|
|
[Gitea's act_runner docs](https://docs.gitea.com/usage/actions/act-runner) for the current command
|
|
and token source):
|
|
|
|
```
|
|
./act_runner register --instance https://<your-gitea> --token <runner-token> \
|
|
--name doos-host --labels doos-host
|
|
./act_runner daemon
|
|
```
|
|
|
|
A `docker://`-labelled runner for `build` and `valgrind` needs no special setup; any act_runner in
|
|
its default Docker mode works (the Gitea docs' own suggested registration labels, such as
|
|
`ubuntu-latest:docker://gitea/runner-images:ubuntu-latest`, are enough).
|
|
|
|
## Known Gitea Actions gaps versus GitHub Actions (checked against the 1.25 docs)
|
|
|
|
- **`timeout-minutes` and `concurrency` are parsed but ignored.** The workflow still sets
|
|
`timeout-minutes` on every job for readability and for anyone who later runs the same file
|
|
under real GitHub Actions, but the actual, enforced cap in each job is a shell-level
|
|
`timeout <seconds>` wrapped around the one command that matters, consistent with this project's
|
|
own rule that every automated process gets a hard, enforced ceiling, not a cap that only works
|
|
if the runner happens to honor it.
|
|
- **`permissions` support is version-dependent** and GitHub-only scopes (`checks`, `id-token`,
|
|
`security-events`, `pages`, ...) are not supported at all. The workflow does not rely on it.
|
|
- **`uses: actions/checkout@v4`** is resolved the same way GitHub Actions resolves it (Gitea
|
|
Actions proxies to GitHub by default); an instance configured without internet access to
|
|
GitHub needs `https://gitea.com/actions/checkout` instead, or a plain `git clone` step.
|
|
|
|
## Running it without Gitea
|
|
|
|
Every job is one or two `make` targets with a `timeout` in front; none of it depends on Gitea
|
|
Actions syntax beyond `on`/`jobs`/`runs-on`/`steps`, so the same file works, unmodified, as a
|
|
GitHub Actions workflow (just move it to `.github/workflows/`) with the one exception that
|
|
`timeout-minutes` would then actually be enforced by the platform instead of being a label only
|
|
(harmless either way).
|
|
|
|
Back to [README](../README.md), [AGENTS](../AGENTS.md), [SPEC](../SPEC.md).
|