From e019a52bd0a8d2a6bac8fb5dab0d85d57993d4ba Mon Sep 17 00:00:00 2001 From: Jahvon Dockery Date: Thu, 27 Aug 2026 00:54:19 -0400 Subject: [PATCH] fix(runner): do not group a single task's output in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A serial or parallel executable wrapped its whole run in a GitHub log group named after the ref. GitHub log groups are always collapsed and offer no way to default one open, so a single-task run hid the only output worth reading behind a click while gaining no structure — `flow test unit` showed a group header and nothing else until expanded. The group is now emitted only when there is more than one task. EndGroup is guarded by the same condition rather than relying on the logger to ignore an unmatched call, so this is correct against the currently pinned tuikit as well as the version that hardens it (flowexec/tuikit#113). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01R328pa3FUUfga4gYah1iQi --- internal/runner/parallel/parallel.go | 12 ++++++++++-- internal/runner/serial/serial.go | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/internal/runner/parallel/parallel.go b/internal/runner/parallel/parallel.go index 1184aedf..a1c0d87a 100644 --- a/internal/runner/parallel/parallel.go +++ b/internal/runner/parallel/parallel.go @@ -268,7 +268,13 @@ func handleExec( } parentTask := ctx.CurrentTask - if parentTask == nil { + // Group the run's output only when there is more than one task. GitHub log + // groups are always collapsed, so wrapping a single task's output hides the + // only thing worth reading behind a click, with no structure gained. + // EndGroup is guarded by the same condition rather than relying on the + // logger to ignore an unmatched call, so this is correct on older tuikit too. + groupOutput := parentTask == nil && len(execs) > 1 + if groupOutput { if tal, ok := logger.Log().(io.TaskAwareLogger); ok { tal.BeginGroup(parent.Ref().String()) } @@ -283,7 +289,9 @@ func handleExec( parentTask.Children = append(parentTask.Children, tracker.Tasks()...) } else { if tal, ok := logger.Log().(io.TaskAwareLogger); ok { - tal.EndGroup() + if groupOutput { + tal.EndGroup() + } tal.PrintTaskSummary(tracker.Tasks()) } } diff --git a/internal/runner/serial/serial.go b/internal/runner/serial/serial.go index e8e61f02..06c01f19 100644 --- a/internal/runner/serial/serial.go +++ b/internal/runner/serial/serial.go @@ -252,7 +252,13 @@ func handleExec( } parentTask := ctx.CurrentTask - if parentTask == nil { + // Group the run's output only when there is more than one task. GitHub log + // groups are always collapsed, so wrapping a single task's output hides the + // only thing worth reading behind a click, with no structure gained. + // EndGroup is guarded by the same condition rather than relying on the + // logger to ignore an unmatched call, so this is correct on older tuikit too. + groupOutput := parentTask == nil && len(execs) > 1 + if groupOutput { if tal, ok := logger.Log().(io.TaskAwareLogger); ok { tal.BeginGroup(parent.Ref().String()) } @@ -263,7 +269,9 @@ func handleExec( parentTask.Children = append(parentTask.Children, tracker.Tasks()...) } else { if tal, ok := logger.Log().(io.TaskAwareLogger); ok { - tal.EndGroup() + if groupOutput { + tal.EndGroup() + } tal.PrintTaskSummary(tracker.Tasks()) } }