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## Configuration
59
60Core configuration controls how tack talks to Tangled. Provider-specific
61configuration (e.g. Buildkite) lives in its own section below.
62
63### Required
64
65| Env var | Description |
66| ---------------- | ----------------------------------------------------------- |
67| `TACK_HOSTNAME` | This spindle's hostname (matches `sh.tangled.repo.spindle`) |
68| `TACK_OWNER_DID` | DID of the spindle operator |
69
70### Optional
71
72| Env var | Description |
73| -------------------- | -------------------------------------------------------- |
74| `TACK_LISTEN_ADDR` | HTTP listen address (default `:8080`) |
75| `TACK_DB_PATH` | Local SQLite path (default `tack.db`) |
76| `TACK_JETSTREAM_URL` | Tangled Jetstream WebSocket URL |
77| `TACK_DEV` | Use `ws://` for knot event-streams (any non-empty value) |
78
79All configured providers are active simultaneously. Each workflow
80chooses its provider via the first key under its top-level `tack:`
81block. e.g. `tack: { buildkite: { ... } }` runs on Buildkite,
82`tack: { fake: {} }` runs on the in-process fake provider.
83
84## Providers
85
86Provider-specific setup (Buildkite-side configuration, the
87provider's tack env vars, and the workflow YAML schema) lives in
88its own doc per provider:
89
90* [Buildkite](docs/buildkite.md)