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:
.secretree/ci, an executable script in the repository.- A
citarget in theMakefile. - 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.