Stitch any CI into Tangled
1# tack - Connect Tangled to your CI
2
3Tack is a custom [Tangled](https://tangled.org) spindle that runs
4CI on alternate providers and reports their results back
5to Tangled using standard ATProto records so they show up natively
6in Tangled's UI.
7
8## Example
9
10A Tangled workflow that fires a Buildkite pipeline on every push to
11`main` and every pull request targeting `main`:
12
13```yaml
14# .tangled/workflows/ci.yml
15when:
16 - event: ["push"]
17 branch: ["main"]
18 - event: ["pull_request"]
19 branch: ["main"]
20
21tack:
22 buildkite:
23 pipeline: my-app-ci
24```
25
26The `when:` block is the standard Tangled trigger schema; the
27`tack:` block tells tack which Buildkite pipeline to fire and how.
28See [docs/buildkite.md](docs/buildkite.md) for the full set of
29options and end-to-end Buildkite setup. Tack can support multiple
30providers.
31
32## How it Works
33
34Tack is a drop-in alternative to the stock `spindle` runner. You run
35`tack` and [register it using the standard UI](https://tangled.org/settings/spindles).
36
37Instead of executing workflows in local containers, tack translates each
38Tangled pipeline trigger into a 3rd party CI build, and reports build state
39back to Tangled using the existing `sh.tangled.pipeline.status` wire format.
40
41This makes even 3rd party CIs integrate first class into Tangled so their
42status, counts, etc. can show up inline in things like pull requests.
43
44```
45 sh.tangled.pipeline
46 Jetstream ───────────────────────▶ tack
47 │
48 │ Create Build
49 ▼
50 Buildkite
51 │
52 │ webhooks
53 ▼
54 tack ──── /events (WebSocket) ────▶ Tangled appview
55 sh.tangled.pipeline.status
56```
57
58```sh
59go run . -addr :8080
60```
61
62## Configuration
63
64Core configuration controls how tack talks to Tangled. Provider-specific
65configuration (e.g. Buildkite) lives in its own section below.
66
67### Required
68
69| Env var | Description |
70| ---------------- | ----------------------------------------------------------- |
71| `TACK_HOSTNAME` | This spindle's hostname (matches `sh.tangled.repo.spindle`) |
72| `TACK_OWNER_DID` | DID of the spindle operator |
73
74### Optional
75
76| Env var | Description |
77| -------------------- | -------------------------------------------------------- |
78| `TACK_LISTEN_ADDR` | HTTP listen address (default `:8080`) |
79| `TACK_DB_PATH` | Local SQLite path (default `tack.db`) |
80| `TACK_JETSTREAM_URL` | Tangled Jetstream WebSocket URL |
81| `TACK_DEV` | Use `ws://` for knot event-streams (any non-empty value) |
82
83When no provider is configured, tack runs an in-process fake provider
84that's useful for exercising the jetstream → knot → `/events` flow
85locally without a real CI account.
86
87## Providers
88
89Provider-specific setup (Buildkite-side configuration, the
90provider's tack env vars, and the workflow YAML schema) lives in
91its own doc per provider:
92
93* [Buildkite](docs/buildkite.md)