xeiaso.net tack
Stitch any CI into Tangled
No tags yet
Push an image to this repository and its tags will appear here.
tack - Connect Tangled to your CI
Tack is a custom Tangled spindle that runs
CI on alternate providers and reports their results back
to Tangled using standard ATProto records so they show up natively
in Tangled’s UI.
[!WARNING]
Project status: Tack is early and experimental software.
This repo itself uses Tack and I (mitchellh) use Tack for my projects,
but it is still new and relatively unproven.
Example
A Tangled workflow that fires a Buildkite pipeline on every push to
main and every pull request targeting main:
# .tangled/workflows/ci.yml
when:
- event: ["push"]
branch: ["main"]
- event: ["pull_request"]
branch: ["main"]
engine: tack
tack:
buildkite:
pipeline: my-app-ci
The when: block is the standard Tangled trigger schema; the
tack: block tells tack which Buildkite pipeline to fire and how.
See docs/buildkite.md for the full set of
options and end-to-end Buildkite setup. Tack can support multiple
providers.
How it Works
Tack is a drop-in alternative to the stock spindle runner. You run
tack and register it using the standard UI.
Native installations require git in PATH; the Docker and Nix packages
include it automatically.
Instead of executing workflows in local containers, tack consumes knot
sh.tangled.git.refUpdate events, loads .tangled/workflows at the pushed
commit, and translates matching workflows into 3rd party CI builds. Tack owns
the resulting pipeline records and exposes them through the standard
sh.tangled.ci.* XRPC API.
This makes even 3rd party CIs integrate first class into Tangled so their
status, counts, etc. can show up inline in things like pull requests.
Jetstream Knot /events (WebSocket)
sh.tangled.repo sh.tangled.git.refUpdate
sh.tangled.spindle.member
sh.tangled.repo.collaborator
│ │
│ (discover knots │
│ + membership) │
▼ ▼
╭────────────────────────────────╮
│ tack │
│ ╭──────────────────────────╮ │
│ │ provider router │ │ selected per-workflow
│ │ (fake │ buildkite) │ │ via `tack: { … }` YAML
│ ╰──────────────────────────╯ │
╰────────────────────────────────╯
│
│ Create Build (REST)
▼
Buildkite
│
│ POST /webhooks/buildkite
▼
tack ◀──── sh.tangled.ci.* XRPC ──── Tangled appview
query/get pipeline + CBOR logs
Configuration
Core configuration controls how tack talks to Tangled. Provider-specific
configuration (e.g. Buildkite) lives in its own section below.
Required
| Env var | Description |
|---|---|
TACK_HOSTNAME |
This spindle’s hostname (matches sh.tangled.repo.spindle) |
TACK_OWNER_DID |
DID of the spindle operator |
Optional
| Env var | Description |
|---|---|
TACK_LISTEN_ADDR |
HTTP listen address (default :8080) |
TACK_DB_PATH |
Local SQLite path (default tack.db) |
TACK_REPO_DIR |
Sparse workflow checkout cache (default tack.db.repos) |
TACK_JETSTREAM_URL |
Tangled Jetstream WebSocket URL |
TACK_DEV |
Use ws:// for knot event-streams (any non-empty value) |
All configured providers are active simultaneously. Each workflow
chooses its provider via the first key under its top-level tack:
block. e.g. tack: { buildkite: { ... } } runs on Buildkite,
tack: { fake: {} } runs on the in-process fake provider.
Providers
Provider-specific setup (Buildkite-side configuration, the
provider’s tack env vars, and the workflow YAML schema) lives in
its own doc per provider: