Skip to content

How CI works

Spindle is a small CI runner service. It watches the knot that hosts your repository. When you push, it runs the workflow files in .tangled/workflows/ on that commit. You can use Tangled’s hosted spindle or run your own.

# .tangled/workflows/test.yml
when:
- event: push
branch: main
engine: microvm
image: nixos
dependencies:
- go
steps:
- name: test
command: go test ./...

Writing workflows explains this file one part at a time.

push ──▶ pipeline ──┬──▶ workflow (test.yml) ──▶ step, step, step
└──▶ workflow (lint.yml) ──▶ step, step
  • One trigger event makes one pipeline.
  • Each workflow file that matches the event becomes a workflow in that pipeline. Workflows run in parallel, each in its own container or microVM.
  • A workflow is a list of steps that run in order. The first step that exits non-zero fails the workflow. The steps after it do not run.
you ──git push──▶ knot ──notifyEvent──▶ spindle ──▶ pipeline
  1. You push to your knot.
  2. The knot tells the repository’s spindle about the push. The spindle ignores refs that are not branches or tags, and pushes made with the skip-ci push option.
  3. The spindle reads the workflow files at the pushed commit and keeps those whose when block matches the event, branch or tag, and changed paths. If none match, nothing runs.
  4. Each matching workflow becomes a run in a pipeline. The repository’s Pipelines tab and the commit show its status and logs.

Behind this:

  • The repository’s org.tangled.repo.manifest record names its spindle. When you pick a spindle in Settings → Pipelines, the manifest changes, and that spindle starts to serve the repository.
  • The spindle watches the Jetstream for changes to repositories, collaborators, pull requests and patches. It reads the records themselves from the knot.
  • Pushes and manual runs reach the spindle as an org.tangled.event.notifyEvent call. Only the repository’s own knot can send a push. Pull request runs start from the pull request and patch records.
  • The spindle writes no records. Pipelines, statuses, logs, secrets and webhooks live in the spindle’s own database. The web app reads them with org.tangled.ci.* queries, and logs stream over a WebSocket.

Spindle has two execution backends, picked per-workflow with the engine field:

EngineRuns onUse it for
nixeryA fresh Docker or Podman container for each step, with the image built from your Nix packages by NixeryShort, stateless builds and tests.
microvmThe whole workflow inside its own microVM, with a choice of imagesStronger isolation, NixOS services such as PostgreSQL, Docker inside CI.

With nixery, state persists across steps only in the /tangled/workspace directory. With microvm, files, packages and services persist for the whole workflow. Which engines and images exist depends on the spindle operator.