Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change bk build pipeline argument to a flag #275

Merged
merged 6 commits into from
Jun 11, 2024
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
27 changes: 27 additions & 0 deletions internal/pipeline/resolver/flag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package resolver

import (
"context"
"fmt"

"github.com/buildkite/cli/v3/internal/config"
"github.com/buildkite/cli/v3/internal/pipeline"
)

func ResolveFromFlag(flag string, conf *config.Config) PipelineResolverFn {
return func(context.Context) (*pipeline.Pipeline, error) {
// if the flag is empty, pass through
if flag == "" {
return nil, nil
}
org, name := parsePipelineArg(flag, conf)

// if we get here, we should be able to parse the value and return an error if not
// this is because a user has explicitly given an input value for us to use - we shoulnt ignore it on error
if org == "" || name == "" {
return nil, fmt.Errorf("unable to parse the input pipeline argument: \"%s\"", flag)
}

return &pipeline.Pipeline{Name: name, Org: org}, nil
}
}
5 changes: 5 additions & 0 deletions internal/pipeline/resolver/picker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ func PickOne(pipelines []pipeline.Pipeline) *pipeline.Pipeline {
return nil
}

// no need to prompt for only one option
if len(pipelines) == 1 {
return &pipelines[0]
}

names := make([]string, len(pipelines))
for i, p := range pipelines {
names[i] = p.Name
Expand Down
19 changes: 10 additions & 9 deletions pkg/cmd/build/cancel.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,25 @@ import (

func NewCmdBuildCancel(f *factory.Factory) *cobra.Command {
var web bool
var pipeline string

cmd := cobra.Command{
DisableFlagsInUseLine: true,
Use: "cancel [number [pipeline]] [flags]",
Short: "Cancels a build.",
Use: "cancel <number> [flags]",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this is a destructive operation and could cause issues when builds are cancelled whilst running, I think requiring an actual build number here is a good idea. That will mean the user won't unintentionally cancel a main branch build which could cause issues with deploys or other things.

Args: cobra.ExactArgs(1),
Short: "Cancel a build.",
Long: heredoc.Doc(`
Cancels the specified build.

It accepts a build number and a pipeline slug as an argument.
The pipeline can be a {pipeline_slug} or in the format {org_slug}/{pipeline_slug}.
If the pipeline argument is omitted, it will be resolved using the current directory.
Cancel the given build.
`),
RunE: func(cmd *cobra.Command, args []string) error {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromPositionalArgument(args, 1, f.Config),
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
)

buildRes := buildResolver.NewAggregateResolver(
buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config),
buildResolver.ResolveBuildFromCurrentBranch(f.GitRepository, pipelineRes.Resolve, f),
)

bld, err := buildRes.Resolve(cmd.Context())
Expand All @@ -51,7 +48,11 @@ func NewCmdBuildCancel(f *factory.Factory) *cobra.Command {
}

cmd.Flags().BoolVarP(&web, "web", "w", false, "Open the build in a web browser after it has been cancelled.")
cmd.Flags().StringVarP(&pipeline, "pipeline", "p", "", "The pipeline to cancel a build on. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}.\n"+
"If omitted, it will be resolved using the current directory.",
)
cmd.Flags().SortFlags = false

return &cmd
}

Expand Down
22 changes: 12 additions & 10 deletions pkg/cmd/build/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,24 @@ import (
)

func NewCmdBuildNew(f *factory.Factory) *cobra.Command {
var message string
var commit string
var branch string
var commit string
var message string
var pipeline string
var web bool

cmd := cobra.Command{
DisableFlagsInUseLine: true,
Use: "new [pipeline] [flags]",
Short: "Creates a new pipeline build",
Args: cobra.MaximumNArgs(1),
Use: "new [flags]",
Short: "Create a new build",
Args: cobra.NoArgs,
Long: heredoc.Doc(`
Creates a new build for the specified pipeline and output the URL to the build.

The pipeline can be a {pipeline_slug} or in the format {org_slug}/{pipeline_slug}.
If the pipeline argument is omitted, it will be resolved using the current directory.
Create a new build on a pipeline.
The web URL to the build will be printed to stdout.
`),
RunE: func(cmd *cobra.Command, args []string) error {
resolvers := resolver.NewAggregateResolver(
resolver.ResolveFromPositionalArgument(args, 0, f.Config),
resolver.ResolveFromFlag(pipeline, f.Config),
Comment on lines -24 to +34
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no build argument to this command. So I thought making the pipeline name optional instead of an arg would make sense. Any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am fine with that behaviour.

resolver.ResolveFromConfig(f.Config, resolver.PickOne),
resolver.ResolveFromRepository(f, resolver.CachedPicker(f.Config, resolver.PickOne)),
)
Expand All @@ -53,6 +52,9 @@ func NewCmdBuildNew(f *factory.Factory) *cobra.Command {
cmd.Flags().StringVarP(&commit, "commit", "c", "HEAD", "The commit to build.")
cmd.Flags().StringVarP(&branch, "branch", "b", "", "The branch to build. Defaults to the default branch of the pipeline.")
cmd.Flags().BoolVarP(&web, "web", "w", false, "Open the build in a web browser after it has been created.")
cmd.Flags().StringVarP(&pipeline, "pipeline", "p", "", "The pipeline to build. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}.\n"+
"If omitted, it will be resolved using the current directory.",
)
cmd.Flags().SortFlags = false
return &cmd
}
Expand Down
18 changes: 10 additions & 8 deletions pkg/cmd/build/rebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,20 @@ import (

func NewCmdBuildRebuild(f *factory.Factory) *cobra.Command {
var web bool
var pipeline string

cmd := cobra.Command{
DisableFlagsInUseLine: true,
Use: "rebuild [number [pipeline]] [flags]",
Short: "Reruns a build.",
Use: "rebuild [number] [flags]",
Short: "Rebuild a build.",
Args: cobra.MaximumNArgs(1),
Long: heredoc.Doc(`
Runs a new build from the specified build number and pipeline and outputs the URL to the new build.

It accepts a build number and a pipeline slug as an argument.
The pipeline can be a {pipeline_slug} or in the format {org_slug}/{pipeline_slug}.
If the pipeline argument is omitted, it will be resolved using the current directory.
Rebuild a build.
The web URL to the build will be printed to stdout.
`),
RunE: func(cmd *cobra.Command, args []string) error {
pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromPositionalArgument(args, 1, f.Config),
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
)
Expand All @@ -51,6 +50,9 @@ func NewCmdBuildRebuild(f *factory.Factory) *cobra.Command {
}

cmd.Flags().BoolVarP(&web, "web", "w", false, "Open the build in a web browser after it has been created.")
cmd.Flags().StringVarP(&pipeline, "pipeline", "p", "", "The pipeline to build. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}.\n"+
"If omitted, it will be resolved using the current directory.",
)
cmd.Flags().SortFlags = false
return &cmd
}
Expand Down
14 changes: 8 additions & 6 deletions pkg/cmd/build/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,24 @@ import (

func NewCmdBuildView(f *factory.Factory) *cobra.Command {
var web bool
var pipeline string

cmd := cobra.Command{
DisableFlagsInUseLine: true,
Use: "view [number [pipeline]] [flags]",
Use: "view [number] [flags]",
Short: "View build information.",
Args: cobra.MaximumNArgs(1),
Long: heredoc.Doc(`
View a build's information.

It accepts a build number and a pipeline slug as an argument.
If the build argument is be omitted, the most recent build on the current branch will be resolved.
The pipeline can be a {pipeline_slug} or in the format {org_slug}/{pipeline_slug}.
If the pipeline argument is omitted, it will be resolved using the current directory.
You can pass an optional build number to view. If omitted, the most recent build on the current branch will be resolved.
`),
RunE: func(cmd *cobra.Command, args []string) error {
buildArtifacts := make([]buildkite.Artifact, 0)
buildAnnotations := make([]buildkite.Annotation, 0)

pipelineRes := pipelineResolver.NewAggregateResolver(
pipelineResolver.ResolveFromPositionalArgument(args, 1, f.Config),
pipelineResolver.ResolveFromFlag(pipeline, f.Config),
pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne),
pipelineResolver.ResolveFromRepository(f, pipelineResolver.CachedPicker(f.Config, pipelineResolver.PickOne)),
)
Expand Down Expand Up @@ -116,6 +115,9 @@ func NewCmdBuildView(f *factory.Factory) *cobra.Command {
}

cmd.Flags().BoolVarP(&web, "web", "w", false, "Open the build in a web browser.")
cmd.Flags().StringVarP(&pipeline, "pipeline", "p", "", "The pipeline to view. This can be a {pipeline slug} or in the format {org slug}/{pipeline slug}.\n"+
"If omitted, it will be resolved using the current directory.",
)

return &cmd
}