CI and deploy

The runner, pipelines, checks, the deploy agent.

Rule one: the key never enters a hosting provider's secrets store. Compute goes where the key is.

The runner

secretree runner is a CI agent for a machine you control: a Mac mini, a home server, a VPS, a spare laptop. It needs a clone made with secretree clone (so it holds a key) and a pipeline in the repository.

$ secretree runner
runner: #1 feature/retry @ 900c2a69
runner: #1 feature/retry @ 900c2a69 → success (./.secretree/ci passed in 4s)
runner: main @ fd72f765
runner: main @ fd72f765 → success (./.secretree/ci passed in 3s)
runner: 2 job(s) done

Every 60 seconds (--interval) it fetches, finds the head of every open pull request and of the branches in --branches (default main) that have no check named --name (default ci) yet, checks each out into a throw-away worktree, runs the pipeline, and records a signed check event with the status, a summary and the log (last 200 KiB). --once does one pass and exits, for cron or tests.

The pipeline

In order of preference:

  1. .secretree/ci, an executable script in the repository.
  2. A ci target in the Makefile.
  3. The command given with --cmd.

The job runs in the worktree with CI=1 and these variables:

Variable Meaning
SECRETREE_COMMIT the commit being checked
SECRETREE_CHECK the check name
SECRETREE_REPO_DIR the runner's clone, for secretree -C … pr comment and friends
SECRETREE_PR, SECRETREE_PR_ID pull request number and id (pull request jobs only)
SECRETREE_BASE, SECRETREE_BASE_BRANCH, SECRETREE_HEAD_BRANCH base commit and branch names (pull request jobs only)
SECRETREE_BRANCH the branch name (plain branch jobs only)

The secretree binary is on the job's PATH. Logs and artifacts never leave the vault unless the pipeline sends them somewhere itself.

A minimal .secretree/ci:

#!/bin/sh
set -e
go vet ./...
go test ./...

Several runners with different --name values give several checks (ci, lint, security); each check can be required in the policy.

Existing workflow files

Runners execute what the repository already has. act runs GitHub workflow files locally; put act -j test in .secretree/ci. Registering the machine as a GitHub or GitLab self-hosted runner is a supported hybrid: the host then sees the workflow file and job names, and the checkout step is replaced by a secretree clone.

Agents as runner jobs

An AI reviewer is a runner whose job talks to a model and writes back through the CLI. Add the agent as a member with --role agent (see Team and agents), then on its machine:

$ secretree runner --name ai-review --branches "" --cmd agents/review.sh

agents/review.sh from the repository sends the diff of SECRETREE_BASE...SECRETREE_COMMIT to the Claude CLI, posts line comments with pr comment --path --line, records a verdict with pr review --verdict, and, because the diff left the key boundary, writes a ledger entry first (secretree ledger add --kind export). Point MODEL_CMD at a local model to keep the diff on the machine.

The deploy agent

Pull-based deploys on the target host: no inbound access to the server, no production credentials on the CI machine.

$ secretree deploy-agent --to /srv/app --branch main --require-check ci --cmd "systemctl restart app"
deploy: 4ebfacfe is live at /srv/app

Every 60 seconds it fetches, and when the branch tip changed and its --require-check is green (default ci; "" to skip the gate), it exports the tree with git archive into --to (no .git on the server), runs --cmd there, and records a signed deploy event that every member sees in the collaboration data. A marker file .secretree-deployed in the target holds the deployed commit.

Notifications about checks and deploys

secretree watch reports new checks and deploys along with pull request activity; see Share, ledger, notifications.