From 4fd349b2668f0946ff91dfd272cbd4dc73d1c1de Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Tue, 28 May 2024 11:00:12 +0800 Subject: [PATCH 1/6] Fill out bk build download cmd --- pkg/cmd/build/build.go | 5 ++-- pkg/cmd/build/download.go | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 pkg/cmd/build/download.go diff --git a/pkg/cmd/build/build.go b/pkg/cmd/build/build.go index f8fc6832..8a79d48e 100644 --- a/pkg/cmd/build/build.go +++ b/pkg/cmd/build/build.go @@ -30,10 +30,11 @@ func NewCmdBuild(f *factory.Factory) *cobra.Command { }, } + cmd.AddCommand(NewCmdBuildCancel(f)) + cmd.AddCommand(NewCmdBuildDownload(f)) cmd.AddCommand(NewCmdBuildNew(f)) - cmd.AddCommand(NewCmdBuildView(f)) cmd.AddCommand(NewCmdBuildRebuild(f)) - cmd.AddCommand(NewCmdBuildCancel(f)) + cmd.AddCommand(NewCmdBuildView(f)) return &cmd } diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go new file mode 100644 index 00000000..110929f5 --- /dev/null +++ b/pkg/cmd/build/download.go @@ -0,0 +1,51 @@ +package build + +import ( + "fmt" + + buildResolver "github.com/buildkite/cli/v3/internal/build/resolver" + pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver" + "github.com/buildkite/cli/v3/pkg/cmd/factory" + "github.com/spf13/cobra" +) + +func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { + var logs bool + + cmd := cobra.Command{ + DisableFlagsInUseLine: true, + Use: "download [number [pipeline]] [flags]", + Short: "Download resources of a build", + Long: "Download allows you to download resources from a build.", + RunE: func(cmd *cobra.Command, args []string) error { + pipelineRes := pipelineResolver.NewAggregateResolver( + pipelineResolver.ResolveFromPositionalArgument(args, 1, 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()) + if err != nil { + return err + } + if bld == nil { + return fmt.Errorf("could not resolve a build") + } + + return download() + }, + } + + cmd.Flags().BoolVar(&logs, "logs", false, "Download all job logs for the build") + + return &cmd +} + +func download() error { + return nil +} From c40863cd9f509aa4f86dd908279ef9e602bf57eb Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Fri, 31 May 2024 10:20:45 +0800 Subject: [PATCH 2/6] First pass to download job logs --- pkg/cmd/build/download.go | 42 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go index 110929f5..be6b2172 100644 --- a/pkg/cmd/build/download.go +++ b/pkg/cmd/build/download.go @@ -2,7 +2,10 @@ package build import ( "fmt" + "os" + "path/filepath" + "github.com/buildkite/cli/v3/internal/build" buildResolver "github.com/buildkite/cli/v3/internal/build/resolver" pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver" "github.com/buildkite/cli/v3/pkg/cmd/factory" @@ -26,7 +29,7 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { buildRes := buildResolver.NewAggregateResolver( buildResolver.ResolveFromPositionalArgument(args, 0, pipelineRes.Resolve, f.Config), - // buildResolver.ResolveBuildFromCurrentBranch(f.GitRepository, pipelineRes.Resolve, f), + buildResolver.ResolveBuildFromCurrentBranch(f.GitRepository, pipelineRes.Resolve, f), ) bld, err := buildRes.Resolve(cmd.Context()) @@ -37,7 +40,7 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { return fmt.Errorf("could not resolve a build") } - return download() + return download(*bld, logs, f) }, } @@ -46,6 +49,39 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { return &cmd } -func download() error { +func download(build build.Build, logs bool, f *factory.Factory) error { + b, _, err := f.RestAPIClient.Builds.Get(build.Organization, build.Pipeline, fmt.Sprint(build.BuildNumber), nil) + if err != nil { + return err + } + if b == nil { + return fmt.Errorf("Could not find build for %s #%d", build.Pipeline, build.BuildNumber) + } + + directory := fmt.Sprintf("build-logs-%s", *b.ID) + err = os.MkdirAll(directory, os.ModePerm) + if err != nil { + return err + } + + for _, job := range b.Jobs { + // only script (command) jobs will have logs + if job == nil || *job.Type != "script" { + continue + } + + log, _, err := f.RestAPIClient.Jobs.GetJobLog(build.Organization, build.Pipeline, *b.ID, *job.ID) + if err != nil { + return err + } + if log == nil { + return fmt.Errorf("Could not get logs for job %s", *job.ID) + } + + err = os.WriteFile(filepath.Join(directory, *job.ID), []byte(*log.Content), 0644) + if err != nil { + return err + } + } return nil } From 655256e1f359fddee3ef2d0a6a1eeb28fc68eec9 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Tue, 4 Jun 2024 12:07:43 +0800 Subject: [PATCH 3/6] Add spinner while downloading logs --- pkg/cmd/build/download.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go index be6b2172..dfb1e39a 100644 --- a/pkg/cmd/build/download.go +++ b/pkg/cmd/build/download.go @@ -4,7 +4,9 @@ import ( "fmt" "os" "path/filepath" + "time" + "github.com/briandowns/spinner" "github.com/buildkite/cli/v3/internal/build" buildResolver "github.com/buildkite/cli/v3/internal/build/resolver" pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver" @@ -50,6 +52,10 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { } func download(build build.Build, logs bool, f *factory.Factory) error { + s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) + s.Suffix = " Downloading logs" + s.Start() + defer s.Stop() b, _, err := f.RestAPIClient.Builds.Get(build.Organization, build.Pipeline, fmt.Sprint(build.BuildNumber), nil) if err != nil { return err From 65ecded45ae060bac3d46c7d25b3d4d9cf8eb415 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Tue, 4 Jun 2024 13:03:51 +0800 Subject: [PATCH 4/6] Refactor spinner and log messages --- pkg/cmd/build/download.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go index dfb1e39a..03feafa4 100644 --- a/pkg/cmd/build/download.go +++ b/pkg/cmd/build/download.go @@ -23,6 +23,10 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { Short: "Download resources of a build", Long: "Download allows you to download resources from a build.", RunE: func(cmd *cobra.Command, args []string) error { + if !logs { + fmt.Println("Nothing to download") + return nil + } pipelineRes := pipelineResolver.NewAggregateResolver( pipelineResolver.ResolveFromPositionalArgument(args, 1, f.Config), pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne), @@ -42,7 +46,13 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { return fmt.Errorf("could not resolve a build") } - return download(*bld, logs, f) + s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) + s.Suffix = " Downloading logs" + s.Start() + defer s.Stop() + err = download(*bld, f) + + return err }, } @@ -51,17 +61,13 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { return &cmd } -func download(build build.Build, logs bool, f *factory.Factory) error { - s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) - s.Suffix = " Downloading logs" - s.Start() - defer s.Stop() +func download(build build.Build, f *factory.Factory) error { b, _, err := f.RestAPIClient.Builds.Get(build.Organization, build.Pipeline, fmt.Sprint(build.BuildNumber), nil) if err != nil { return err } if b == nil { - return fmt.Errorf("Could not find build for %s #%d", build.Pipeline, build.BuildNumber) + return fmt.Errorf("could not find build for %s #%d", build.Pipeline, build.BuildNumber) } directory := fmt.Sprintf("build-logs-%s", *b.ID) @@ -81,7 +87,7 @@ func download(build build.Build, logs bool, f *factory.Factory) error { return err } if log == nil { - return fmt.Errorf("Could not get logs for job %s", *job.ID) + return fmt.Errorf("could not get logs for job %s", *job.ID) } err = os.WriteFile(filepath.Join(directory, *job.ID), []byte(*log.Content), 0644) @@ -89,5 +95,8 @@ func download(build build.Build, logs bool, f *factory.Factory) error { return err } } + + fmt.Printf("\nDownloaded logs to: %s\n", directory) + return nil } From e0236774b51febdfdb87616b2f834cef6b1f7b38 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Mon, 10 Jun 2024 09:32:55 +0800 Subject: [PATCH 5/6] Remove logs flag --- pkg/cmd/build/download.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go index 03feafa4..85894940 100644 --- a/pkg/cmd/build/download.go +++ b/pkg/cmd/build/download.go @@ -15,18 +15,12 @@ import ( ) func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { - var logs bool - cmd := cobra.Command{ DisableFlagsInUseLine: true, Use: "download [number [pipeline]] [flags]", - Short: "Download resources of a build", - Long: "Download allows you to download resources from a build.", + Short: "Download job logs for a build", + Long: "Download allows you to download resources for a build.", RunE: func(cmd *cobra.Command, args []string) error { - if !logs { - fmt.Println("Nothing to download") - return nil - } pipelineRes := pipelineResolver.NewAggregateResolver( pipelineResolver.ResolveFromPositionalArgument(args, 1, f.Config), pipelineResolver.ResolveFromConfig(f.Config, pipelineResolver.PickOne), @@ -56,8 +50,6 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { }, } - cmd.Flags().BoolVar(&logs, "logs", false, "Download all job logs for the build") - return &cmd } From 8ea291a73c1ad2a047ce26108da02667b42c36c1 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Wed, 12 Jun 2024 10:50:58 +0800 Subject: [PATCH 6/6] Update to huh? spinner --- .gitignore | 1 + pkg/cmd/build/download.go | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index ef6b8f54..b4b66b69 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dist/ buildkite.yaml .bk.yaml +build-logs-* diff --git a/pkg/cmd/build/download.go b/pkg/cmd/build/download.go index 85894940..17e662cb 100644 --- a/pkg/cmd/build/download.go +++ b/pkg/cmd/build/download.go @@ -4,13 +4,12 @@ import ( "fmt" "os" "path/filepath" - "time" - "github.com/briandowns/spinner" "github.com/buildkite/cli/v3/internal/build" buildResolver "github.com/buildkite/cli/v3/internal/build/resolver" pipelineResolver "github.com/buildkite/cli/v3/internal/pipeline/resolver" "github.com/buildkite/cli/v3/pkg/cmd/factory" + "github.com/charmbracelet/huh/spinner" "github.com/spf13/cobra" ) @@ -40,11 +39,15 @@ func NewCmdBuildDownload(f *factory.Factory) *cobra.Command { return fmt.Errorf("could not resolve a build") } - s := spinner.New(spinner.CharSets[11], 100*time.Millisecond) - s.Suffix = " Downloading logs" - s.Start() - defer s.Stop() - err = download(*bld, f) + spinErr := spinner.New(). + Title("Downloading logs"). + Action(func() { + err = download(*bld, f) + }). + Run() + if spinErr != nil { + return spinErr + } return err },