Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added cli
Binary file not shown.
4 changes: 2 additions & 2 deletions internal/build/resolver/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestParseBuildArg(t *testing.T) {
t.Parallel()

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing")
conf.SelectOrganization("testing", true)
res := func(context.Context) (*pipeline.Pipeline, error) {
return &pipeline.Pipeline{
Name: testcase.pipeline,
Expand Down Expand Up @@ -71,7 +71,7 @@ func TestParseBuildArg(t *testing.T) {
t.Parallel()

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing")
conf.SelectOrganization("testing", true)
f := resolver.ResolveFromPositionalArgument([]string{"https://buildkite.com/"}, 0, nil, conf)
build, err := f(context.Background())
if err == nil {
Expand Down
15 changes: 12 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,13 @@ func (conf *Config) OrganizationSlug() string {
)
}

// SelectOrganization sets the selected organization in the local configuration file
func (conf *Config) SelectOrganization(org string) error {
// SelectOrganization sets the selected organization in the configuration file
func (conf *Config) SelectOrganization(org string, inGitRepo bool) error {
if !inGitRepo {
conf.userConfig.Set("selected_org", org)
return conf.userConfig.WriteConfig()
}

conf.localConfig.Set("selected_org", org)
return conf.localConfig.WriteConfig()
}
Expand Down Expand Up @@ -176,12 +181,16 @@ func (conf *Config) PreferredPipelines() []pipeline.Pipeline {
}

// SetPreferredPipelines will write the provided list of pipelines to local configuration
func (conf *Config) SetPreferredPipelines(pipelines []pipeline.Pipeline) error {
func (conf *Config) SetPreferredPipelines(pipelines []pipeline.Pipeline, inGitRepo bool) error {
// only save pipelines if they are present
if len(pipelines) == 0 {
return nil
}

if !inGitRepo {
return fmt.Errorf("cannot save preferred pipelines: not in a git repository")
}

names := make([]string, len(pipelines))
for i, p := range pipelines {
names[i] = p.Name
Expand Down
4 changes: 2 additions & 2 deletions internal/pipeline/resolver/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestParsePipelineArg(t *testing.T) {
t.Parallel()

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing")
conf.SelectOrganization("testing", true)
f := resolver.ResolveFromPositionalArgument([]string{testcase.url}, 0, conf)
pipeline, err := f(context.Background())
if err != nil {
Expand All @@ -57,7 +57,7 @@ func TestParsePipelineArg(t *testing.T) {
t.Parallel()

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing")
conf.SelectOrganization("testing", true)
f := resolver.ResolveFromPositionalArgument([]string{"https://buildkite.com/"}, 0, conf)
pipeline, err := f(context.Background())
if err == nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/pipeline/resolver/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestResolvePipelineFromConfig(t *testing.T) {

pipelines := []pipeline.Pipeline{{Name: "pipeline1"}}
conf := config.New(afero.NewMemMapFs(), nil)
conf.SetPreferredPipelines(pipelines)
conf.SetPreferredPipelines(pipelines, true)
resolve := ResolveFromConfig(conf, PassthruPicker)
selected, err := resolve(context.Background())
if err != nil {
Expand All @@ -53,7 +53,7 @@ func TestResolvePipelineFromConfig(t *testing.T) {

pipelines := []pipeline.Pipeline{{Name: "pipeline1"}, {Name: "pipeline2"}, {Name: "pipeline3"}}
conf := config.New(afero.NewMemMapFs(), nil)
conf.SetPreferredPipelines(pipelines)
conf.SetPreferredPipelines(pipelines, true)
resolve := ResolveFromConfig(conf, PassthruPicker)
selected, err := resolve(context.Background())
if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/pipeline/resolver/picker.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func PickOne(pipelines []pipeline.Pipeline) *pipeline.Pipeline {

// CachedPicker returns a PipelinePicker that saves the given pipelines to local config as well as running the provider
// picker.
func CachedPicker(conf *config.Config, picker PipelinePicker) PipelinePicker {
func CachedPicker(conf *config.Config, picker PipelinePicker, inGitRepo bool) PipelinePicker {
return func(pipelines []pipeline.Pipeline) *pipeline.Pipeline {
// run the picker first because we want to put the chosen on at the top of the saved list
chosen := picker(pipelines)
Expand All @@ -67,7 +67,7 @@ func CachedPicker(conf *config.Config, picker PipelinePicker) PipelinePicker {
pipelines[0], pipelines[index] = tmp, pipelines[0]

// save the pipelines to local config before passing to the picker
err := conf.SetPreferredPipelines(pipelines)
err := conf.SetPreferredPipelines(pipelines, inGitRepo)
if err != nil {
return nil
}
Expand Down
6 changes: 3 additions & 3 deletions internal/pipeline/resolver/picker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestPickers(t *testing.T) {
pipelines := []pipeline.Pipeline{
{Name: "pipeline", Org: "org"},
}
picked := resolver.CachedPicker(conf, resolver.PassthruPicker)(pipelines)
picked := resolver.CachedPicker(conf, resolver.PassthruPicker, true)(pipelines)

if picked == nil {
t.Fatal("Should not have received nil from picker")
Expand All @@ -41,7 +41,7 @@ func TestPickers(t *testing.T) {
conf := config.New(fs, nil)

pipelines := []pipeline.Pipeline{}
resolver.CachedPicker(conf, func(p []pipeline.Pipeline) *pipeline.Pipeline { return nil })(pipelines)
resolver.CachedPicker(conf, func(p []pipeline.Pipeline) *pipeline.Pipeline { return nil }, true)(pipelines)

b, _ := afero.ReadFile(fs, ".bk.yaml")
expected := ""
Expand All @@ -61,7 +61,7 @@ func TestPickers(t *testing.T) {
{Name: "second"},
{Name: "third"},
}
resolver.CachedPicker(conf, func(p []pipeline.Pipeline) *pipeline.Pipeline { return &p[1] })(pipelines)
resolver.CachedPicker(conf, func(p []pipeline.Pipeline) *pipeline.Pipeline { return &p[1] }, true)(pipelines)

b, _ := afero.ReadFile(fs, ".bk.yaml")
expected := "pipelines:\n - second\n - first\n - third\n"
Expand Down
2 changes: 1 addition & 1 deletion internal/pipeline/resolver/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func testFactory(t *testing.T, serverURL string, org string, repo *git.Repositor
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization(org)
conf.SelectOrganization(org, true)
return &factory.Factory{
Config: conf,
RestAPIClient: bkClient,
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestParseAgentArg(t *testing.T) {
t.Parallel()

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("testing")
conf.SelectOrganization("testing", true)
org, agent := parseAgentArg(testcase.url, conf)

if org != testcase.org {
Expand Down
8 changes: 4 additions & 4 deletions pkg/cmd/agent/stop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestCmdAgentStop(t *testing.T) {
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("test")
conf.SelectOrganization("test", true)

factory := &factory.Factory{
Config: conf,
Expand Down Expand Up @@ -84,7 +84,7 @@ func TestCmdAgentStop(t *testing.T) {
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("test")
conf.SelectOrganization("test", true)

factory := &factory.Factory{
Config: conf,
Expand Down Expand Up @@ -124,7 +124,7 @@ func TestCmdAgentStop(t *testing.T) {
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("test")
conf.SelectOrganization("test", true)

factory := &factory.Factory{
Config: conf,
Expand Down Expand Up @@ -167,7 +167,7 @@ func TestCmdAgentStop(t *testing.T) {
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("test")
conf.SelectOrganization("test", true)

factory := &factory.Factory{
Config: conf,
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/artifacts/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func NewCmdArtifactsList(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

// we resolve a build an optional argument or positional argument
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/cancel.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func NewCmdBuildCancel(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

buildRes := buildResolver.NewAggregateResolver(
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

// we resolve a build based on the following rules:
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func NewCmdBuildNew(f *factory.Factory) *cobra.Command {
resolvers := resolver.NewAggregateResolver(
resolver.ResolveFromFlag(pipeline, f.Config),
resolver.ResolveFromConfig(f.Config, resolver.PickOne),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOne)),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOne, f.GitRepository != nil)),
)

resolvedPipeline, err := resolvers.Resolve(cmd.Context())
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/rebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func NewCmdBuildRebuild(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

// we resolve a build based on the following rules:
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func NewCmdBuildView(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(opts.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

// Resolve build options
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/build/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func NewCmdBuildWatch(f *factory.Factory) *cobra.Command {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromFlag(opts.Pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne, f.GitRepository != nil)),
)

optionsResolver := options.AggregateResolver{
Expand Down
10 changes: 8 additions & 2 deletions pkg/cmd/configure/add/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,19 @@ func NewCmdAdd(f *factory.Factory) *cobra.Command {
}

func ConfigureWithCredentials(f *factory.Factory, org, token string) error {
if err := f.Config.SelectOrganization(org); err != nil {
if err := f.Config.SelectOrganization(org, f.GitRepository != nil); err != nil {
return err
}

return f.Config.SetTokenForOrg(org, token)
}

func ConfigureRun(f *factory.Factory) error {
// Check if we're in a Git repository
if f.GitRepository == nil {
return errors.New("not in a Git repository - bk should be configured at the root of a Git repository")
}

// Get organization slug
org, err := promptForInput("Organization slug: ", false)
if err != nil {
Expand All @@ -48,7 +54,7 @@ func ConfigureRun(f *factory.Factory) error {
existingToken := getTokenForOrg(f, org)
if existingToken != "" {
fmt.Printf("Using existing API token for organization: %s\n", org)
return f.Config.SelectOrganization(org)
return f.Config.SelectOrganization(org, f.GitRepository != nil)
}

// Get API token with password input (no echo)
Expand Down
31 changes: 31 additions & 0 deletions pkg/cmd/configure/add/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,34 @@ func TestConfigureTokenReuse(t *testing.T) {
}
})
}

func TestConfigureRequiresGitRepository(t *testing.T) {
t.Parallel()

t.Run("fails when not in a git repository", func(t *testing.T) {
t.Parallel()
fs := afero.NewMemMapFs()
conf := config.New(fs, nil)

// Create a factory with nil GitRepository (simulating not being in a git repo)
f := &factory.Factory{Config: conf, GitRepository: nil}

err := ConfigureRun(f)

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

expectedErr := "not in a Git repository - bk should be configured at the root of a Git repository"
if err.Error() != expectedErr {
t.Errorf("expected error message %q, got %q", expectedErr, err.Error())
}
})

t.Run("succeeds when in a git repository", func(t *testing.T) {
// Skip this test because we can't easily mock the interactive prompts
// In a real implementation, we would need to mock the promptForInput function
// or restructure the code to allow for testing without interactive input
t.Skip("skipping test that requires interactive input")
})
}
8 changes: 7 additions & 1 deletion pkg/cmd/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,13 @@ func (a *gqlHTTPClient) Do(req *http.Request) (*http.Response, error) {
}

func New(version string) (*Factory, error) {
repo, _ := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true, EnableDotGitCommonDir: true})
repo, err := git.PlainOpenWithOptions(".", &git.PlainOpenOptions{DetectDotGit: true, EnableDotGitCommonDir: true})
if err != nil {
if err == git.ErrRepositoryNotExists {
repo = nil
}
}

conf := config.New(nil, repo)
buildkiteClient, err := buildkite.NewOpts(
buildkite.WithBaseURL(conf.RESTAPIEndpoint()),
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/pipeline/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewCmdPipelineView(f *factory.Factory) *cobra.Command {
pipelineRes := resolver.NewAggregateResolver(
resolver.ResolveFromPositionalArgument(args, 0, f.Config),
resolver.ResolveFromConfig(f.Config, resolver.PickOne),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOne)),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOne, f.GitRepository != nil)),
)

pipeline, err := pipelineRes.Resolve(cmd.Context())
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/pkg/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func createCommand(t *testing.T, cci createCommandInput) (*cobra.Command, error)
}

conf := config.New(afero.NewMemMapFs(), nil)
conf.SelectOrganization("test")
conf.SelectOrganization("test", true)

f := &factory.Factory{Config: conf, RestAPIClient: client}

Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/use/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ func NewCmdUse(f *factory.Factory) *cobra.Command {
if len(args) > 0 {
org = &args[0]
}
return useRun(org, f.Config)
return useRun(org, f.Config, f.GitRepository != nil)
},
}

return cmd
}

func useRun(org *string, conf *config.Config) error {
func useRun(org *string, conf *config.Config, inGitRepo bool) error {
var selected string

// prompt to choose from configured orgs if one is not already selected
Expand All @@ -51,7 +51,7 @@ func useRun(org *string, conf *config.Config) error {
// if the selected org exists, use it
if conf.HasConfiguredOrganization(selected) {
fmt.Printf("Using configuration for `%s`\n", selected)
return conf.SelectOrganization(selected)
return conf.SelectOrganization(selected, inGitRepo)
}

// if the selected org doesnt exist, recommend configuring it and error out
Expand Down
Loading