diff --git a/cli/exp_boundary.go b/cli/exp_boundary.go new file mode 100644 index 0000000000..a465e06eda --- /dev/null +++ b/cli/exp_boundary.go @@ -0,0 +1,12 @@ +package cli + +import ( + boundarycli "github.com/coder/boundary/cli" + "github.com/coder/serpent" +) + +func (*RootCmd) boundary() *serpent.Command { + cmd := boundarycli.BaseCommand() // Package coder/boundary/cli exports a "base command" designed to be integrated as a subcommand. + cmd.Use += " [args...]" // The base command looks like `boundary -- command`. Serpent adds the flags piece, but we need to add the args. + return cmd +} diff --git a/cli/exp_boundary_test.go b/cli/exp_boundary_test.go new file mode 100644 index 0000000000..228214e465 --- /dev/null +++ b/cli/exp_boundary_test.go @@ -0,0 +1,33 @@ +package cli_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + boundarycli "github.com/coder/boundary/cli" + "github.com/coder/coder/v2/cli/clitest" + "github.com/coder/coder/v2/pty/ptytest" + "github.com/coder/coder/v2/testutil" +) + +// Actually testing the functionality of coder/boundary takes place in the +// coder/boundary repo, since it's a dependency of coder. +// Here we want to test basically that integrating it as a subcommand doesn't break anything. +func TestBoundarySubcommand(t *testing.T) { + t.Parallel() + ctx := testutil.Context(t, testutil.WaitShort) + + inv, _ := clitest.New(t, "exp", "boundary", "--help") + pty := ptytest.New(t).Attach(inv) + + go func() { + err := inv.WithContext(ctx).Run() + assert.NoError(t, err) + }() + + // Expect the --help output to include the short description. + // We're simply confirming that `coder boundary --help` ran without a runtime error as + // a good chunk of serpents self validation logic happens at runtime. + pty.ExpectMatch(boundarycli.BaseCommand().Short) +} diff --git a/cli/root.go b/cli/root.go index 64c3da672f..c44c0625c2 100644 --- a/cli/root.go +++ b/cli/root.go @@ -145,6 +145,7 @@ func (r *RootCmd) AGPLExperimental() []*serpent.Command { r.promptExample(), r.rptyCommand(), r.tasksCommand(), + r.boundary(), } } diff --git a/go.mod b/go.mod index 934ea364db..b0c3360913 100644 --- a/go.mod +++ b/go.mod @@ -480,6 +480,7 @@ require ( github.com/coder/agentapi-sdk-go v0.0.0-20250505131810-560d1d88d225 github.com/coder/aibridge v0.1.3 github.com/coder/aisdk-go v0.0.9 + github.com/coder/boundary v1.0.1-0.20250925154134-55a44f2a7945 github.com/coder/preview v1.0.4 github.com/dgraph-io/ristretto/v2 v2.3.0 github.com/fsnotify/fsnotify v1.9.0 diff --git a/go.sum b/go.sum index abb051943e..2842cbcc7b 100644 --- a/go.sum +++ b/go.sum @@ -915,6 +915,8 @@ github.com/coder/aibridge v0.1.3 h1:7A9RQaHQUjtse47ShF3kBj2hMmT1R7BEFgiyByr8Vvc= github.com/coder/aibridge v0.1.3/go.mod h1:GWc0Owtlzz5iMHosDm6FhbO+SoG5W+VeOKyP9p9g9ZM= github.com/coder/aisdk-go v0.0.9 h1:Vzo/k2qwVGLTR10ESDeP2Ecek1SdPfZlEjtTfMveiVo= github.com/coder/aisdk-go v0.0.9/go.mod h1:KF6/Vkono0FJJOtWtveh5j7yfNrSctVTpwgweYWSp5M= +github.com/coder/boundary v1.0.1-0.20250925154134-55a44f2a7945 h1:hDUf02kTX8EGR3+5B+v5KdYvORs4YNfDPci0zCs+pC0= +github.com/coder/boundary v1.0.1-0.20250925154134-55a44f2a7945/go.mod h1:d1AMFw81rUgrGHuZzWdPNhkY0G8w7pvLNLYF0e3ceC4= github.com/coder/bubbletea v1.2.2-0.20241212190825-007a1cdb2c41 h1:SBN/DA63+ZHwuWwPHPYoCZ/KLAjHv5g4h2MS4f2/MTI= github.com/coder/bubbletea v1.2.2-0.20241212190825-007a1cdb2c41/go.mod h1:I9ULxr64UaOSUv7hcb3nX4kowodJCVS7vt7VVJk/kW4= github.com/coder/clistat v1.0.0 h1:MjiS7qQ1IobuSSgDnxcCSyBPESs44hExnh2TEqMcGnA=