A rewrite of the Plan 9 rc shell in Goose for UNIX-like systems and with structured CLI args
README.md

Tangled CI #

The workflows use the Spindle microVM engine with the nixos image.

Workflow Trigger Actions
check.yml Push to master, pull request to master, or manual run Nix checks, release tests, debug tests, and manual lint.
release.yml Push of a v* tag The same checks, then archive creation and publication to Tangled artifacts.

The Linux test environment supplies the absolute /bin and /usr/bin paths that the POSIX tests require. flake.lock pins the compiler, test tools, and release tools. The tests include uploader checks with mock authentication and HTTP commands. They do not use real credentials or upload files.

Repository setup #

  1. Open Settings → Pipelines on the Tangled repository.
  2. Select a spindle with the microvm engine and nixos image.
  3. Add RELEASE_HANDLE as a repository secret.
  4. Add RELEASE_APP_PASSWORD as a repository secret.

The handle must identify a repository owner or collaborator. The app password belongs to that account. Do not put credentials in workflow files, Git, or artifacts.

Spindle's default workflow timeout is five minutes. The operator must allow enough time for a cold Nix build and both test suites. This workflow has no custom timeout field because Spindle does not support one.

Release artifacts #

After the tag's tests pass, the release workflow publishes three artifacts:

  • rc2-<commit>-source.tar.gz: the tagged Git source tree, under rc2/.
  • rc2-<commit>-<system>.tar.gz: the Nix package and its complete runtime closure.
  • SHA256SUMS: SHA-256 checksums for both archives.

<commit> contains the first twelve hexadecimal characters of the commit ID. <system> is the runner's x86_64-linux or aarch64-linux system. The workflow does not cross-compile or produce macOS artifacts.

The package archive contains closure.nar, store-path, and README.txt. It includes the executable, manual, completions, licenses, and runtime dependencies. It requires Nix on a compatible Linux system. It is not a standalone package for systems without Nix.

After extraction, import and install the package:

nix-store --import < closure.nar
nix profile install "$(cat store-path)"

An import requires the permissions that your Nix installation grants for store imports. The CI export is unsigned. A restricted multi-user store can require an administrator or a trusted signature. SHA256SUMS detects corruption, but it does not supply a signature.

Publication uses Tangled's documented release artifact method. goat obtains a fresh service token for each knot write. The uploader sends each blob to com.atproto.repo.uploadBlob, then creates an org.tangled.repo.artifact record for the commit. The artifacts appear with the tag on Tangled.

The uploader rejects non-tag runs, fork sources, commit mismatches, unsafe filenames, symlinks, and files that exceed 50 MiB. A failed upload stops publication. Artifacts from earlier successful uploads remain. Publication is not atomic. A retry can create duplicate artifact records. Inspect the tag before a retry.

Local checks #

On Linux, run the same POSIX tests as CI:

nix run .#ci -- -euc 'make check test test-debug; mandoc -T lint doc/rc2.1'

Run the uploader tests without credentials:

bb ci/release-test.clj

Build archives locally without publication:

nix develop .#release --command bb ci/release.clj pack

The archives and manifest appear in .build/artifacts/. Source archives use HEAD, not uncommitted files. Commit the intended source before a release.