119 lines
6.1 KiB
Markdown
119 lines
6.1 KiB
Markdown
# box
|
||
|
||
`box` runs builds and tests in disposable containers through the containers service at `citadel.vpn.surma.technology:8093`.
|
||
All network operations use standard `wasi:http`. The component has no Sausage host imports.
|
||
|
||
## Commands
|
||
|
||
```sh
|
||
box create [--flake reference] [--ttl seconds]
|
||
box exec ID [--timeout seconds] [--inline-bytes bytes] -- COMMAND ARGUMENTS...
|
||
box put ID WORLD_PATH BOX_PATH
|
||
box get ID BOX_PATH WORLD_PATH
|
||
box logs ID
|
||
box ls
|
||
box rm ID
|
||
```
|
||
|
||
Every command accepts `--host hostname[:port]`. The default port is 8093.
|
||
Create remembers the host in `/var/lib/box/hosts/<id>`. Separate files prevent unrelated creates from replacing each other’s mappings.
|
||
Other commands use the remembered host unless `--host` overrides it. Unknown IDs use the default service.
|
||
Host mappings remain after deletion for diagnostics. They contain no credentials.
|
||
|
||
Create prints the ID and waits up to 240 seconds for readiness.
|
||
Without a flake, it uses v2’s Node/NixOS configuration with Node, npm, Git, Chromium, fonts, and tar.
|
||
A flake selects a service-side configuration, for example `github:OWNER/REPO#container`.
|
||
TTL is positive seconds from creation. The service defaults to 3600 seconds.
|
||
A failed or timed-out create reports its accepted ID. Do not repeat create blindly. Inspect logs and remove that ID.
|
||
|
||
Exec runs as root. It passes an argv array without shell interpolation.
|
||
For shell syntax, use `-- sh -c 'COMMAND'`. The timeout defaults to 60 seconds and accepts 1 through 1800 seconds.
|
||
Exec prints stdout and stderr separately and returns the command’s exit code.
|
||
It does not consume local stdin. Use put for inputs.
|
||
|
||
Put detects a local directory. Get detects a remote directory.
|
||
File transfers support binary bytes and a 64 MiB limit. Downloads replace a destination file only after complete validation.
|
||
Tree transfers use an uncompressed tar with a 64 MiB limit. Put merges into a box directory.
|
||
Get requires a new world directory and publishes it only after complete extraction.
|
||
The port preserves v2’s portable file modes and hardlink materialization.
|
||
Get rejects symlinks because the world VFS cannot create them. Export a dereferenced tree when necessary.
|
||
Special files and paths outside the destination fail explicitly.
|
||
Temporary tar files disappear after a transfer, including failures where cleanup remains possible.
|
||
|
||
## Build a pnpm project in a box
|
||
|
||
```sh
|
||
id=$(box create --ttl 1800)
|
||
box put "$id" /repos/project /work
|
||
box exec "$id" --timeout 600 -- sh -c 'cd /work && npm install --global pnpm && pnpm install --frozen-lockfile && pnpm test && pnpm build'
|
||
box get "$id" /work/dist /repos/project-dist
|
||
box logs "$id"
|
||
box rm "$id"
|
||
```
|
||
|
||
Use the same ID to inspect failed builds. Always remove disposable boxes when the work ends.
|
||
Boxes have open network access. The world’s host credential boundary remains unchanged.
|
||
|
||
## Output retention
|
||
|
||
The CLI preserves v2’s full output archives independently of presentation.
|
||
It downloads both raw streams for new-service executions, including small and binary output.
|
||
Files live under `/logs/box/YYYY-MM-DD/<id>-<exec>.stdout` and `.stderr`.
|
||
Collision snapshots receive unique suffixes. Existing archives never change.
|
||
Result JSON retains original service excerpts before the CLI bounds presentation.
|
||
The CLI prints archive paths and availability notices on stderr.
|
||
|
||
Each displayed stream defaults to a 16 KiB UTF-8 head and tail budget.
|
||
The omission marker is outside that budget. `--inline-bytes 0` prints only the marker for nonempty output.
|
||
A larger budget reads archives, not an already-truncated service excerpt. UTF-8 replacement remains bounded.
|
||
Full archives have no retention cap. Transfer limits do not cap execution archives.
|
||
|
||
Downloads request 1 MiB ranges and validate every Content-Range page and exact byte total.
|
||
They also accept a complete 200 response from a server that ignores Range.
|
||
A shared deadline allows 60 seconds plus one second per 256 KiB of combined output, capped at 30 minutes.
|
||
Unknown totals receive five minutes. Only immutable archive GETs retry. Exec POSTs never retry.
|
||
Incomplete archives retain `.partial` names. Only complete, flushed downloads receive published paths.
|
||
|
||
Build logs try `/log/full`. Only 404 or 405 triggers `/log` fallback.
|
||
The CLI retains all available raw build bytes and displays at most their last 16 KiB.
|
||
A fallback warning states that earlier bytes may be unavailable.
|
||
Failed creates archive build diagnostics. Explicit removal attempts a build snapshot but proceeds if that snapshot fails.
|
||
|
||
Old services expose only JSON stream text. The CLI saves all available text before presentation limits.
|
||
It warns when upstream truncation discarded bytes. Those missing bytes cannot be restored.
|
||
Archive failures return the completed command and an availability notice. Never replay a command to repair its archive.
|
||
|
||
## Build and validation
|
||
|
||
Build the shared startup object from the repository root:
|
||
|
||
```sh
|
||
nix develop -c nu --no-config-file userland/cwd-init/build.nu
|
||
```
|
||
|
||
Run the following commands from `userland/` so Cargo loads the shared startup and numeric exit support:
|
||
|
||
```sh
|
||
df -h /
|
||
export CARGO_TARGET_DIR=/home/surma/src/gitea.surma.technology/surma/sausage/target/p1-tools
|
||
nix develop -c cargo build -p box-cli --target wasm32-wasip2 --release --locked
|
||
nix develop -c kache stats
|
||
nix develop -c nu box/test.nu
|
||
```
|
||
|
||
The existing `userland/bundle.nu` discovers the workspace member and copies its `box` binary into `/bin`.
|
||
It applies the same cwd initializer as other bundled programs.
|
||
|
||
Keep the same target directory for tests. Do not override `CARGO_HOME` or `RUSTC_WRAPPER`.
|
||
Stop before a build if disk use exceeds 85%.
|
||
Run pure unit tests with the native target from `rustc -vV`, for example:
|
||
|
||
```sh
|
||
nix develop -c cargo test -p box-cli --target aarch64-unknown-linux-gnu --locked
|
||
```
|
||
|
||
The real-service script tests every required command and removes every created box, including after an assertion failure.
|
||
It round-trips files and nested trees, runs a tiny Node project through npm test, and retrieves its result.
|
||
It also verifies large binary archive retention and WASI-only component imports.
|
||
The script preserves its temporary world and archives as evidence.
|