feat: Go harness CLI with provider validation#12
Merged
Conversation
…alidation Cobra CLI replacing the bash bin/harness dispatcher. All 7 subcommands registered: new, connect, deploy, teardown, preflight, providers, test. The `new --local` path is implemented natively in Go — parses profile TOML, validates that profile providers are registered on the gateway (✓/✗ for each), stages env + GWS creds, creates sandbox with retry. Remote path and other subcommands delegate to existing bash scripts. Package structure: - internal/profile/ — Config struct, TOML parsing, ValidateProviders, StageHarnessDir (6 unit tests) - internal/runner/ — RunScript, RunCLI, Exec helpers for os/exec - cmd/ — one file per subcommand Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All OpenShell CLI calls now go through the gateway.Gateway interface: InferenceGet, ProviderGet, ProviderList, SandboxCreate, SandboxDelete, SandboxConnect, SandboxUpload, SandboxExec. gateway.CLI implements the interface by shelling out to the openshell binary. A future gateway.GRPC implementation can swap in by changing one line (NewCLI → NewGRPC). ValidateProviders now takes a gateway.Gateway instead of a CLI path string. Tests use a mockGateway (3 new test cases). Runner package simplified to just RunScript (bash wrapper helper). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Unit tests (no gateway needed):
- 11 gateway CLI tests — stub-based: output parsing, arg building,
provider get/list, inference check, sandbox create args
- 7 command tests — mock gateway: no gateway, missing providers,
all providers missing, bad profile, retry logic, create opts
- 10 profile tests (existing)
Integration tests (test-flow.sh):
- --go flag runs same flow through Go binary instead of bash scripts
- step_fail helper for expected-failure assertions
- Error scenarios: bad profile, no gateway, teardown idempotency,
missing providers (all run in both bash and Go paths)
- Full matrix: {bash,go} x {podman,ocp} via make targets
Makefile:
- test-unit: fast unit tests (Go + bats, no gateway)
- test-go-podman / test-go-ocp: Go binary integration
- test-all: all 4 combinations with image rebuilds
Total: 28 Go harness tests + 7 launcher tests + 29 bats = 64 unit tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three fixes discovered by OCP integration tests: 1. Dockerfile: use UBI9-minimal + openssh-clients (not scratch/distroless). The openshell CLI is dynamically linked against glibc and shells out to ssh for sandbox connections. 2. metadata.json: read-then-patch instead of overwrite. The openshell CLI writes fields like gateway_type that it needs later. Overwriting with only gateway_endpoint + auth_mode caused "Unknown gateway" errors. 3. K8s volume mounts: skip dotfiles (..data, ..2024_*) when copying from Secret-mounted directories. These are K8s internal symlinks. 4. Job YAML: add emptyDir volume for /tmp so the launcher has a writable tmpdir regardless of OpenShift security policies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UBI9 has a writable /tmp by default — the emptyDir volume mount and Go-side os.MkdirAll(home) were only needed for scratch/distroless bases. Revert staging dir to /tmp/openshell. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
bin/harnessdispatcher. All 7 subcommands:new,connect,deploy,teardown,preflight,providers,test.harness new --localimplemented natively in Go — parses profile TOML, validates profile providers against the gateway (✓/✗ per provider), stages env + GWS creds, creates sandbox with retry.internal/gateway/) abstracts all OpenShell CLI calls behind an interface. CLI implementation shells out toopenshell; swap to gRPC later by changing one line.{bash,go}×{podman,ocp}.Package structure
Test results
Test targets
Test plan
make test-unit— 64/64 passmake test-podman— 19/19 pass (bash + podman)test-flow.sh podman --full --go— 19/19 pass (Go + podman)test-flow.sh ocp --full— 17/17 pass (bash + OCP)test-flow.sh ocp --full --go— not yet run (Go + OCP)🤖 Generated with Claude Code