diff --git a/internal/batches/ui/task_exec_tui.go b/internal/batches/ui/task_exec_tui.go index b90df64fe9..080107036d 100644 --- a/internal/batches/ui/task_exec_tui.go +++ b/internal/batches/ui/task_exec_tui.go @@ -236,6 +236,7 @@ func (ui *taskExecTUI) StepsExecutionUI(task *executor.Task) executor.StepsExecu } return &stepsExecTUI{ + out: ui.out, task: task, updateStatusBar: func(message string) { ts.currentlyExecuting = message @@ -427,41 +428,68 @@ func diffStatDiagram(stat diff.Stat) string { } type stepsExecTUI struct { + out *output.Output task *executor.Task updateStatusBar func(string) } func (ui stepsExecTUI) ArchiveDownloadStarted() { ui.updateStatusBar("Downloading archive") + ui.out.Verbosef("[%s] Downloading repository archive...", ui.task.Repository.Name) } -func (ui stepsExecTUI) ArchiveDownloadFinished(err error) {} + +func (ui stepsExecTUI) ArchiveDownloadFinished(err error) { + if err != nil { + ui.out.Verbosef("[%s] Archive download failed: %v", ui.task.Repository.Name, err) + } else { + ui.out.Verbosef("[%s] Archive download completed", ui.task.Repository.Name) + } +} + func (ui stepsExecTUI) WorkspaceInitializationStarted() { ui.updateStatusBar("Initializing workspace") + ui.out.Verbosef("[%s] Initializing workspace...", ui.task.Repository.Name) +} + +func (ui stepsExecTUI) WorkspaceInitializationFinished() { + ui.out.Verbosef("[%s] Workspace initialization completed", ui.task.Repository.Name) } -func (ui stepsExecTUI) WorkspaceInitializationFinished() {} + func (ui stepsExecTUI) SkippingStepsUpto(startStep int) { switch startStep { case 1: ui.updateStatusBar("Skipping step 1. Found cached result.") + ui.out.Verbosef("[%s] Skipping step 1 (cached result found)", ui.task.Repository.Name) default: ui.updateStatusBar(fmt.Sprintf("Skipping steps 1 to %d. Found cached results.", startStep)) + ui.out.Verbosef("[%s] Skipping steps 1 to %d (cached results found)", ui.task.Repository.Name, startStep) } } func (ui stepsExecTUI) StepSkipped(step int) { ui.updateStatusBar(fmt.Sprintf("Skipping step %d", step)) + ui.out.Verbosef("[%s] Step %d skipped", ui.task.Repository.Name, step) } + func (ui stepsExecTUI) StepPreparingStart(step int) { ui.updateStatusBar(fmt.Sprintf("Preparing step %d", step)) + ui.out.Verbosef("[%s] Preparing step %d...", ui.task.Repository.Name, step) } + func (ui stepsExecTUI) StepPreparingSuccess(step int) { - // noop right now + ui.out.Verbosef("[%s] Step %d preparation completed", ui.task.Repository.Name, step) } + func (ui stepsExecTUI) StepPreparingFailed(step int, err error) { - // noop right now + ui.out.Verbosef("[%s] Step %d preparation failed: %v", ui.task.Repository.Name, step, err) } -func (ui stepsExecTUI) StepStarted(step int, runScript string, _ map[string]string) { + +func (ui stepsExecTUI) StepStarted(step int, runScript string, env map[string]string) { ui.updateStatusBar(runScript) + ui.out.Verbosef("[%s] Step %d started: %s", ui.task.Repository.Name, step, truncateScript(runScript, 100)) + if len(env) > 0 { + ui.out.Verbosef("[%s] Step %d environment variables: %d set", ui.task.Repository.Name, step, len(env)) + } } func (ui stepsExecTUI) StepOutputWriter(ctx context.Context, task *executor.Task, step int) executor.StepOutputWriter { @@ -469,8 +497,33 @@ func (ui stepsExecTUI) StepOutputWriter(ctx context.Context, task *executor.Task } func (ui stepsExecTUI) StepFinished(idx int, diff []byte, changes git.Changes, outputs map[string]any) { - // noop right now + ui.out.Verbosef("[%s] Step %d finished successfully", ui.task.Repository.Name, idx) + if len(diff) > 0 { + ui.out.Verbosef("[%s] Step %d produced %d bytes of diff", ui.task.Repository.Name, idx, len(diff)) + } + if len(changes.Modified)+len(changes.Added)+len(changes.Deleted)+len(changes.Renamed) > 0 { + ui.out.Verbosef("[%s] Step %d changes: %d modified, %d added, %d deleted, %d renamed", + ui.task.Repository.Name, idx, + len(changes.Modified), len(changes.Added), len(changes.Deleted), len(changes.Renamed)) + } + if len(outputs) > 0 { + ui.out.Verbosef("[%s] Step %d outputs: %d variables set", ui.task.Repository.Name, idx, len(outputs)) + } } + func (ui stepsExecTUI) StepFailed(idx int, err error, exitCode int) { - // noop right now + ui.out.Verbosef("[%s] Step %d failed (exit code %d): %v", ui.task.Repository.Name, idx, exitCode, err) +} + +// truncateScript truncates a script string for display purposes +func truncateScript(script string, maxLen int) string { + lines := strings.Split(script, "\n") + firstLine := lines[0] + if len(firstLine) > maxLen { + return firstLine[:maxLen] + "..." + } + if len(lines) > 1 { + return firstLine + " ..." + } + return firstLine } diff --git a/internal/batches/ui/tui.go b/internal/batches/ui/tui.go index 94724909b1..405918909e 100644 --- a/internal/batches/ui/tui.go +++ b/internal/batches/ui/tui.go @@ -63,8 +63,9 @@ func (ui *TUI) ResolvingNamespace() { ui.pending = batchCreatePending(ui.Out, "Resolving namespace") } -func (ui *TUI) ResolvingNamespaceSuccess(_namespace string) { +func (ui *TUI) ResolvingNamespaceSuccess(namespace string) { batchCompletePending(ui.pending, "Resolving namespace") + ui.Out.Verbosef("Resolved namespace: %s", namespace) } func (ui *TUI) PreparingContainerImages() { @@ -80,6 +81,7 @@ func (ui *TUI) PreparingContainerImagesProgress(done, total int) { func (ui *TUI) PreparingContainerImagesSuccess() { ui.progress.Complete() + ui.Out.Verbosef("Container images prepared successfully") } func (ui *TUI) DeterminingWorkspaceCreatorType() { @@ -104,13 +106,16 @@ func (ui *TUI) DeterminingWorkspaces() { func (ui *TUI) DeterminingWorkspacesSuccess(workspacesCount, reposCount int, unsupported batches.UnsupportedRepoSet, ignored batches.IgnoredRepoSet) { batchCompletePending(ui.pending, fmt.Sprintf("Resolved %d workspaces from %d repositories", workspacesCount, reposCount)) + ui.Out.Verbosef("Workspace resolution: %d workspaces across %d repositories", workspacesCount, reposCount) if len(unsupported) != 0 { + ui.Out.Verbosef("Unsupported repositories: %d", len(unsupported)) block := ui.Out.Block(output.Line(" ", output.StyleWarning, "Some repositories are hosted on unsupported code hosts and will be skipped. Use the -allow-unsupported flag to avoid skipping them.")) for repo := range unsupported { block.Write(repo.Name) } block.Close() } else if len(ignored) != 0 { + ui.Out.Verbosef("Ignored repositories (have .batchignore): %d", len(ignored)) block := ui.Out.Block(output.Line(" ", output.StyleWarning, "The repositories listed below contain .batchignore files and will be skipped. Use the -force-override-ignore flag to avoid skipping them.")) for repo := range ignored { block.Write(repo.Name) @@ -163,6 +168,7 @@ func (ui *TUI) CheckingCacheSuccess(cachedSpecsFound int, uncachedTasks int) { default: batchCompletePending(ui.pending, fmt.Sprintf("%s; %d tasks need to be executed", specsFoundMessage, uncachedTasks)) } + ui.Out.Verbosef("Cache check: %d cached specs found, %d tasks to execute", cachedSpecsFound, uncachedTasks) } func (ui *TUI) ExecutingTasks(verbose bool, parallelism int) executor.TaskExecutionUI {