Say nothing more on a step's log after one publish fails, so a bus that does not take its lines costs a step at most one timeout and never fails it
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -90,6 +91,17 @@ func TestStepEndsPassedFailedOrRefusedOnItsKey(t *testing.T) {
|
||||
{"no whole output", func(context.Context) (any, error) {
|
||||
return map[string]any{"failed": []map[string]string{{"package": "p", "full_output": "all of it"}}}, nil
|
||||
}, delivery.StepPassed, "", `{"failed":[{"package":"p"}]}`},
|
||||
// A log the bus does not take is tried once in a step, then left: the step passes, its failures name no step.
|
||||
{"a dead log", func(context.Context) (any, error) {
|
||||
tries := 0
|
||||
l := &stepLog{say: func(string, any) error { tries++; return errors.New("timeout") }, id: "s1", run: "r1"}
|
||||
raw := l.narrate(json.RawMessage(`{"failed":[{"package":"p","full_output":"a"},{"package":"q","full_output":"b"}]}`), nil)
|
||||
raw = l.narrate(raw, nil)
|
||||
if tries != 1 {
|
||||
return nil, fmt.Errorf("%d publishes, want one", tries)
|
||||
}
|
||||
return raw, nil
|
||||
}, delivery.StepPassed, "", `{"failed":[{"package":"p"},{"package":"q"}]}`},
|
||||
{"error", func(context.Context) (any, error) { return nil, errors.New("exit 2") }, delivery.StepFailed, "exit 2", ""},
|
||||
{"refusal", func(context.Context) (any, error) {
|
||||
return nil, &Refusal{Text: "go 1.27.1 installed, the recipe builds with go 1.27.0", Want: "1.27.0", Have: "1.27.1"}
|
||||
|
||||
@@ -31,6 +31,9 @@ type stepLog struct {
|
||||
module, node string
|
||||
id, run string
|
||||
seq int
|
||||
// dead says a publish failed: the step says nothing more on its log, so a bus that does not take its lines costs the
|
||||
// step at most one publish's timeout, and never fails it (the 2026-10-30 review).
|
||||
dead bool
|
||||
}
|
||||
|
||||
// stepLog is the log of the step whose ask runs under ctx, or nil when no ask runs (a tool called by hand) or the module
|
||||
@@ -49,8 +52,8 @@ func (s AskSteps) stepLog(ctx context.Context) *stepLog {
|
||||
}
|
||||
|
||||
// narrate says every failure's Full of a step answer's "failed" on the step's log and empties it, setting the failure's
|
||||
// Step, Module, Machine and Run; a failure whose lines could not all be said keeps no address, and that is said through
|
||||
// logf. With l nil, Full is only emptied: the step's result never holds it.
|
||||
// Step, Module, Machine and Run; a failure whose lines could not all be said keeps no address, that is said once through
|
||||
// logf, and the step says nothing more on its log (dead). With l nil, Full is only emptied: the step's result never holds it.
|
||||
func (l *stepLog) narrate(raw json.RawMessage, logf func(string, ...any)) json.RawMessage {
|
||||
if !strings.Contains(string(raw), `"full_output"`) {
|
||||
return raw
|
||||
@@ -67,7 +70,7 @@ func (l *stepLog) narrate(raw json.RawMessage, logf func(string, ...any)) json.R
|
||||
var full string
|
||||
_ = json.Unmarshal(f["full_output"], &full)
|
||||
delete(failed[i], "full_output")
|
||||
if full == "" || l == nil {
|
||||
if full == "" || l == nil || l.dead {
|
||||
continue
|
||||
}
|
||||
var name struct {
|
||||
@@ -77,8 +80,9 @@ func (l *stepLog) narrate(raw json.RawMessage, logf func(string, ...any)) json.R
|
||||
b, _ := json.Marshal(f)
|
||||
_ = json.Unmarshal(b, &name)
|
||||
if err := l.say1(name.Package, name.Test, strings.Split(full, "\n")); err != nil {
|
||||
l.dead = true
|
||||
if logf != nil {
|
||||
logf("the whole output of %s %s in the step %s is not on its log: %v", name.Package, name.Test, l.id, err)
|
||||
logf("the step %s says no more on its log, from the whole output of %s %s on: %v", l.id, name.Package, name.Test, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user