Skip to content

Absorb captain-cli into rwx test commands#385

Draft
robinaugh wants to merge 7 commits intomainfrom
jason/absorb-captain
Draft

Absorb captain-cli into rwx test commands#385
robinaugh wants to merge 7 commits intomainfrom
jason/absorb-captain

Conversation

@robinaugh
Copy link
Contributor

@robinaugh robinaugh commented Feb 27, 2026

Note: 66,682 lines are isolated in the first commit, which is a straight copy from the Captain repo's internal package.

Tentative next steps are to migrate RWX's own use of captain run to use rwx test run on an unstable build of the CLI before releasing this.

Summary

Ports the captain-cli command layer into the RWX CLI under rwx test, rebranding all user-facing references from "Captain" to "rwx test" / "RWX", and cleaning up integration issues.

Key changes:

  • Copies captain-cli internal packages into internal/captain/ and registers them as rwx test subcommands
  • Renames all user-facing "Captain" references (help text, error messages, log output, report labels) to "rwx test" / "RWX"
  • Moves config and storage directory from .captain/ to .rwx/test/ (e.g. .captain/config.yml.rwx/test/config.yml)
  • Migrates CAPTAIN_* environment variables to RWX_TEST_* with backwards-compatible fallbacks
  • Removes commands not needed in the RWX CLI (add, update, remove, quarantine)
  • Removes OSS mode entirely: the local file-based backend (internal/captain/backend/local/), the cloud.disabled config option, the --update-stored-results flag, and all OSS fallback code are dropped. rwx test now requires an RWX access token — users who need OSS mode should stay on the original captain CLI.
  • Restructures rwx test parse resultsrwx test results parse and rwx test mergerwx test results merge
  • Auto-derives git metadata (--who, --branch, --sha) from the local repo for local runs
  • Resolves access tokens from the file backend so rwx login tokens work with test commands
  • Fixes: file descriptor leak in config parsing, misleading error messages, path separator issues on Windows, inconsistent error decoration

Command migration

Run a test suite

# Captain
captain run --suite-id my-suite -c "bundle exec rspec"

# RWX
rwx test run --suite-id my-suite -c "bundle exec rspec"

Run with test results file

# Captain
captain run --suite-id my-suite --test-results jest-result.json -c jest

# RWX
rwx test run --suite-id my-suite --test-results jest-result.json -c jest

Parse test results

# Captain
captain parse results --suite-id my-suite --test-results rspec.json --framework rspec --language ruby

# RWX
rwx test results parse --suite-id my-suite --test-results rspec.json --framework rspec --language ruby

Merge partitioned results

# Captain
captain merge "results-*.json"

# RWX
rwx test results merge "results-*.json"

Partition a test suite

# Captain
captain partition --suite-id my-suite --index 0 --total 4 spec/**/*_spec.rb

# RWX
rwx test partition --suite-id my-suite --index 0 --total 4 spec/**/*_spec.rb

Config file

# Captain
.captain/config.yml

# RWX
.rwx/test/config.yml

Environment variables

Captain RWX
CAPTAIN_SUITE_ID RWX_TEST_SUITE_ID
CAPTAIN_SHA RWX_TEST_SHA
CAPTAIN_BRANCH RWX_TEST_BRANCH
CAPTAIN_WHO RWX_TEST_WHO
CAPTAIN_COMMIT_MESSAGE RWX_TEST_COMMIT_MESSAGE
CAPTAIN_BUILD_URL RWX_TEST_BUILD_URL
CAPTAIN_TITLE RWX_TEST_TITLE
CAPTAIN_DELIMITER RWX_TEST_DELIMITER

All CAPTAIN_* env vars continue to work as fallbacks for backwards compatibility.

Test plan

Command surface

  • rwx --help does not show test as a visible subcommand
  • rwx test --help shows run, partition, results subcommands; no add, remove, update, or quarantine
  • rwx test results --help shows parse and merge subcommands
  • Removed commands (add, remove, update, quarantine) are not registered

PersistentPreRunE skip for test subcommands

  • rwx test run --help, rwx test partition --help, rwx test results parse --help, rwx test results merge --help all produce help output without Docker/SSH/API init errors (even with RWX_ACCESS_TOKEN unset)
  • Non-test commands (e.g. rwx run --help) still run root init normally

