Self-hosted Tangled spindle
spindle docs agents tangled.md
4.1 kB · 47 lines
Markdown
at main

Tangled: PRs, merges and CI for this repo #

These are the steps that worked for demi.dev/spindle on 2026-11-01 (ENG-469). Only the lead agent does any of this; implementers commit and stop.

Remote #

Remote URL
origin demi.dev@tangled.org:did:plc:mj26t7lhrwzongl7wg4qtacm

git ls-remote origin proves access. tang can't resolve repos that use the new repo records, so every PR step goes through the web UI in the owner's signed-in Chrome.

Pull requests #

  1. Push: git push -u origin <branch>. A push to a branch other than main starts no pipeline.
  2. Open: go to https://tangled.org/demi.dev/spindle/pulls/new?source=branch&sourceBranch=<branch>&targetBranch=main, then fill in Title and Body.
    • Click Create pull request. The first click often doesn't submit, so click again if the page doesn't redirect to /pulls.
    • Before a third click, check that /demi.dev/spindle/pulls/<next N> exists, so you don't open a duplicate.
  3. Comment: in the right-hand Comments panel, set the textarea's value and send it.
    • Set the value with the native value setter followed by an input event.
    • Click into the textarea, then press cmd+End, space, BackSpace, and finally cmd+Return.
    • Reload the page. Then check that the comment shows once in the panel. Searching the page's raw HTML for its heading finds about 3 copies of one comment.
  4. New round: push to the same branch, then click Resubmit next to the round selector (v0, v1, …).
  5. Merge:
    • First check that the page has no Resubmit button and that the newest round's head matches git rev-parse --short <branch>.
    • Then click Rebase & merge at the bottom right of the page. Never use Manually mark as merged.
    • The knot applies the patches as new commits, so afterwards run git pull --ff-only origin main and delete the branch and worktree.

CI on our spindle #

  • Which spindle runs CI: repo Settings → Pipelines → Spindle. Choose spindle.demi.dev, then Save. The choice persists, and secrets are stored on the selected spindle.
  • Workflows: .tangled/workflows/*.yml with engine: nixery. A PR to main and a push to main each start a pipeline within seconds.
  • Reading a run:
    • Pipelines lists every run. Each run's page is at /pipelines/<id>/workflow/<file>.yml and shows per-step logs with durations.
    • The log panel shows "Waiting for the spindle" until the spindle streams the logs.
    • Retry appears on a finished run, and it creates a new pipeline id.
  • Cancel (XRPC path drilled 2026-11-01, ENG-469): the Tangled web UI has no cancel control. In v1.20.0 the web app wires up only Retry and Approve, and the old appview route POST /<repo>/pipelines/<id>/cancel returns 404. Cancel through the spindle's own XRPC instead. It needs a service-auth token from the PDS of an account with push access, which here means the owner's. Never print the app password or either token.
    1. Create a session on the owner's PDS with an app password (com.atproto.server.createSession). This gives an access JWT.
    2. Call GET <pds>/xrpc/com.atproto.server.getServiceAuth?aud=did:web:spindle.demi.dev&lxm=org.tangled.ci.cancelPipeline with that JWT. It returns {token}.
    3. Call POST https://spindle.demi.dev/xrpc/org.tangled.ci.cancelPipeline with Authorization: Bearer <token> and the JSON body {"repo":"did:plc:mj26t7lhrwzongl7wg4qtacm","pipeline":"<pipeline id>"}.
      • It returns 200 on success.
      • It returns 404 PipelineNotFound if the id doesn't belong to the repo.
      • The mill then marks the workflow cancelled and tells the executor to destroy it.
      • Proven on pipeline 3mzbcyk3zfq22: the page showed "User canceled the workflow", the executor logged workflow canceled, and the job container was gone within a second.
  • Where a run happened:
    • On the VM: journalctl -u spindle | grep <pipeline id> shows workflow started … node_id=spindle-exec-1 and then workflow finished.
    • In the bucket: logs are stored under logs/<lease id>.log.