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.
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"]
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.
Instead of executing workflows in local containers, tack translates each
Tangled pipeline trigger into a 3rd party CI build, and reports build state
back to Tangled using the existing sh.tangled.pipeline.status wire format.
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.
sh.tangled.pipeline
Jetstream ───────────────────────▶ tack
│
│ Create Build
▼
Buildkite
│
│ webhooks
▼
tack ──── /events (WebSocket) ────▶ Tangled appview
sh.tangled.pipeline.status
go run . -addr :8080
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_JETSTREAM_URL |
Tangled Jetstream WebSocket URL |
TACK_DEV |
Use ws:// for knot event-streams (any non-empty value) |
When no provider is configured, tack runs an in-process fake provider
that's useful for exercising the jetstream → knot → /events flow
locally without a real CI account.
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: