diff --git a/docs/daytona_build_logs.md b/docs/daytona_build_logs.md index 501bcfc07a..7a85f91bbf 100644 --- a/docs/daytona_build_logs.md +++ b/docs/daytona_build_logs.md @@ -9,7 +9,8 @@ daytona build logs [flags] ### Options ``` - -f, --follow Follow logs + --continue-on-completed Continue streaming logs after the build is completed + -f, --follow Follow logs ``` ### Options inherited from parent commands diff --git a/hack/docs/daytona_build_logs.yaml b/hack/docs/daytona_build_logs.yaml index 2be578cdf6..683b7571be 100644 --- a/hack/docs/daytona_build_logs.yaml +++ b/hack/docs/daytona_build_logs.yaml @@ -2,6 +2,9 @@ name: daytona build logs synopsis: View logs for build usage: daytona build logs [flags] options: + - name: continue-on-completed + default_value: "false" + usage: Continue streaming logs after the build is completed - name: follow shorthand: f default_value: "false" diff --git a/pkg/build/runner.go b/pkg/build/runner.go index 94d6318a00..5a300c7ab9 100644 --- a/pkg/build/runner.go +++ b/pkg/build/runner.go @@ -9,6 +9,7 @@ import ( "path/filepath" "sync" + "github.com/charmbracelet/lipgloss" "github.com/daytonaio/daytona/pkg/containerregistry" "github.com/daytonaio/daytona/pkg/docker" "github.com/daytonaio/daytona/pkg/git" @@ -283,7 +284,7 @@ func (r *BuildRunner) RunBuildProcess(config BuildProcessConfig) { config.BuildLogger.Write([]byte(errMsg + "\n")) } - config.BuildLogger.Write([]byte("\nBuild completed successfully\n")) + config.BuildLogger.Write([]byte("\n \n" + lipgloss.NewStyle().Bold(true).Render("Build completed successfully"))) if r.telemetryEnabled { r.logTelemetry(context.Background(), *config.Build, err) diff --git a/pkg/cmd/build/logs.go b/pkg/cmd/build/logs.go index e5ed09f000..fea0b10344 100644 --- a/pkg/cmd/build/logs.go +++ b/pkg/cmd/build/logs.go @@ -5,10 +5,14 @@ package build import ( "context" + "fmt" "log" + "slices" + "time" "github.com/daytonaio/daytona/cmd/daytona/config" apiclient_util "github.com/daytonaio/daytona/internal/util/apiclient" + "github.com/daytonaio/daytona/pkg/apiclient" "github.com/daytonaio/daytona/pkg/views/workspace/selection" "github.com/spf13/cobra" ) @@ -57,12 +61,51 @@ var buildLogsCmd = &cobra.Command{ } stopLogs := false - apiclient_util.ReadBuildLogs(activeProfile, buildId, query, &stopLogs) + go apiclient_util.ReadBuildLogs(activeProfile, buildId, query, &stopLogs) + + if !continueOnCompletedFlag { + err = waitForBuildToComplete(buildId, apiClient) + if err != nil { + log.Fatal(err) + } + stopLogs = true + } else { + // Sleep indefinitely + select {} + } + + // Make sure the terminal cursor is reset + fmt.Print("\033[?25h") }, } +func waitForBuildToComplete(buildId string, apiClient *apiclient.APIClient) error { + for { + build, res, err := apiClient.BuildAPI.GetBuild(context.Background(), buildId).Execute() + if err != nil { + return apiclient_util.HandleErrorResponse(res, err) + } + + completedStates := []apiclient.BuildBuildState{ + apiclient.BuildStatePublished, + apiclient.BuildStateError, + apiclient.BuildStateDeleting, + } + + if slices.Contains(completedStates, build.State) { + // Allow the logs to be printed before exiting + time.Sleep(time.Second) + return nil + } + + time.Sleep(time.Second) + } +} + var followFlag bool +var continueOnCompletedFlag bool func init() { buildLogsCmd.Flags().BoolVarP(&followFlag, "follow", "f", false, "Follow logs") + buildLogsCmd.Flags().BoolVar(&continueOnCompletedFlag, "continue-on-completed", false, "Continue streaming logs after the build is completed") }