Access token resolution

  • rwx login token is picked up by test commands without RWX_ACCESS_TOKEN set
  • Explicit RWX_ACCESS_TOKEN env var overrides the stored token
  • Running without any access token produces a clear error directing users to set RWX_ACCESS_TOKEN or run rwx login

OSS mode removed

  • No --update-stored-results flag on rwx test run
  • cloud.disabled in config file produces a parse error (unknown field)
  • No local file-based backend code exists (internal/captain/backend/local/ deleted)

Auto-derive git metadata

  • Running in a git repo without --who, --branch, --sha auto-derives values from the local repo
  • Explicit --who, --sha, --branch flags override auto-derived values

Branding — "Captain" references removed

  • Help text descriptions say "rwx test", not "Captain" (only CAPTAIN_* env var names remain for backwards compat)
  • Error messages say "rwx test requires..." not "Captain requires..."

User-Agent header

  • --test-debug output shows rwx-cli/dev user-agent, not captain-cli/unset

rwx test results parse

  • Parses RSpec, go test, Jest, and Pytest fixtures into valid RWX v1 JSON
  • Missing positional arg produces a clear error

rwx test results merge

  • Merges partitioned result files and prints summary

rwx test partition

  • Round-robin partitioning across indices produces complementary file subsets

Config file discovery

  • Auto-discovers .rwx/test/config.yaml and applies suite config
  • --config-file flag works for explicit config path
  • CLI flags override config file values
  • Config discovery works from subdirectories (walks up to find .rwx/test/)
  • Invalid YAML produces a formatted parsing error, not a panic

Error handling

  • Missing required --suite-id produces a formatted error
  • Exit code from the test command is passed through (e.g. exit 42 → exit code 42)

Environment variable migration

  • Legacy CAPTAIN_* env vars still work when RWX_TEST_* are unset

Regression

  • rwx --help, rwx run --help, rwx login --help are unaffected
  • go test ./internal/... ./cmd/... passes

@robinaugh robinaugh self-assigned this Feb 27, 2026
@robinaugh robinaugh force-pushed the jason/absorb-captain branch from 9106fd9 to d1544cb Compare February 28, 2026 20:32
Copies all of captain-cli's internal/ packages (~111 source files) into
internal/captain/, preserving directory structure. Also copies version.go
and test fixtures needed by the test suite.

All imports rewritten from github.com/rwx-research/captain-cli/internal/
to github.com/rwx-cloud/cli/internal/captain/. One test path adjusted
for the extra directory depth (fs/local_test.go ../../go.mod ->
../../../go.mod).
Adds direct dependencies required by the absorbed captain packages:
zap (logging), gomega/ginkgo (testing), shellwords, doublestar (globs),
stripansi, semver, wordwrap, sync, and others. Go version remains 1.24
as the captain code does not require 1.25 features.
Removes functions and tests that were only used by the captain CLI
commands we don't need (add, remove, quarantine, update):
- parseFlags, AddFlake, AddQuarantine, RemoveFlake, RemoveQuarantine,
  UploadTestResults, UpdateTestResults and all associated tests
@robinaugh robinaugh force-pushed the jason/absorb-captain branch from d1544cb to fe5fef0 Compare March 1, 2026 13:22
Ports the captain-cli run command as `rwx test run`, including:
- Test suite execution with retries, result uploads, and partitioning
- Config file discovery and parsing (.captain/config.yaml)
- Captain error handling bridge in main.go
- Access token resolution from file backend
- Auto-derivation of git metadata for local runs
- Identity recipes for framework detection

Also includes all internal captain package updates needed to rename
Captain references to RWX and wire up env var fallbacks
(RWX_TEST_ with CAPTAIN_ backwards compatibility).
Adds `rwx test results parse` to parse test result files into RWX v1
JSON, and `rwx test results merge` to combine partitioned test results
into a single file.
Adds `rwx test partition` to split tests across partitions using
historical timing data or round-robin distribution.
Ginkgo v2 rejects `go test -parallel`, so captain tests are split into
their own CI task without the flag while non-captain tests retain
`-parallel 4` for performance.
@robinaugh robinaugh force-pushed the jason/absorb-captain branch from fe5fef0 to 2eef374 Compare March 1, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant