From d5e21848701742640d5d9e6c0acfe17f23d64a51 Mon Sep 17 00:00:00 2001 From: Gabriel Paradiso Date: Thu, 19 Dec 2024 10:24:09 +0100 Subject: [PATCH] fix: correctly propagate errors whenever the fetcher fails to download the artifacts (#15758) --- core/services/workflows/syncer/fetcher.go | 4 +++ .../services/workflows/syncer/fetcher_test.go | 34 +++++++++++++++++++ core/services/workflows/syncer/handler.go | 6 ++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/services/workflows/syncer/fetcher.go b/core/services/workflows/syncer/fetcher.go index 6a80739bbfe..5c8856d58c1 100644 --- a/core/services/workflows/syncer/fetcher.go +++ b/core/services/workflows/syncer/fetcher.go @@ -100,5 +100,9 @@ func (s *FetcherService) Fetch(ctx context.Context, url string) ([]byte, error) return nil, err } + if payload.ExecutionError { + return nil, fmt.Errorf("execution error from gateway: %s", payload.ErrorMessage) + } + return payload.Body, nil } diff --git a/core/services/workflows/syncer/fetcher_test.go b/core/services/workflows/syncer/fetcher_test.go index ee59d22608a..017b052f8ab 100644 --- a/core/services/workflows/syncer/fetcher_test.go +++ b/core/services/workflows/syncer/fetcher_test.go @@ -58,6 +58,40 @@ func TestNewFetcherService(t *testing.T) { expectedPayload := []byte("response body") require.Equal(t, expectedPayload, payload) }) + + t.Run("NOK-response_payload_too_large", func(t *testing.T) { + headers := map[string]string{"Content-Type": "application/json"} + responsePayload, err := json.Marshal(ghcapabilities.Response{ + StatusCode: 400, + Headers: headers, + ErrorMessage: "http: request body too large", + ExecutionError: true, + }) + require.NoError(t, err) + gatewayResponse := &api.Message{ + Body: api.MessageBody{ + MessageId: msgID, + Method: ghcapabilities.MethodWebAPITarget, + Payload: responsePayload, + }, + } + + connector.EXPECT().AddHandler([]string{capabilities.MethodWorkflowSyncer}, mock.Anything).Return(nil) + + fetcher := NewFetcherService(lggr, wrapper) + require.NoError(t, fetcher.Start(ctx)) + defer fetcher.Close() + + connector.EXPECT().SignAndSendToGateway(mock.Anything, "gateway1", mock.Anything).Run(func(ctx context.Context, gatewayID string, msg *api.MessageBody) { + fetcher.och.HandleGatewayMessage(ctx, "gateway1", gatewayResponse) + }).Return(nil).Times(1) + connector.EXPECT().DonID().Return("don-id") + connector.EXPECT().AwaitConnection(matches.AnyContext, "gateway1").Return(nil) + connector.EXPECT().GatewayIDs().Return([]string{"gateway1", "gateway2"}) + + _, err = fetcher.Fetch(ctx, url) + require.Error(t, err, "execution error from gateway: http: request body too large") + }) } func gatewayResponse(t *testing.T, msgID string) *api.Message { diff --git a/core/services/workflows/syncer/handler.go b/core/services/workflows/syncer/handler.go index 534dfd57e7b..ef5455bfbc8 100644 --- a/core/services/workflows/syncer/handler.go +++ b/core/services/workflows/syncer/handler.go @@ -497,19 +497,19 @@ func (h *eventHandler) getWorkflowArtifacts( if err != nil { binary, err2 := h.fetcher(ctx, payload.BinaryURL) if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err) + return nil, nil, fmt.Errorf("failed to fetch binary from %s : %w", payload.BinaryURL, err2) } decodedBinary, err2 := base64.StdEncoding.DecodeString(string(binary)) if err2 != nil { - return nil, nil, fmt.Errorf("failed to decode binary: %w", err) + return nil, nil, fmt.Errorf("failed to decode binary: %w", err2) } var config []byte if payload.ConfigURL != "" { config, err2 = h.fetcher(ctx, payload.ConfigURL) if err2 != nil { - return nil, nil, fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err) + return nil, nil, fmt.Errorf("failed to fetch config from %s : %w", payload.ConfigURL, err2) } } return decodedBinary, config, nil