ci
A Nix-native CI/CD system that speaks Tangled’s protocol: a knot-compatible
bridge for a soft-serve forge, a spindle-compatible runner, a minimal appview,
and ci, the engine that runs the same workflow on your machine and on the
runner. The design, and the reasons behind it, are in DESIGN.md;
work is tracked with bug ls (tracking issue eae4f87).
Layout
| Path | What |
|---|---|
cmd/ci |
The ci binary (engine commands and the three hosts); ci-result is a symlink to it |
internal/lex |
Go types for the lexicons, checked against the JSON by go test |
lexicons/ci |
Our lexicons, run.rtw.ci.*: workflow manifest, step result, gate, transition, run event |
lexicons/tangled |
Vendored Tangled lexicons (see its README) |
Development
devenv shell # Go toolchain, golangci-lint, just
go test ./...
nix build .#ci # ./result/bin/ci
To see the appview with something in it:
devenv up -d # bridge, runner and appview on 127.0.0.1:8475-8477
devenv tasks run ci:seed # pushes a demo commit; its run waits at "Deploy demo?"
# open http://127.0.0.1:8477 and sign in with the password "dev"
devenv processes logs runner # or: appview, bridge
devenv processes down
ci:seed creates a demo repo on a directory “forge” (.devenv/state/ci-dev) with a post-receive hook for the bridge, so a push goes through the real path: hook, bridge, runner, a gated run. Run it again for another run. Actions use plain bash, not devenv; the dev credentials (dev, an agent token for claude) are fixed strings and only for this. The first start downloads Go modules, so give it a minute.
License
MIT, see LICENSE.
Using the engine in another repo
Add the flake as a devenv input and put the package on PATH:
# devenv.yaml
inputs:
ci:
url: git+ssh://[email protected]/ci
# devenv.nix
{ pkgs, inputs, ... }: {
packages = [ inputs.ci.packages.${pkgs.stdenv.system}.ci ];
}