···11+# spindle architecture
22+33+Spindle is a small CI runner service. Here's a high level overview of how it operates:
44+55+* listens for [`sh.tangled.spindle.member`](/lexicons/spindle/member.json) and
66+[`sh.tangled.repo`](/lexicons/repo.json) records on the Jetstream.
77+* when a new repo record comes through (typically when you add a spindle to a
88+repo from the settings), spindle then resolves the underlying knot and
99+subscribes to repo events (see:
1010+[`sh.tangled.pipeline`](/lexicons/pipeline.json)).
1111+* the spindle engine then handles execution of the pipeline, with results and
1212+logs beamed on the spindle event stream over wss
1313+1414+### the engine
1515+1616+At present, the only supported backend is Docker. Spindle executes each step in
1717+the pipeline in a fresh container, with state persisted across steps within the
1818+`/tangled/workspace` directory.
1919+2020+The base image for the container is constructed on the fly using
2121+[Nixery](https://nixery.dev), which is handy for caching layers for frequently
2222+used packages.
2323+2424+The pipeline manifest is [specified here](/docs/spindle/pipeline.md).
+43
docs/spindle/hosting.md
···11+# spindle self-hosting guide
22+33+## prerequisites
44+55+* Go
66+* Docker (the only supported backend currently)
77+88+## configuration
99+1010+Spindle is configured using environment variables. The following environment variables are available:
1111+1212+* `SPINDLE_SERVER_LISTEN_ADDR`: The address the server listens on (default: `"0.0.0.0:6555"`).
1313+* `SPINDLE_SERVER_DB_PATH`: The path to the SQLite database file (default: `"spindle.db"`).
1414+* `SPINDLE_SERVER_HOSTNAME`: The hostname of the server (required).
1515+* `SPINDLE_SERVER_JETSTREAM_ENDPOINT`: The endpoint of the Jetstream server (default: `"wss://jetstream1.us-west.bsky.network/subscribe"`).
1616+* `SPINDLE_SERVER_DEV`: A boolean indicating whether the server is running in development mode (default: `false`).
1717+* `SPINDLE_SERVER_OWNER`: The DID of the owner (required).
1818+* `SPINDLE_PIPELINES_NIXERY`: The Nixery URL (default: `"nixery.tangled.sh"`).
1919+* `SPINDLE_PIPELINES_WORKFLOW_TIMEOUT`: The default workflow timeout (default: `"5m"`).
2020+* `SPINDLE_PIPELINES_LOG_DIR`: The directory to store workflow logs (default: `"/var/log/spindle"`).
2121+2222+## running spindle
2323+2424+1. **Set the environment variables.** For example:
2525+2626+ ```shell
2727+ export SPINDLE_SERVER_HOSTNAME="your-hostname"
2828+ export SPINDLE_SERVER_OWNER="your-did"
2929+ ```
3030+3131+2. **Build the Spindle binary.**
3232+3333+ ```shell
3434+ go build -o spindle core/spindle/server.go
3535+ ```
3636+3737+3. **Run the Spindle binary.**
3838+3939+ ```shell
4040+ ./spindle
4141+ ```
4242+4343+Spindle will now start, connect to the Jetstream server, and begin processing pipelines.
+59
docs/spindle/pipeline.md
···11+# spindle pipeline manifest
22+33+Spindle pipelines are defined under the `.tangled/workflows` directory in a
44+repo. Generally:
55+66+* Pipelines are defined in YAML.
77+* Dependencies can be specified from
88+[Nixpkgs](https://search.nixos.org) or custom registries.
99+* Environment variables can be set globally or per-step.
1010+1111+Here's an example that uses all fields:
1212+1313+```yaml
1414+# build_and_test.yaml
1515+when:
1616+ - event: ["push", "pull_request"]
1717+ branch: ["main", "develop"]
1818+ - event: ["manual"]
1919+2020+dependencies:
2121+ ## from nixpkgs
2222+ nixpkgs:
2323+ - nodejs
2424+ ## custom registry
2525+ git+https://tangled.sh/@oppi.li/statix:
2626+ - statix
2727+2828+steps:
2929+ - name: "Install dependencies"
3030+ command: "npm install"
3131+ environment:
3232+ NODE_ENV: "development"
3333+ CI: "true"
3434+3535+ - name: "Run linter"
3636+ command: "npm run lint"
3737+3838+ - name: "Run tests"
3939+ command: "npm test"
4040+ environment:
4141+ NODE_ENV: "test"
4242+ JEST_WORKERS: "2"
4343+4444+ - name: "Build application"
4545+ command: "npm run build"
4646+ environment:
4747+ NODE_ENV: "production"
4848+4949+environment:
5050+ BUILD_NUMBER: "123"
5151+ GIT_BRANCH: "main"
5252+5353+## current repository is cloned and checked out at the target ref
5454+## by default.
5555+clone:
5656+ skip: false
5757+ depth: 50
5858+ submodules: true
5959+```