@microck/raft 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/deploy/build-image.py +4 -2
- package/deploy/verify-controls.py +5 -5
- package/deploy/verify-features.py +35 -2
- package/deploy/verify-jobs.py +264 -0
- package/deploy/verify-limits.py +20 -2
- package/deploy/verify-live.py +12 -3
- package/deploy/verify-output.py +208 -0
- package/deploy/verify-release.py +33 -4
- package/deploy/verify-run.py +571 -0
- package/deploy/verify-self-update.py +9 -1
- package/deploy/verify-sync.py +122 -0
- package/docs/benchmarks/read-latency-2026-10-29.json +70 -0
- package/docs/boat-capabilities.md +60 -7
- package/docs/boat-parity-design.md +1 -0
- package/docs/boot-performance.mdx +21 -0
- package/docs/contract.md +76 -2
- package/docs/first-box.mdx +22 -19
- package/docs/guides/background-jobs.mdx +38 -31
- package/docs/guides/backup-recovery.mdx +3 -2
- package/docs/guides/ci-jobs.mdx +209 -0
- package/docs/guides/files.mdx +2 -2
- package/docs/guides/index.mdx +31 -0
- package/docs/guides/long-running-services.mdx +1 -1
- package/docs/guides/meta.json +7 -2
- package/docs/guides/project-setup.mdx +1 -1
- package/docs/guides/scripting-ci.mdx +28 -9
- package/docs/guides/snapshots-forks.mdx +3 -1
- package/docs/guides/upgrades.mdx +7 -7
- package/docs/index.mdx +26 -28
- package/docs/maintainers/index.mdx +18 -0
- package/docs/maintainers/meta.json +12 -0
- package/docs/meta.json +5 -9
- package/docs/operations.mdx +7 -0
- package/docs/publishing.md +14 -4
- package/docs/reference/capacity.mdx +2 -1
- package/docs/reference/cli.md +85 -19
- package/docs/reference/meta.json +3 -1
- package/docs/releases/0.2.0.md +1 -0
- package/docs/releases/0.2.1.md +1 -0
- package/docs/releases/0.3.0.md +1 -0
- package/docs/releases/0.4.0.md +1 -0
- package/docs/releases/0.5.0.md +1 -0
- package/docs/releases/0.6.0.md +1 -0
- package/docs/releases/0.7.0.md +23 -0
- package/docs/releases/index.mdx +21 -0
- package/docs/releases/meta.json +15 -0
- package/docs/requirements.mdx +1 -1
- package/docs/reviews/docs-audit-2026-10-24.md +92 -0
- package/docs/reviews/performance-audit-2026-10-29.md +90 -0
- package/docs/site-development.md +1 -0
- package/docs/verification.mdx +21 -3
- package/package.json +3 -1
- package/raft.py +380 -179
- package/raft_files.py +13 -1
- package/raft_jobs.py +390 -0
- package/raft_output.py +166 -0
- package/raft_run.py +330 -0
- package/skills/raft-cli/SKILL.md +78 -197
|
@@ -9,7 +9,8 @@ Raft exports portable workspace archives and restores them onto compatible hosts
|
|
|
9
9
|
|
|
10
10
|
## Target workspace handle
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use a **persistent** workspace. Stop it before backup; stopping a disposable box
|
|
13
|
+
deletes it and its snapshots, so copy files out instead.
|
|
13
14
|
|
|
14
15
|
```sh title="CONTROLLER: Select and stop target workspace"
|
|
15
16
|
raft list
|
|
@@ -35,7 +36,7 @@ Backup archives contain the entire guest filesystem, including credentials, SSH
|
|
|
35
36
|
|
|
36
37
|
Raft enforces safeguards during export:
|
|
37
38
|
|
|
38
|
-
- **Private permissions**:
|
|
39
|
+
- **Private permissions**: Raft creates the staged archive with mode `0600` and publishes it privately. Choose a new destination path; do not pre-create the file.
|
|
39
40
|
- **Atomic link publication**: After export and `fsync`, Raft publishes the archive using `os.link(archive.name, destination)`. Hard-link support is checked at final publication rather than preflight; export can succeed while publication fails if the filesystem lacks hard-link support.
|
|
40
41
|
- **No overwriting**: The destination file must not already exist.
|
|
41
42
|
- **Lifecycle lock**: Export holds `/run/lock/raft-incus.lock`. Expiry checks for other containers on the host are delayed while the lock is held.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Disposable CI jobs
|
|
3
|
+
description: Run trusted builds in temporary Raft boxes, collect results, and clean up with a bounded lifetime.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Disposable CI jobs
|
|
7
|
+
|
|
8
|
+
`raft run` runs one foreground command in a fresh disposable box. It creates the
|
|
9
|
+
box, waits for command readiness, optionally uploads source, streams command
|
|
10
|
+
output, collects requested result directories, and attempts ownership-checked
|
|
11
|
+
cleanup even after failure or cancellation. It does not register a GitHub
|
|
12
|
+
self-hosted runner or replace your CI scheduler.
|
|
13
|
+
|
|
14
|
+
<Callout type="warn" title="Unreleased: requires the 0.7.0 development code">
|
|
15
|
+
The published release is 0.6.0, which does not include `raft run`. As checked on
|
|
16
|
+
2026-10-24, no 0.7.0 npm package or GitHub release assets are available. Use the
|
|
17
|
+
[stable scripting workflow](./scripting-ci.mdx) unless you intend to test a reviewed
|
|
18
|
+
source revision. Do not install a nonexistent 0.7.0 package.
|
|
19
|
+
</Callout>
|
|
20
|
+
|
|
21
|
+
For development, run `python3 /path/to/raft.py run` from the reviewed checkout.
|
|
22
|
+
The CI example below pins the full source commit instead of an unpublished tag.
|
|
23
|
+
|
|
24
|
+
## Trust boundary
|
|
25
|
+
|
|
26
|
+
Use dedicated hosts and trusted jobs only. The controller's SSH identity has
|
|
27
|
+
passwordless sudo and controls the host; it is not a scoped, per-job CI token.
|
|
28
|
+
Boxes are unprivileged Incus containers sharing the host kernel, not separate
|
|
29
|
+
kernel VMs. Do not expose this identity to unreviewed pull requests, fork jobs,
|
|
30
|
+
or a `pull_request_target` workflow that checks out attacker-controlled code.
|
|
31
|
+
|
|
32
|
+
Raft does not install or register a runner, configure repository secrets, forward
|
|
33
|
+
your SSH agent, copy controller environment variables, or buy cloud capacity.
|
|
34
|
+
The operator must approve and configure existing host access separately. Never
|
|
35
|
+
copy a host private key or a GitHub token into the guest.
|
|
36
|
+
|
|
37
|
+
## One command
|
|
38
|
+
|
|
39
|
+
```sh title="CONTROLLER: Git working tree"
|
|
40
|
+
RAFT_NO_UPDATE_CHECK=1 raft run \
|
|
41
|
+
--location lab --timeout 600 --cpu 2 --memory 4GiB \
|
|
42
|
+
--purpose "Project tests" --owner "Local CI" --next "Delete after collection" \
|
|
43
|
+
--push . --pull /workspace/project/reports ./ci-reports \
|
|
44
|
+
-- bash -lc 'set -euo pipefail; mkdir -p reports; npm ci; npm test 2>&1 | tee reports/test.log'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The controller needs Linux, Python 3.11.8+, OpenSSH, Git for `--push`, a configured
|
|
48
|
+
Raft location, verified SSH host keys, batch authentication, and the current host
|
|
49
|
+
expiry worker. Ordinary image/host sizing and note policies still apply. `run`
|
|
50
|
+
always forces disposable behavior, regardless of controller lifetime defaults.
|
|
51
|
+
It never retries the payload command.
|
|
52
|
+
|
|
53
|
+
- stdout/stderr stream the payload; lifecycle messages and elapsed time go to
|
|
54
|
+
stderr. There is no cost estimate or JSON result protocol.
|
|
55
|
+
- `--timeout` is one total deadline for Git filtering, creation, readiness, upload
|
|
56
|
+
and execution, not a fresh timeout for each step. Default: 600 seconds; range:
|
|
57
|
+
1 to 2,591,880 seconds.
|
|
58
|
+
- `--push` includes tracked and unignored untracked files from the chosen Git
|
|
59
|
+
working tree, including working-tree edits. It excludes `.git` at every level
|
|
60
|
+
and refuses submodules. Tracked files remain included even if ignored later:
|
|
61
|
+
this is not a secret scanner. Deleted tracked files are absent.
|
|
62
|
+
- `--push-all` explicitly copies the complete directory, including hidden and
|
|
63
|
+
ignored files and Git metadata. Inspect it for credentials first. This is the
|
|
64
|
+
opt-in alternative for non-Git or explicitly staged trees; it is not a silent
|
|
65
|
+
fallback when Git fails.
|
|
66
|
+
- Uploads default to `/workspace/project`; without an upload, commands default
|
|
67
|
+
to `/workspace`. `--cwd` overrides this. An upload destination must not exist,
|
|
68
|
+
and its parent must already exist. Raft never merges into a stale checkout.
|
|
69
|
+
- Repeat `--pull GUEST_DIRECTORY NEW_LOCAL_DIRECTORY` to collect directories,
|
|
70
|
+
including after a failing payload. Local parents must exist; destinations
|
|
71
|
+
must be new, including no existing symlinks. Files can be placed in a result
|
|
72
|
+
directory. Collection happens before deletion, with a shared 30-second grace.
|
|
73
|
+
A failed pull does not stop later pulls unless that grace has expired.
|
|
74
|
+
- Exit status preserves a failing payload, including signal-style statuses.
|
|
75
|
+
Job timeout returns 124, Ctrl-C 130, SIGTERM 143. Setup/collection/cleanup
|
|
76
|
+
failure returns 1 when there is no earlier failing status. A successful
|
|
77
|
+
payload is not reported successful when cleanup cannot be confirmed.
|
|
78
|
+
|
|
79
|
+
The host receives a unique ownership marker and a fixed expiry of timeout + 120
|
|
80
|
+
seconds as part of creation, before startup. Cleanup checks ownership under the
|
|
81
|
+
host lifecycle lock and has a separate 30-second grace. Repeated cancellation is
|
|
82
|
+
ignored during these bounded collection/cleanup attempts. No lease renewal or
|
|
83
|
+
`--keep` mode is implemented.
|
|
84
|
+
|
|
85
|
+
If creation was not acknowledged, cleanup first records that run's cancellation
|
|
86
|
+
under the same host lifecycle lock. Creation checks that record before allocating,
|
|
87
|
+
so a queued SSH request cannot start the box after cleanup has confirmed absence.
|
|
88
|
+
These empty per-run records live in the root-only `/run/raft-ci-cancelled`
|
|
89
|
+
directory, use no-follow operations, and remain until host reboot, when queued
|
|
90
|
+
processes also disappear. Ordinary acknowledged runs leave no cancellation file.
|
|
91
|
+
|
|
92
|
+
If the controller is killed before cleanup, SSH is lost, or cleanup fails, inspect
|
|
93
|
+
the exact handle printed on stderr. A disconnected create may still finish when
|
|
94
|
+
cancellation could not be recorded. The disposable expiry worker is a backstop,
|
|
95
|
+
not a guarantee of instantaneous deletion: an unreachable host, stopped worker or
|
|
96
|
+
held lifecycle lock can delay it. Do not blindly rerun an uncertain job or assume
|
|
97
|
+
its side effects were rolled back.
|
|
98
|
+
|
|
99
|
+
## Prepared templates instead of shared mutable caches
|
|
100
|
+
|
|
101
|
+
Prepare dependencies and tool versions in a persistent base box, stop it, then
|
|
102
|
+
create a named snapshot. See [project setup](./project-setup.mdx) and
|
|
103
|
+
[snapshots](./snapshots-forks.mdx). Keep the source box and snapshot available:
|
|
104
|
+
|
|
105
|
+
```sh title="CONTROLLER: Use an existing trusted snapshot"
|
|
106
|
+
raft run --from lab:rf-REPLACE_WITH_BASE_ID/ci-base --timeout 900 \
|
|
107
|
+
--purpose "Cached build" --owner "CI" --next "Delete after tests" \
|
|
108
|
+
--push . -- bash -lc 'npm ci --prefer-offline && npm test'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The template stays on its source host and retains its size unless explicitly
|
|
112
|
+
overridden. Put reusable caches outside the upload destination, which must be
|
|
113
|
+
new. Each job gets an independent copy; its mutations do not update the template
|
|
114
|
+
or another job's cache. Refresh templates deliberately when dependencies change.
|
|
115
|
+
|
|
116
|
+
Raft snapshots retain filesystem contents, including credentials and Docker
|
|
117
|
+
storage. They do not save process memory. Inspect and sanitize the base before
|
|
118
|
+
sharing it with jobs. Do not assume Boat's selective snapshot/cache rules apply
|
|
119
|
+
to Raft's whole-filesystem copies.
|
|
120
|
+
|
|
121
|
+
## GitHub Actions orchestration example
|
|
122
|
+
|
|
123
|
+
The following is an example for a separate trusted project, not a change to
|
|
124
|
+
Raft's own runner fleet. An ordinary `ubuntu-latest` job invokes Raft over SSH.
|
|
125
|
+
Before using it, an operator must approve storing a dedicated CI host key as
|
|
126
|
+
`RAFT_SSH_KEY`, verified host-key lines as `RAFT_KNOWN_HOSTS`, and the location
|
|
127
|
+
inventory JSON as `RAFT_INVENTORY`. The inventory's SSH target must use that key
|
|
128
|
+
and its image fingerprint must be pinned. Never generate trust with an unchecked
|
|
129
|
+
`ssh-keyscan` or disable host-key checking. Restrict access to these secrets.
|
|
130
|
+
|
|
131
|
+
The example pins development commit `7d678bb079a9b2dcde4e2eb9e4cd0468d00f50f3` in a
|
|
132
|
+
separate Python environment. Review that code and its unreleased status
|
|
133
|
+
before use; do not silently replace it with a moving branch.
|
|
134
|
+
|
|
135
|
+
```yaml title="EXAMPLE: .github/workflows/trusted-build.yml"
|
|
136
|
+
name: Trusted Raft build
|
|
137
|
+
on:
|
|
138
|
+
push:
|
|
139
|
+
branches: [main]
|
|
140
|
+
workflow_dispatch:
|
|
141
|
+
permissions:
|
|
142
|
+
contents: read
|
|
143
|
+
jobs:
|
|
144
|
+
test:
|
|
145
|
+
runs-on: ubuntu-latest
|
|
146
|
+
timeout-minutes: 20
|
|
147
|
+
env:
|
|
148
|
+
RAFT_NO_UPDATE_CHECK: '1'
|
|
149
|
+
steps:
|
|
150
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
|
|
151
|
+
with:
|
|
152
|
+
persist-credentials: false
|
|
153
|
+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
|
|
154
|
+
with:
|
|
155
|
+
python-version: '3.14'
|
|
156
|
+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
|
157
|
+
with:
|
|
158
|
+
node-version: '24'
|
|
159
|
+
- name: Install reviewed development controller
|
|
160
|
+
run: |
|
|
161
|
+
python -m venv "$RUNNER_TEMP/raft-cli"
|
|
162
|
+
"$RUNNER_TEMP/raft-cli/bin/pip" install "git+https://github.com/Microck/raft.git@7d678bb079a9b2dcde4e2eb9e4cd0468d00f50f3"
|
|
163
|
+
echo "$RUNNER_TEMP/raft-cli/bin" >> "$GITHUB_PATH"
|
|
164
|
+
- name: Configure approved existing access
|
|
165
|
+
env:
|
|
166
|
+
SSH_KEY: ${{ secrets.RAFT_SSH_KEY }}
|
|
167
|
+
KNOWN_HOSTS: ${{ secrets.RAFT_KNOWN_HOSTS }}
|
|
168
|
+
INVENTORY: ${{ secrets.RAFT_INVENTORY }}
|
|
169
|
+
run: |
|
|
170
|
+
umask 077
|
|
171
|
+
mkdir -p ~/.ssh ~/.config/raft
|
|
172
|
+
printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519
|
|
173
|
+
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
174
|
+
printf '%s\n' "$INVENTORY" > ~/.config/raft/incus.json
|
|
175
|
+
printf 'Host *\n BatchMode yes\n StrictHostKeyChecking yes\n IdentitiesOnly yes\n' > ~/.ssh/config
|
|
176
|
+
- name: Run remote tests and collect logs
|
|
177
|
+
run: |
|
|
178
|
+
raft run --location ci --timeout 900 --cpu 2 --memory 4GiB \
|
|
179
|
+
--purpose "Trusted project tests" --owner "GitHub Actions" --next "Delete after tests" \
|
|
180
|
+
--push . --pull /workspace/project/reports ./ci-reports \
|
|
181
|
+
-- bash -lc 'set -euo pipefail; mkdir -p reports; npm ci; npm test 2>&1 | tee reports/test.log'
|
|
182
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
|
183
|
+
if: always()
|
|
184
|
+
with:
|
|
185
|
+
name: test-reports
|
|
186
|
+
path: ci-reports/
|
|
187
|
+
if-no-files-found: warn
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
No checkout credential is needed in the guest. The secret files are outside the
|
|
191
|
+
uploaded tree, and `.git` is excluded. Set a CI job limit longer than Raft's
|
|
192
|
+
command deadline plus collection and cleanup grace. A forcibly terminated CI
|
|
193
|
+
runner cannot perform final cleanup; check the host expiry service and inventory.
|
|
194
|
+
|
|
195
|
+
## Comparison and cost
|
|
196
|
+
|
|
197
|
+
[Boat's CI guide](https://docs.boat.dev/ci) uses the same broad pattern: an existing
|
|
198
|
+
CI job orchestrates a disposable remote workspace. Boat also provides a managed
|
|
199
|
+
`run` command, scoped API keys, renewable leases and a different VM/snapshot
|
|
200
|
+
model. Raft implements a fixed lifetime on operator-owned Incus hosts and uses
|
|
201
|
+
host-level SSH access; these are meaningful differences, not interchangeable
|
|
202
|
+
security or billing guarantees.
|
|
203
|
+
|
|
204
|
+
There is no universal “10x cheaper” claim for Raft. Compare the complete host,
|
|
205
|
+
storage, idle capacity, operations and orchestration-runner cost. Standard
|
|
206
|
+
GitHub-hosted runners are already free for public repositories; remote capacity
|
|
207
|
+
can still help with specific hardware, prepared environments or isolation from
|
|
208
|
+
other trusted jobs. See [Boat pricing](https://docs.boat.dev/pricing) and
|
|
209
|
+
[GitHub Actions billing](https://docs.github.com/en/billing/concepts/product-billing/github-actions).
|
package/docs/guides/files.mdx
CHANGED
|
@@ -5,11 +5,11 @@ description: Transfer files between your controller machine and running Raft wor
|
|
|
5
5
|
|
|
6
6
|
# File transfer
|
|
7
7
|
|
|
8
|
-
Upload and download individual files between your
|
|
8
|
+
Upload and download individual files between your controller and a box over verified host SSH and Incus instance APIs.
|
|
9
9
|
|
|
10
10
|
## Target workspace handle
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use a running box for all examples below. Individual-file transfers also work while stopped; recursive directory transfers require a running box. Select one from `raft list` (see [First working box](../first-box.mdx)):
|
|
13
13
|
|
|
14
14
|
```sh title="CONTROLLER: Select running workspace"
|
|
15
15
|
raft list
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Task guides
|
|
3
|
+
description: Pick a workflow after setting up your first Raft host.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task guides
|
|
7
|
+
|
|
8
|
+
Start with [your first box](../first-box.mdx) if you have not run a command yet.
|
|
9
|
+
Commands run on the controller unless a block is labeled **HOST**.
|
|
10
|
+
|
|
11
|
+
## Develop
|
|
12
|
+
|
|
13
|
+
- [Project setup and templates](./project-setup.mdx): upload a project and reuse dependencies.
|
|
14
|
+
- [Docker](./docker.mdx): build images and manage guest disk use.
|
|
15
|
+
- [File transfer](./files.mdx): copy individual files or directory trees.
|
|
16
|
+
- [Desktop and private services](./desktop-services.mdx): open a browser, desktop or local tunnel.
|
|
17
|
+
|
|
18
|
+
## Automate
|
|
19
|
+
|
|
20
|
+
- [Background jobs](./background-jobs.mdx): detach, inspect logs and cancel.
|
|
21
|
+
- [Lifetime and persistent services](./long-running-services.mdx): set deadlines and restart services after resume.
|
|
22
|
+
- [Scripting and CI](./scripting-ci.mdx): parse output and handle failures.
|
|
23
|
+
- [Disposable CI jobs — unreleased 0.7.0](./ci-jobs.mdx): run and clean up one temporary build.
|
|
24
|
+
|
|
25
|
+
## Operate
|
|
26
|
+
|
|
27
|
+
- [Snapshots and forks](./snapshots-forks.mdx): save disk state or make a same-host copy.
|
|
28
|
+
- [Backup and recovery](./backup-recovery.mdx): move a whole box to a compatible host.
|
|
29
|
+
- [Defaults and policies](./config-policy.mdx): set creation defaults and retention rules.
|
|
30
|
+
- [Upgrades](./upgrades.mdx): update the CLI, host worker and image separately.
|
|
31
|
+
- [Troubleshooting](./troubleshooting.mdx): start from a symptom.
|
|
@@ -11,7 +11,7 @@ terminal, and detached jobs do not extend that deadline automatically.
|
|
|
11
11
|
## Choose a lifetime and retention policy
|
|
12
12
|
|
|
13
13
|
```sh title="CONTROLLER: Create a persistent box"
|
|
14
|
-
box=$(raft new --location lab --ttl 3600)
|
|
14
|
+
box=$(raft new --location lab --ttl 3600 --persistent)
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
TTL is in seconds: 60 to 2,592,000 (30 days), with a creation default of 600.
|
package/docs/guides/meta.json
CHANGED
|
@@ -3,16 +3,21 @@
|
|
|
3
3
|
"collapsible": true,
|
|
4
4
|
"defaultOpen": false,
|
|
5
5
|
"pages": [
|
|
6
|
+
"index",
|
|
7
|
+
"---Develop---",
|
|
6
8
|
"project-setup",
|
|
7
9
|
"docker",
|
|
8
10
|
"files",
|
|
11
|
+
"desktop-services",
|
|
12
|
+
"---Automate---",
|
|
9
13
|
"background-jobs",
|
|
10
14
|
"long-running-services",
|
|
11
15
|
"scripting-ci",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
16
|
+
"ci-jobs",
|
|
17
|
+
"---Operate---",
|
|
14
18
|
"snapshots-forks",
|
|
15
19
|
"backup-recovery",
|
|
20
|
+
"config-policy",
|
|
16
21
|
"upgrades",
|
|
17
22
|
"troubleshooting"
|
|
18
23
|
]
|
|
@@ -15,7 +15,7 @@ service. Commands run as guest root in `/workspace` unless you choose another us
|
|
|
15
15
|
Create a persistent box after [host setup](../operations.mdx):
|
|
16
16
|
|
|
17
17
|
```sh title="CONTROLLER: Create a project box"
|
|
18
|
-
box=$(raft new --location lab --ttl 3600)
|
|
18
|
+
box=$(raft new --location lab --ttl 3600 --persistent)
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
Upload a local project, excluding credentials and files you do not want copied.
|
|
@@ -11,9 +11,28 @@ authentication, and hosts with passwordless sudo. No Raft HTTP API, SDK, or API
|
|
|
11
11
|
exists. Give access only to trusted jobs: the configured SSH account has host sudo
|
|
12
12
|
and controls all boxes on that host.
|
|
13
13
|
|
|
14
|
+
For one-shot builds, [`raft run`](./ci-jobs.mdx) combines allocation, source upload,
|
|
15
|
+
foreground execution, artifact collection and disposable cleanup. It is an
|
|
16
|
+
orchestration command, not a registered CI runner. The manual lifecycle examples
|
|
17
|
+
below remain useful for persistent debugging workflows.
|
|
18
|
+
|
|
14
19
|
## Output formats
|
|
15
20
|
|
|
16
|
-
|
|
21
|
+
The development CLI supports `raft --json COMMAND ...` for JSON Lines output.
|
|
22
|
+
Each event has a `type`: `data` carries a structured `value`; `stdout` and
|
|
23
|
+
`stderr` carry base64-encoded bytes in `data`; `error` carries `code` and
|
|
24
|
+
`message`; the final `exit` carries the process exit `code`. Decode stream events
|
|
25
|
+
in order within each channel. Chunks need not end at line boundaries. This keeps
|
|
26
|
+
binary output intact and streams long-running command output without buffering
|
|
27
|
+
it all. Interactive `ssh`, `forward` and `desktop` reject JSON mode before acting.
|
|
28
|
+
Help/version work without configuration. JSON mode suppresses release notices.
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
raft --json list --location lab | jq 'select(.type == "data") | .value'
|
|
32
|
+
raft --json exec "$BOX" -- sh -c 'echo hello; exit 7'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Without global `--json`, parse each command's format:
|
|
17
36
|
|
|
18
37
|
| Command | stdout |
|
|
19
38
|
| --- | --- |
|
|
@@ -27,9 +46,9 @@ Raft does not have a global `--json` option. Parse each command's actual format:
|
|
|
27
46
|
| `config` | One pretty-printed JSON object with `file`, `defaults`, `policy` |
|
|
28
47
|
| `config set/unset`, `policy` | One line describing the change |
|
|
29
48
|
| `prune` | JSONL candidates or deleted records with `box`, `action` |
|
|
30
|
-
| `status` |
|
|
31
|
-
| `logs` |
|
|
32
|
-
| `exec` | Payload stdout/stderr |
|
|
49
|
+
| `status` | Retained JSON record with `state`, `exitCode`, timestamps and `droppedBytes` |
|
|
50
|
+
| `logs` | First 1 MiB of retained combined output |
|
|
51
|
+
| `exec`, `run` | Payload stdout/stderr; `run` lifecycle diagnostics use stderr |
|
|
33
52
|
| Other inspection/maintenance commands | Human-readable text or no output |
|
|
34
53
|
|
|
35
54
|
`list` emits nothing when there are no boxes. `stopAt` is the host Unix deadline
|
|
@@ -79,10 +98,10 @@ stderr.
|
|
|
79
98
|
|
|
80
99
|
SSH transport failures may return SSH's status rather than the payload's result.
|
|
81
100
|
The foreground tunnel replaces the CLI process with SSH and uses SSH's exit code.
|
|
82
|
-
A zero exit from `status` means the query succeeded
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
[Background jobs](./background-jobs.mdx).
|
|
101
|
+
A zero exit from `status` means the query succeeded. Wait for a terminal `state`
|
|
102
|
+
and read `exitCode`; running, cancelled and interrupted jobs have no confirmed
|
|
103
|
+
payload exit code. Results remain readable after stop or deletion for seven days.
|
|
104
|
+
See [Background jobs](./background-jobs.mdx).
|
|
86
105
|
|
|
87
106
|
## Create, wait, run, and stop
|
|
88
107
|
|
|
@@ -108,7 +127,7 @@ cleanup() {
|
|
|
108
127
|
}
|
|
109
128
|
trap cleanup EXIT
|
|
110
129
|
|
|
111
|
-
box=$(raft new --location lab --ttl 3600)
|
|
130
|
+
box=$(raft new --location lab --ttl 3600 --persistent)
|
|
112
131
|
printf 'Created %s\n' "$box" >&2
|
|
113
132
|
ready=false
|
|
114
133
|
for attempt in {1..30}; do
|
|
@@ -9,7 +9,8 @@ Raft captures filesystem snapshots, rolls back changes, and clones workspaces on
|
|
|
9
9
|
|
|
10
10
|
## Target workspace handle
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Use a **persistent** workspace and stop it first. Stopping a disposable box deletes
|
|
13
|
+
it and its snapshots; do not use one as the source for this walkthrough.
|
|
13
14
|
|
|
14
15
|
```sh title="CONTROLLER: Select and stop target workspace"
|
|
15
16
|
raft list
|
|
@@ -66,6 +67,7 @@ raft resume "$box" --ttl 600
|
|
|
66
67
|
Forking creates an independent clone on the same host:
|
|
67
68
|
|
|
68
69
|
```sh title="CONTROLLER: Fork workspace into a new clone"
|
|
70
|
+
raft stop "$box" # Use a persistent box; stop deletes disposable boxes
|
|
69
71
|
copy=$(raft fork "$box" --ttl 600)
|
|
70
72
|
echo "Created fork: $copy"
|
|
71
73
|
```
|
package/docs/guides/upgrades.mdx
CHANGED
|
@@ -17,7 +17,7 @@ parts of Raft. Updating one does not automatically update the others.
|
|
|
17
17
|
## Choose a release and prepare
|
|
18
18
|
|
|
19
19
|
Review [release notes](https://github.com/Microck/raft/releases) and use matching
|
|
20
|
-
CLI and deployment sources. The examples below pin `v0.
|
|
20
|
+
CLI and deployment sources. The examples below pin `v0.6.0`; replace that version
|
|
21
21
|
consistently when adopting another release.
|
|
22
22
|
|
|
23
23
|
```sh title="CONTROLLER: Inspect the current installation"
|
|
@@ -34,7 +34,7 @@ stopping one. Schedule redeployment when interruptions are acceptable.
|
|
|
34
34
|
## Update the controller
|
|
35
35
|
|
|
36
36
|
`raft self-update` installs the latest release through the channel that
|
|
37
|
-
installed the CLI, and `raft self-update --version 0.
|
|
37
|
+
installed the CLI, and `raft self-update --version 0.6.0` installs a chosen
|
|
38
38
|
one. `raft self-update --check` only reports. For npm installs, npm checks the
|
|
39
39
|
registry integrity hash of a package published with provenance. For uv tools,
|
|
40
40
|
Raft downloads the release wheel and refuses it unless its SHA-256 matches the
|
|
@@ -43,7 +43,7 @@ release `SHA256SUMS`. See [`self-update`](../reference/cli.md#self-update).
|
|
|
43
43
|
To install a release by hand instead, for an npm installation:
|
|
44
44
|
|
|
45
45
|
```sh title="CONTROLLER: Install a pinned CLI release"
|
|
46
|
-
npm install -g @microck/raft@0.
|
|
46
|
+
npm install -g @microck/raft@0.6.0
|
|
47
47
|
raft --version
|
|
48
48
|
```
|
|
49
49
|
|
|
@@ -52,7 +52,7 @@ release, verify the checksum, then install it with `uv`:
|
|
|
52
52
|
|
|
53
53
|
```sh title="CONTROLLER: Install a verified release wheel instead of npm"
|
|
54
54
|
sha256sum --ignore-missing -c SHA256SUMS
|
|
55
|
-
uv tool install --force ./raft-0.
|
|
55
|
+
uv tool install --force ./raft-0.6.0-py3-none-any.whl
|
|
56
56
|
raft --version
|
|
57
57
|
```
|
|
58
58
|
|
|
@@ -71,8 +71,8 @@ reports each host whose worker differs from the new CLI.
|
|
|
71
71
|
Obtain a separate checkout of the matching release:
|
|
72
72
|
|
|
73
73
|
```sh title="CONTROLLER: Obtain and deploy matching host code"
|
|
74
|
-
git clone --branch v0.
|
|
75
|
-
cd raft-v0.
|
|
74
|
+
git clone --branch v0.6.0 https://github.com/Microck/raft.git raft-v0.6.0
|
|
75
|
+
cd raft-v0.6.0
|
|
76
76
|
python3 deploy/deploy.py --location lab
|
|
77
77
|
raft doctor
|
|
78
78
|
```
|
|
@@ -105,7 +105,7 @@ backup's guest filesystem rather than rebuilding it from the new image.
|
|
|
105
105
|
## Verify the update
|
|
106
106
|
|
|
107
107
|
```sh title="CONTROLLER: Smoke-check a new persistent box"
|
|
108
|
-
box=$(raft new --location lab --ttl 600)
|
|
108
|
+
box=$(raft new --location lab --ttl 600 --persistent)
|
|
109
109
|
raft exec "$box" -- node --version
|
|
110
110
|
raft exec "$box" -- docker info
|
|
111
111
|
raft stop "$box"
|
package/docs/index.mdx
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Overview
|
|
3
|
-
description:
|
|
3
|
+
description: Create persistent Linux development boxes on Ubuntu hosts you control.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Raft
|
|
7
7
|
|
|
8
|
-
Raft
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
Raft creates **persistent Linux boxes on your own Ubuntu hosts**. Run commands,
|
|
9
|
+
Docker builds and development services; copy files; save snapshots; or open a
|
|
10
|
+
private desktop. A box is an unprivileged Incus container that shares its host's
|
|
11
|
+
kernel, not a virtual machine.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Start here
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
1. [Check requirements](./requirements.mdx): a Linux controller and a dedicated Ubuntu host.
|
|
16
|
+
2. [Set up a host](./operations.mdx): install the CLI and run guided onboarding.
|
|
17
|
+
3. [Create your first box](./first-box.mdx): run a command, stop it and resume it.
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
Already have a configured host? Run these commands on your **controller**
|
|
20
|
+
(the machine where you installed `raft`). Replace `lab` with your location:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
box=$(raft new --location lab --ttl 600 --persistent)
|
|
19
24
|
raft exec "$box" -- node --version
|
|
20
25
|
raft ssh "$box"
|
|
21
|
-
raft stop "$box"
|
|
22
26
|
```
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
| Set defaults for new boxes, require box note fields or delete boxes left stopped | [Defaults and host policies](./guides/config-policy.mdx) |
|
|
37
|
-
| Forward guest ports or open noVNC desktop | [Desktop and private services](./guides/desktop-services.mdx) |
|
|
38
|
-
| Capture disk state or clone workspaces | [Snapshots and forks](./guides/snapshots-forks.mdx) |
|
|
39
|
-
| Export portable backups across hosts | [Backup and recovery](./guides/backup-recovery.mdx) |
|
|
40
|
-
| Update the CLI, host worker, and workspace image | [Upgrades and image changes](./guides/upgrades.mdx) |
|
|
41
|
-
| Inspect host services and diagnose errors | [Troubleshooting](./guides/troubleshooting.mdx) |
|
|
28
|
+
Exit the guest shell, then run `raft stop "$box"` on the controller. Files remain;
|
|
29
|
+
processes stop. Host retention policies can later delete stopped boxes.
|
|
30
|
+
|
|
31
|
+
## Find a task
|
|
32
|
+
|
|
33
|
+
- [Work with a project](./guides/project-setup.mdx) or [copy files](./guides/files.mdx).
|
|
34
|
+
- [Run Docker](./guides/docker.mdx), [background jobs](./guides/background-jobs.mdx), or [open a desktop](./guides/desktop-services.mdx).
|
|
35
|
+
- [Browse all guides](./guides/index.mdx), [look up a command](./reference/cli.md), or [troubleshoot](./guides/troubleshooting.mdx).
|
|
36
|
+
|
|
37
|
+
Raft is an independent open-source alternative to Boat, not affiliated with it.
|
|
38
|
+
[Compare the trade-offs](./boat-capabilities.md). Setup examples target published
|
|
39
|
+
**0.6.0**; [0.7.0 features](./releases/0.7.0.md) are marked unreleased.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Maintain Raft
|
|
3
|
+
description: Design, verification, release and documentation work for Raft contributors.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Maintain Raft
|
|
7
|
+
|
|
8
|
+
These pages are for changing or releasing Raft, not for creating your first box.
|
|
9
|
+
For everyday use, start with [host setup](../operations.mdx) or the [task guides](../guides/index.mdx).
|
|
10
|
+
|
|
11
|
+
- [Design decisions](../boat-parity-design.md): why Raft uses Incus and host SSH.
|
|
12
|
+
- [Runtime contract](../contract.md): behavior that implementations must preserve.
|
|
13
|
+
- [Verification](../verification.mdx): test commands, evidence and unverified boundaries.
|
|
14
|
+
- [Publishing](../publishing.md): package and image release gates.
|
|
15
|
+
- [Documentation site](../site-development.md): edit, preview and check these docs.
|
|
16
|
+
|
|
17
|
+
Host tests create and delete real workspaces. Read each suite's effects before
|
|
18
|
+
running it, and use dedicated infrastructure you are authorized to change.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Maintainers",
|
|
3
|
+
"collapsible": true,
|
|
4
|
+
"defaultOpen": false,
|
|
5
|
+
"pages": [
|
|
6
|
+
"index",
|
|
7
|
+
"[Design decisions](/docs/boat-parity-design/)",
|
|
8
|
+
"[Verification](/docs/verification/)",
|
|
9
|
+
"[Publishing](/docs/publishing/)",
|
|
10
|
+
"[Documentation site](/docs/site-development/)"
|
|
11
|
+
]
|
|
12
|
+
}
|
package/docs/meta.json
CHANGED
|
@@ -2,20 +2,16 @@
|
|
|
2
2
|
"title": "Raft",
|
|
3
3
|
"pages": [
|
|
4
4
|
"index",
|
|
5
|
-
"---
|
|
5
|
+
"---Get started---",
|
|
6
6
|
"requirements",
|
|
7
7
|
"operations",
|
|
8
8
|
"first-box",
|
|
9
|
+
"---Use Raft---",
|
|
9
10
|
"guides",
|
|
10
11
|
"reference",
|
|
11
|
-
"
|
|
12
|
-
"---Comparison---",
|
|
12
|
+
"---About---",
|
|
13
13
|
"boat-capabilities",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"boat-parity-design",
|
|
17
|
-
"verification",
|
|
18
|
-
"publishing",
|
|
19
|
-
"site-development"
|
|
14
|
+
"maintainers",
|
|
15
|
+
"releases"
|
|
20
16
|
]
|
|
21
17
|
}
|
package/docs/operations.mdx
CHANGED
|
@@ -7,6 +7,8 @@ description: Install the Raft controller CLI, provision a dedicated host, and ac
|
|
|
7
7
|
|
|
8
8
|
Set up a dedicated Ubuntu host, install the Raft CLI, provision Incus, acquire a workspace image, and verify readiness.
|
|
9
9
|
|
|
10
|
+
Examples pin published **0.6.0**. Use matching CLI, deployment scripts and image assets.
|
|
11
|
+
|
|
10
12
|
Review prerequisites in [System requirements](./requirements.mdx) before starting.
|
|
11
13
|
|
|
12
14
|
## Guided onboarding
|
|
@@ -30,6 +32,9 @@ that instead. See [`host add`](./reference/cli.md#host-add) for image options.
|
|
|
30
32
|
|
|
31
33
|
## Manual setup
|
|
32
34
|
|
|
35
|
+
<details>
|
|
36
|
+
<summary>Advanced: provision each component yourself instead of using host add</summary>
|
|
37
|
+
|
|
33
38
|
The steps below are what `raft host add` automates. Follow them to inspect or
|
|
34
39
|
customize each stage.
|
|
35
40
|
|
|
@@ -258,6 +263,8 @@ Check that Incus, the network service, and the expiration timer are active. For
|
|
|
258
263
|
|
|
259
264
|
</Steps>
|
|
260
265
|
|
|
266
|
+
</details>
|
|
267
|
+
|
|
261
268
|
## Next step
|
|
262
269
|
|
|
263
270
|
Proceed to [First working box](./first-box.mdx) to launch, verify, and manage your first workspace.
|