diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3997e66 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + go: + name: Go + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Set up Go + uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 + with: + go-version-file: go.mod + + # -buildvcs=false matches the Makefile. Go fails the build when VCS + # metadata is unavailable, which includes the default shallow checkout + # and this repo's linked worktrees. The CLI version comes from -ldflags. + # + # internal/docker's live helper tests run only when TX9_TEST_DOCKER_IMAGE + # names an already installed shell image. Leave it unset so this job does + # not pull images or start containers. See CONTRIBUTING.md. + - name: gofmt + run: | + unformatted="$(gofmt -l .)" + if [ -n "$unformatted" ]; then + printf 'gofmt: unformatted files:\n%s\n' "$unformatted" >&2 + exit 1 + fi + + - name: go vet + run: go vet -buildvcs=false ./... + + - name: go build + run: go build -buildvcs=false -o "${RUNNER_TEMP}/tx9" . + + - name: go test + run: go test -buildvcs=false ./... diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..49dcbd8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,86 @@ +# Contributing + +## Prerequisites + +- Go 1.26.7 or newer, matching the `go` line in `go.mod` +- GNU Make +- Bash, Python 3 with PyYAML, jq, gzip, and tar (the shell regression suite) +- ShellCheck 0.11.0 (`make lint` and `make check`) +- A Docker daemon only when you run a box, or the optional integration tests below + +Builds pass `-buildvcs=false`. A shallow checkout or a linked git worktree can +make Go's VCS stamping fail, and the CLI version is set with `-ldflags`. + +## Build + +```bash +make tx9 +``` + +That writes `bin/tx9` (gitignored). The same build by hand: + +```bash +go build -buildvcs=false -ldflags "-X github.com/davis7dotsh/tx9/internal/version.Version=dev" -o bin/tx9 . +``` + +`go install github.com/davis7dotsh/tx9@latest` installs a published module +version. A source build reports version `dev` and tags its image `tx9-box:dev`. + +The binary embeds `box.env`, `provision/`, `guest/`, and `docker/` at compile +time. Rebuild after editing those files before the next `tx9 create` or +`tx9 upgrade`. + +Cross-compile the four release binaries and `checksums.txt` into `dist/`: + +```bash +make dist VERSION=0.12.1 +``` + +## Test + +`make check` is the full local gate: shell syntax, ShellCheck, guest +regressions, a gofmt check, `go vet`, and `go test ./...`. + +```bash +make check +make go-check # gofmt, go vet, go test only +make format # gofmt -w . +``` + +GitHub Actions (`.github/workflows/ci.yml`) runs the same gofmt check, +`go vet -buildvcs=false ./...`, `go build -buildvcs=false`, and +`go test -buildvcs=false ./...` on pull requests and on pushes to `main`. + +`.depot/workflows/check.yml` runs `make check` and the `site/` Worker checks +on Depot. Changes under `guest/`, `provision/`, `docker/`, `scripts/`, or +`tests/` still need `make check` locally. + +### Docker integration tests + +`TestEphemeralDockerIntegration` and `TestExecDockerIntegration` talk to a +live daemon. `go test` skips them unless `TX9_TEST_DOCKER_IMAGE` is an image +already present locally that provides `/bin/sh`, `cat`, `ls`, and `sleep`. +The tests create disposable containers and do not mount host data. CI leaves +the variable unset. + +```bash +TX9_TEST_DOCKER_IMAGE=ubuntu:24.04 go test -buildvcs=false ./internal/docker/ +``` + +`make go-check` and `make check` pick up the same variable when it is set in +the environment. + +## Makefile targets + +| Target | What it runs | +| --- | --- | +| `syntax` | `bash -n` / `sh -n`, and a Python compile of the guest and release scripts | +| `lint` | ShellCheck on the bash scripts, and on `scripts/install.sh` as POSIX sh | +| `test` | `tests/static.sh`, `tests/hermes-state.sh`, and `tests/regressions-*.sh` | +| `go-check` | gofmt check, `go vet ./...`, `go test ./...` | +| `check` | `syntax`, `lint`, `test`, and `go-check` | +| `format` | `gofmt -w .` | +| `tx9` | Build `bin/tx9` | +| `dist` | Cross-compile release binaries into `dist/` (`VERSION=` stamps the binary) | + +`make test` is the shell suite. The Go tests are `make go-check`. diff --git a/README.md b/README.md index dc931a7..bb9895e 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,48 @@ Separate containers do not keep Executor credentials confidential from that agent. Read the [security model](docs/security-model.md) before connecting sensitive accounts or host storage. +## Install + +Prerequisites: a running Docker daemon your user can access. Release binaries +are Linux and macOS, amd64 and arm64. The first `tx9 create` builds the box +image on that daemon. The build takes several minutes and is cached after that. + +Install the current release into `~/.local/bin` (`TX9_INSTALL_DIR` overrides +the directory). The installer prints a `PATH` line when that directory is +absent from `PATH`: + +```bash +curl -fsSL https://tx9.col-agents.com/install | sh +tx9 version +``` + +Or install a published module version. This needs the Go version in `go.mod` +(1.26.7 or newer): + +```bash +go install github.com/davis7dotsh/tx9@latest +``` + +Or build from a checkout. `make tx9` writes `./bin/tx9`: + +```bash +make tx9 +./bin/tx9 version +``` + +A source build reports version `dev` and tags its image `tx9-box:dev`. + +Create a box, then open a shell in the agent container. With no name, `tx9 +create` generates one and prints it: + +```bash +tx9 create my-box +tx9 list +tx9 enter my-box +``` + +Build, test, and Makefile details are in [CONTRIBUTING.md](CONTRIBUTING.md). + The [October 2026 reliability and performance pass](docs/audit-2026-10-04.md) records the latest fixes and measurements. The [August 2026 audit](docs/audit-2026-08-27.md) records earlier validation and remaining decisions. Package versions and earlier @@ -255,10 +297,17 @@ toolchain declared in `go.mod`, and Node 22.18 or newer with npm. Go modules and npm packages must be available or downloaded first. With an older Go 1.26 patch release installed, `go` downloads the declared toolchain on first use unless `GOTOOLCHAIN=local` is set, in which case the build fails instead. -Docker integration tests are optional; setting `TX9_TEST_DOCKER_IMAGE` to an -already installed image with `/bin/sh`, `cat`, `ls`, and `sleep` enables -disposable helper tests. The audit used an existing `ubuntu:24.04` image. +Set `TX9_TEST_DOCKER_IMAGE` to run the live Docker helper tests. The image +must already be installed and must provide `/bin/sh`, `cat`, `ls`, and +`sleep`. Without that variable, `go test ./...` skips them, including on +GitHub Actions: + +```bash +TX9_TEST_DOCKER_IMAGE=ubuntu:24.04 go test -buildvcs=false ./internal/docker/ +``` +`.github/workflows/ci.yml` runs gofmt, `go vet`, `go build`, and +`go test ./...` on pull requests and pushes to `main`. `.depot/workflows/check.yml` runs the Go/guest and site checks through Depot CI for pushes to `main` and pull requests against any branch, including stacks.