diff --git a/github/actions/client.go b/github/actions/client.go index a527581e..77d27cbb 100644 --- a/github/actions/client.go +++ b/github/actions/client.go @@ -274,6 +274,10 @@ func (c *Client) Identifier() string { func (c *Client) Do(req *http.Request) (*http.Response, error) { resp, err := c.Client.Do(req) if err != nil { + // If we have a response even with an error, include the status code + if resp != nil { + return nil, fmt.Errorf("client request failed with status code %d: %w", resp.StatusCode, err) + } return nil, fmt.Errorf("client request failed: %w", err) } @@ -856,7 +860,8 @@ func (c *Client) GenerateJitRunnerConfig(ctx context.Context, jitRunnerSetting * resp, err := c.Do(req) if err != nil { - return nil, fmt.Errorf("failed to issue the request: %w", err) + // Include the URL and method in the error for better debugging + return nil, fmt.Errorf("failed to issue the request %s %s: %w", req.Method, req.URL.String(), err) } if resp.StatusCode != http.StatusOK { diff --git a/github/actions/client_generate_jit_test.go b/github/actions/client_generate_jit_test.go index 94f9d537..ee77ca7d 100644 --- a/github/actions/client_generate_jit_test.go +++ b/github/actions/client_generate_jit_test.go @@ -2,6 +2,7 @@ package actions_test import ( "context" + "errors" "net/http" "testing" "time" @@ -58,4 +59,37 @@ func TestGenerateJitRunnerConfig(t *testing.T) { assert.NotNil(t, err) assert.Equalf(t, actualRetry, expectedRetry, "A retry was expected after the first request but got: %v", actualRetry) }) + + t.Run("Error includes HTTP method and URL when request fails", func(t *testing.T) { + runnerSettings := &actions.RunnerScaleSetJitRunnerSetting{} + + server := newActionsServer(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + })) + + client, err := actions.NewClient( + server.configURLForOrg("my-org"), + auth, + actions.WithRetryMax(0), // No retries to get immediate error + actions.WithRetryWaitMax(1*time.Millisecond), + ) + require.NoError(t, err) + + _, err = client.GenerateJitRunnerConfig(ctx, runnerSettings, 1) + require.NotNil(t, err) + // Verify error message includes HTTP method and URL for better debugging + errMsg := err.Error() + assert.Contains(t, errMsg, "POST", "Error message should include HTTP method") + assert.Contains(t, errMsg, "generatejitconfig", "Error message should include URL path") + + // The error might be an ActionsError (if response was received) or a wrapped error (if Do() failed) + // In either case, the error message should include request details + var actionsErr *actions.ActionsError + if errors.As(err, &actionsErr) { + // If we got an ActionsError, verify the status code is included + assert.Equal(t, http.StatusInternalServerError, actionsErr.StatusCode) + } + // If it's a wrapped error from Do(), the error message already includes the method and URL + // which is what we're testing for + }) }