The builder narrates every step, and every command it runs
A build was silent from clone to publish, so a build in progress, one that failed quietly, and a request that never arrived all looked identical — which cost a long diagnosis against a running mesh chasing "the handler never fired". Now: the handler announces a request the instant it lands. Build logs each phase — clone, commit, manifest, bases, each artifact starting and finishing with what it produced, resolve, done — through a Log callback that is nil-safe, so the tests that pass none still build. And the Command runner echoes every command before it runs, with where and how long it took, because on a hang the last line is exactly the command it is stuck inside: "git clone waiting on a network that will not answer" rather than "the builder did nothing". The unreadable-request path prints to stdout now too, not stderr, so it shows in docker logs without splitting streams — the split is what hid it. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
@@ -160,12 +160,18 @@ func run() error {
|
||||
func answer(ctx context.Context, channel *amqp.Channel, publisher builder.Publisher,
|
||||
on, workspace string, delivery amqp.Delivery) {
|
||||
|
||||
// **First thing, and to stdout.** A build request that arrives and produces no visible line
|
||||
// until it either finishes or fails is indistinguishable from one that never arrived — which
|
||||
// cost a long diagnosis against a running mesh, chasing "the handler never fired" when the
|
||||
// truth was only that the handler said nothing until the end.
|
||||
fmt.Printf("a build request arrived (%d bytes)\n", len(delivery.Body))
|
||||
|
||||
var request link.BuildRequest
|
||||
if err := json.Unmarshal(delivery.Body, &request); err != nil {
|
||||
// Unreadable. Acknowledged and dropped rather than requeued: a message this builder
|
||||
// cannot parse will not become parseable by being delivered again, and requeueing it
|
||||
// would put it in front of every real request for ever.
|
||||
fmt.Fprintf(os.Stderr, "a request could not be read and was dropped: %v\n", err)
|
||||
fmt.Printf("a request could not be read and was dropped: %v\n", err)
|
||||
_ = delivery.Ack(false)
|
||||
return
|
||||
}
|
||||
@@ -184,7 +190,10 @@ func answer(ctx context.Context, channel *amqp.Channel, publisher builder.Publis
|
||||
fmt.Println()
|
||||
|
||||
built, err := builder.Build(ctx, builder.Command, publisher,
|
||||
request.Repository, request.Path, request.Ref, workspace, request.Held)
|
||||
request.Repository, request.Path, request.Ref, workspace, request.Held,
|
||||
func(step, message string) {
|
||||
fmt.Printf(" [%s] %s\n", step, message)
|
||||
})
|
||||
if err != nil {
|
||||
// A failure is a result. A build that fails and says nothing is indistinguishable from a
|
||||
// builder that is not running, and those want completely different responses.
|
||||
|
||||
@@ -84,7 +84,8 @@ func buildOnce(ctx context.Context, args []string) error {
|
||||
}
|
||||
fmt.Fprintln(os.Stderr)
|
||||
|
||||
built, buildErr := builder.Build(ctx, builder.Command, publisher, repository, *path, *ref, where, bases)
|
||||
built, buildErr := builder.Build(ctx, builder.Command, publisher, repository, *path, *ref, where, bases,
|
||||
func(step, message string) { fmt.Printf(" [%s] %s\n", step, message) })
|
||||
if buildErr != nil {
|
||||
return buildErr
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user