···1010 - name: Anirudh
1111 email: anirudh@tangled.sh
1212 handle: icyphox.sh
1313+ - name: Akshay
1414+ email: akshay@tangled.sh
1515+ handle: oppi.li
1316---
14171515-Since launching Tangled, continuous integration has consistently topped our
1616-feature request list. And rightfully so -- modern software development is
1717-unthinkable without automated testing, building, and deployment pipelines.
1818-Today, we're excited to announce that CI is no longer a wishlist item, but a
1919-fully-featured reality.
1818+Since launching Tangled, continuous integration has
1919+consistently topped our feature request list. Today, CI is
2020+no longer a wishlist item, but a fully-featured reality.
20212122Meet **spindle**: Tangled's new CI runner that brings powerful automation
2223directly to your repositories. In typical Tangled fashion we've been dogfooding
···3637Once triggered, spindle reads your pipeline manifest, spins up the necessary
3738execution environment (covered below), and runs your defined workflow steps.
3839Throughout execution, it streams real-time logs and status updates
3939-(`sh.tangled.pipeline.status`) back through websocktes, which the Tangled
4040+(`sh.tangled.pipeline.status`) back through websockets, which the Tangled
4041appview subscribes to for live updates.
41424243This architecture keeps everything responsive and real-time while maintaining
···4546## spindle pipelines
46474748The pipeline manifest is defined in YAML, and should be relatively familiar to
4848-those that have used other CI products. Here's a minimal example:
4949+those that have used other CI solutions. Here's a minimal example:
49505051```yaml
5152# test.yaml
···5960 - go
60616162steps:
6262- - name: patch static dir
6363- command: |
6464- mkdir -p appview/pages/static; touch appview/pages/static/x
6565-6663 - name: run all tests
6764 environment:
6865 CGO_ENABLED: 1
···7067 go test -v ./...
7168```
72697373-Manifests are stored under your repo's `.tangled/workflows` directory. There may
7474-be multiple manifests here describing different workflows -- for example, a
7575-`build.yaml`, `test.yaml` and a `lint.yaml`. You can read the [full manifest spec
7676-here](https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/pipeline.md).
7777-7878-The `when` block defines the set of events that can trigger the workflow run.
7979-The above example will run tests on any push or pull request targeting the
8080-`master` branch.
8181-8282-Now the `dependencies` block is the real interesting bit. Dependencies for your
8383-workflow, like Go, Node.js, Python etc. can be pulled in from nixpkgs. nixpkgs
8484--- for the uninitiated -- is a vast collection of packages for the Nix package
8585-manager. Fortunately, you needn't know nor care about Nix to use it! Just head
8686-to https://search.nixos.org to find your package of choice (I'll bet 1€ that
8787-it's there[^1]), toss it in the list and run your build. The Nix-savvy of you
8888-lot will be happy to know that you can toss in custom registries there.
7070+You can read the [full manifest spec
7171+here](https://tangled.sh/@tangled.sh/core/blob/master/docs/spindle/pipeline.md),
7272+but the `dependencies` block is the real interesting bit.
7373+Dependencies for your workflow, like Go, Node.js, Python
7474+etc. can be pulled in from nixpkgs.
7575+[Nixpkgs](https://github.com/nixos/nixpkgs/) -- for the
7676+uninitiated -- is a vast collection of packages for the Nix
7777+package manager. Fortunately, you needn't know nor care
7878+about Nix to use it! Just head to https://search.nixos.org
7979+to find your package of choice (I'll bet 1€ that it's
8080+there[^1]), toss it in the list and run your build. The
8181+Nix-savvy of you lot will be happy to know that you can use
8282+custom registries too.
89839084[^1]: I mean, if it isn't there, it's nowhere.
91859292-Finally, define your steps, neccesary environment variables and commands.
8686+Finally, define your steps, necessary environment variables and commands.
9387Commands can be multi-lined. Let's take a look at how spindle executes workflow
9488steps.
9589···116110[hello-go](https://search.nixos.org/packages?channel=25.05&show=hello-go)
117111package from nixpkgs.
118112119119-Nixery is super handy since we can construct these images for CI environments on
120120-the fly, with all dependencies baked in, and the best part: caching for commonly
121121-used packages is free thanks to Docker (pre-existing layers get reused). We run
122122-a Nixery instance of our own at https://nixery.tangled.sh but you may override
123123-that if you choose not to trust us.
113113+Nixery is super handy since we can construct these images
114114+for CI environments on the fly, with all dependencies baked
115115+in, and the best part: caching for commonly used packages is
116116+free thanks to Docker (pre-existing layers get reused). We
117117+run a Nixery instance of our own at
118118+https://nixery.tangled.sh but you may override that if you
119119+choose to.
124120125125-## pipeline statuses and log streaming
121121+## debugging CI
122122+123123+We understand that debugging CI can be the worst. There are
124124+two parts to this problem:
125125+126126+- CI services often bring their own workflow definition
127127+ formats and it can sometimes be difficult to know why the
128128+ workflow won't run or why the workflow definition is
129129+ incorrect
130130+- The CI job itself fails, but this has more to do with the
131131+ build system of choice
126132127127-Now that your workflow is running, watching it run to completion is half the
128128-fun! Or watching it fail inexplicably for the hundredth time... which is
129129-decidedly unfun. In any case, logs and pipeline statuses are streamed websockets
130130-exposed by spindle, and show up in the brand new "pipelines" tab in your
131131-repository.
133133+To mend the first problem: we are making use of git
134134+[push-options](https://git-scm.com/docs/git-push#Documentation/git-push.txt--ooption).
135135+When you push to a repository with an option like so:
132136133133-
137137+```
138138+git push origin master -o verbose-ci
139139+```
140140+141141+The server runs a basic set of analysis rules on your
142142+workflow file, and reports any errors:
143143+144144+```
145145+λ git push origin main -o verbose-ci
146146+ .
147147+ .
148148+ .
149149+ .
150150+remote: error: failed to parse workflow(s):
151151+remote: - at .tangled/workflows/fmt.yml: yaml: line 14: did not find expected key
152152+remote:
153153+remote: warning(s) on pipeline:
154154+remote: - at build.yml: workflow skipped: did not match trigger push
155155+```
156156+157157+The analysis performed at the moment is quite basic (expect
158158+it to get better over time), but it is already quite useful
159159+to help debug workflows that don't trigger!
134160135161## pipeline secrets
136162···144170145171
146172147147-The secrets themselves are stored in a configured secret manager. By default,
148148-this is the same sqlite database that spindle uses. This is *fine* for
149149-self-hosters. The hosted, flagship instance at https://spindle.tangled.sh
150150-however uses [OpenBao](https://openbao.org), an OSS fork of HashiCorp Vault.
173173+The secrets themselves are stored in a secret manager. By
174174+default, this is the same sqlite database that spindle uses.
175175+This is *fine* for self-hosters. The hosted, flagship
176176+instance at https://spindle.tangled.sh however uses
177177+[OpenBao](https://openbao.org), an OSS fork of HashiCorp
178178+Vault.
151179152180## get started now
153181