# Releasing Digital Rust A release is one annotated tag push. The Spindle pipeline in `.tangled/workflows/release.yml` packages the theme files, publishes them to `katsuricata.tngl.io/digitalrust/`, and writes the release record to the PDS. That record is what renders the download list on the tag page at `tangled.org/katsuricata.com/DigitalRust`. The pipeline has no build step. The deliverables are the files in `static/ports/` and the two specifications, so a release packages what the tag already holds. This keeps the run well inside the five minute microvm timeout, and it means a release does not depend on the network. ## What a release ships | File | Contents | | --------------------------------------------------- | ------------------------------------------- | | `digital-rust-ports-vX.Y.Z.zip` | Every port in `static/ports/`, one per tool | | `digital-rust-agentskill-vX.Y.Z.zip` | The agent skill, ready to install | | `digital-rust-syntax-highlighting-specification.md` | The canonical syntax and palette spec | | `digital-rust-ui-specification.md` | The canonical UI specification | | `SHA256SUMS.txt` | Checksums for the files above | `scripts/make-archives.py` builds these, and it refuses to build when the version on the tag, the version in the syntax specification's version history, and the version in `package.json` disagree. The site's version badge reads the specification, so a mismatch would ship a release that reports another number. ## Setup, once per project 1. The repo is on Tangled with its spindle set to `spindle.tangled.sh`: ```sh tg repo view katsuricata.com/DigitalRust --json | jq .spindle ``` 2. Two secrets in **this** repo's Settings → Secrets, not in the pages repo: - `SHEAF_PAGES_SSH_KEY`: the contents of `~/.config/sheaf/pages-deploy`. The name is historical; one shared deploy keypair covers every project. - `ATP_APP_PASSWORD`: an app password from bsky.social, for the release record. 3. `scripts/make-indexes.py` and `scripts/write-ssh-key.sh` are committed here. The pipeline runs both from this checkout, never from the pages repo. ## Cutting a release ```sh pnpm install pnpm check && pnpm lint && pnpm contrast pnpm build python3 scripts/make-archives.py --version 1.3.1 --check-only git tag -a v1.3.1 -m "Digital Rust v1.3.1: Safe Mode in the agent skill" git push origin v1.3.1 ``` Then watch it, and verify it: ```sh tg pipeline list katsuricata.com/DigitalRust tg pipeline logs curl -sI https://katsuricata.tngl.io/digitalrust/v1.3.1/ ``` Open the tag page on tangled.org as well: the artifact list there comes from the PDS record, which is a different path from the pages mirror, so a release can succeed at one and fail at the other. ## Rules the pipeline depends on - The tag must be annotated (`git tag -a`). A lightweight tag has no tag object, and the release record is keyed to that object. The pipeline checks for one and fails before it builds anything. - To re-run a release, fix the problem on `main` first, then delete the tag locally and remotely and tag again. A tag always runs the workflow file from its own commit, so editing the workflow and re-pushing the same tag changes nothing. - Every published file carries an extension. Tangled Pages maps a path without one to a directory and then answers 404, which makes the file undownloadable. - A dependency must exist in nixpkgs before you add it to the workflow. A name that does not resolve fails the microvm before any step runs, and it is only exercised the first time a step needs it, which can be releases later. The current list is the same set of attributes another project has used for a while.