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 ];
}