Skip to content

Commit 6bd3580

Browse files
authored
Move configure cmd to Kong (#602)
* Move configure cmd to Kong * Removed delegate functions to cobra and clean up of cobra implementation of configure * fix configure logic * fix lint errors * Add back asking for token as input prompt * add back the prompts for org and token * Move implementation of bk configure to one package
1 parent f01f293 commit 6bd3580

File tree

6 files changed

+156
-197
lines changed

6 files changed

+156
-197
lines changed

cmd/configure/configure.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package configure
2+
3+
import (
4+
"bufio"
5+
"errors"
6+
"fmt"
7+
"os"
8+
"strings"
9+
10+
"github.com/alecthomas/kong"
11+
"github.com/buildkite/cli/v3/internal/cli"
12+
"github.com/buildkite/cli/v3/internal/io"
13+
"github.com/buildkite/cli/v3/pkg/cmd/factory"
14+
"github.com/buildkite/cli/v3/pkg/cmd/validation"
15+
)
16+
17+
type ConfigureCmd struct {
18+
Org string `help:"Organization slug" optional:""`
19+
Token string `help:"API token" optional:""`
20+
Force bool `help:"Force setting a new token" optional:""`
21+
Default ConfigureDefaultCmd `cmd:"" optional:"" help:"Configure Buildkite API token" hidden:"" default:"1"`
22+
Add ConfigureAddCmd `cmd:"" optional:"" help:"Add configuration for a new organization"`
23+
}
24+
25+
type ConfigureDefaultCmd struct {
26+
}
27+
28+
type ConfigureAddCmd struct {
29+
}
30+
31+
func (c *ConfigureAddCmd) Help() string {
32+
return `
33+
Examples:
34+
# Prompt configuration to add for a new organization
35+
$ bk configure add
36+
37+
# Add configure Buildkite API token
38+
$ bk configure add --org my-org --token my-token
39+
`
40+
}
41+
42+
func (c *ConfigureCmd) Help() string {
43+
return `
44+
Examples:
45+
# Configure Buildkite API token
46+
$ bk configure --org my-org --token my-token
47+
48+
# Force setting a new token
49+
$ bk configure --force --org my-org --token my-token
50+
`
51+
}
52+
53+
func (c *ConfigureCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error {
54+
f, err := factory.New()
55+
56+
if err != nil {
57+
return err
58+
}
59+
60+
f.SkipConfirm = globals.SkipConfirmation()
61+
f.NoInput = globals.DisableInput()
62+
f.Quiet = globals.IsQuiet()
63+
64+
if err := validation.ValidateConfiguration(f.Config, kongCtx.Command()); err != nil {
65+
return err
66+
}
67+
68+
if kongCtx.Command() == "configure default" {
69+
if !c.Force && f.Config.APIToken() != "" {
70+
return errors.New("API token already configured. You must use --force")
71+
}
72+
73+
}
74+
75+
// If flags are provided, use them directly
76+
if c.Org != "" && c.Token != "" {
77+
return ConfigureWithCredentials(f, c.Org, c.Token)
78+
}
79+
80+
return ConfigureRun(f, c.Org)
81+
}
82+
83+
func ConfigureWithCredentials(f *factory.Factory, org, token string) error {
84+
if err := f.Config.SelectOrganization(org, f.GitRepository != nil); err != nil {
85+
return err
86+
}
87+
return f.Config.SetTokenForOrg(org, token)
88+
}
89+
90+
func ConfigureRun(f *factory.Factory, org string) error {
91+
// Check if we're in a Git repository
92+
if f.GitRepository == nil {
93+
return errors.New("not in a Git repository - bk should be configured at the root of a Git repository")
94+
}
95+
96+
if org == "" {
97+
// Get organization slug
98+
inputOrg, err := promptForInput("Organization slug: ", false)
99+
100+
if err != nil {
101+
return err
102+
}
103+
if inputOrg == "" {
104+
return errors.New("organization slug cannot be empty")
105+
}
106+
org = inputOrg
107+
}
108+
// Check if token already exists for this organization
109+
existingToken := getTokenForOrg(f, org)
110+
if existingToken != "" {
111+
fmt.Printf("Using existing API token for organization: %s\n", org)
112+
return f.Config.SelectOrganization(org, f.GitRepository != nil)
113+
}
114+
115+
// Get API token with password input (no echo)
116+
token, err := promptForInput("API Token: ", true)
117+
if err != nil {
118+
return err
119+
}
120+
if token == "" {
121+
return errors.New("API token cannot be empty")
122+
}
123+
124+
fmt.Println("API token set for organization:", org)
125+
return ConfigureWithCredentials(f, org, token)
126+
}
127+
128+
// getTokenForOrg retrieves the token for a specific organization from the user config
129+
func getTokenForOrg(f *factory.Factory, org string) string {
130+
return f.Config.GetTokenForOrg(org)
131+
}
132+
133+
// promptForInput handles terminal input with optional password masking
134+
func promptForInput(prompt string, isPassword bool) (string, error) {
135+
fmt.Print(prompt)
136+
137+
if isPassword {
138+
return io.ReadPassword()
139+
} else {
140+
// Use standard input for regular text
141+
reader := bufio.NewReader(os.Stdin)
142+
input, err := reader.ReadString('\n')
143+
if err != nil {
144+
return "", err
145+
}
146+
// Trim whitespace and newlines
147+
return strings.TrimSpace(input), nil
148+
}
149+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package add
1+
package configure
22

33
import (
44
"testing"
@@ -136,7 +136,7 @@ func TestConfigureRequiresGitRepository(t *testing.T) {
136136
// Create a factory with nil GitRepository (simulating not being in a git repo)
137137
f := &factory.Factory{Config: conf, GitRepository: nil}
138138

139-
err := ConfigureRun(f)
139+
err := ConfigureRun(f, "test-org")
140140

141141
if err == nil {
142142
t.Error("expected error when not in a git repository, got nil")

main.go

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/buildkite/cli/v3/cmd/artifacts"
1212
"github.com/buildkite/cli/v3/cmd/build"
1313
"github.com/buildkite/cli/v3/cmd/cluster"
14+
"github.com/buildkite/cli/v3/cmd/configure"
1415
bkInit "github.com/buildkite/cli/v3/cmd/init"
1516
"github.com/buildkite/cli/v3/cmd/job"
1617
"github.com/buildkite/cli/v3/cmd/organization"
@@ -109,56 +110,10 @@ type (
109110
api.ApiCmd `cmd:"" help:"Interact with the Buildkite API"`
110111
}
111112
ConfigureCmd struct {
112-
Args []string `arg:"" optional:"" passthrough:"all"`
113+
configure.ConfigureCmd `cmd:"" help:"Configure Buildkite API token"`
113114
}
114115
)
115116

116-
// Delegation methods, we should delete when native Kong implementations ready
117-
func (c *ConfigureCmd) Run(cli *CLI) error { return cli.delegateToCobraSystem("configure", c.Args) }
118-
119-
// delegateToCobraSystem delegates execution to the legacy Cobra command system.
120-
// This is a temporary bridge during the Kong migration that ensures backwards compatibility
121-
// by reconstructing global flags that Kong has already parsed.
122-
func (cli *CLI) delegateToCobraSystem(command string, args []string) error {
123-
// Preserve and restore original args for safety
124-
originalArgs := os.Args
125-
defer func() { os.Args = originalArgs }()
126-
127-
// Reconstruct command args with global flags for Cobra compatibility
128-
reconstructedArgs := cli.buildCobraArgs(command, args)
129-
os.Args = reconstructedArgs
130-
131-
if code := runCobraSystem(); code != 0 {
132-
os.Exit(code)
133-
}
134-
return nil
135-
}
136-
137-
// buildCobraArgs constructs the argument slice for Cobra, including global flags.
138-
// Kong parses and consumes global flags before delegation, so we need to reconstruct
139-
// them to maintain backwards compatibility with Cobra commands.
140-
func (cli *CLI) buildCobraArgs(command string, passthroughArgs []string) []string {
141-
args := []string{os.Args[0], command}
142-
143-
if cli.Yes {
144-
args = append(args, "--yes")
145-
}
146-
if cli.NoInput {
147-
args = append(args, "--no-input")
148-
}
149-
if cli.Quiet {
150-
args = append(args, "--quiet")
151-
}
152-
// TODO: Add verbose flag reconstruction when implemented
153-
// if cli.Verbose {
154-
// args = append(args, "--verbose")
155-
// }
156-
157-
args = append(args, passthroughArgs...)
158-
159-
return args
160-
}
161-
162117
func runCobraSystem() int {
163118
f, err := factory.New()
164119
if err != nil {
@@ -315,6 +270,9 @@ func isHelpRequest() bool {
315270
if len(os.Args) >= 2 && os.Args[1] == "user" {
316271
return false
317272
}
273+
if len(os.Args) >= 2 && os.Args[1] == "configure" {
274+
return false
275+
}
318276

319277
if len(os.Args) == 3 && (os.Args[2] == "-h" || os.Args[2] == "--help") {
320278
return true

pkg/cmd/configure/add/add.go

Lines changed: 0 additions & 100 deletions
This file was deleted.

pkg/cmd/configure/configure.go

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)