diff --git a/github/actions/client.go b/github/actions/client.go index 51fe75d8..bea3e9b2 100644 --- a/github/actions/client.go +++ b/github/actions/client.go @@ -921,6 +921,16 @@ func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *regis } defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode > 299 { + registrationErr := fmt.Errorf("unexpected response from Actions service during registration call: %v", resp.StatusCode) + + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("%v - %v", registrationErr, err) + } + return nil, fmt.Errorf("%v - %v", registrationErr, string(body)) + } + var actionsServiceAdminConnection *ActionsServiceAdminConnection if err := json.NewDecoder(resp.Body).Decode(&actionsServiceAdminConnection); err != nil { return nil, err diff --git a/github/actions/github_api_request_test.go b/github/actions/github_api_request_test.go index fef7b58f..da43a1b3 100644 --- a/github/actions/github_api_request_test.go +++ b/github/actions/github_api_request_test.go @@ -122,6 +122,28 @@ func TestNewActionsServiceRequest(t *testing.T) { assert.Equal(t, "Bearer "+newToken, req.Header.Get("Authorization")) }) + t.Run("admin token refresh failure", func(t *testing.T) { + newToken := defaultActionsToken(t) + errMessage := `{"message":"test"}` + unauthorizedHandler := func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusUnauthorized) + w.Write([]byte(errMessage)) + } + server := testserver.New(t, nil, testserver.WithActionsToken("random-token"), testserver.WithActionsToken(newToken), testserver.WithActionsRegistrationTokenHandler(unauthorizedHandler)) + client, err := actions.NewClient(server.ConfigURLForOrg("my-org"), defaultCreds) + require.NoError(t, err) + expiringToken := "expiring-token" + expiresAt := time.Now().Add(59 * time.Second) + client.ActionsServiceAdminToken = expiringToken + client.ActionsServiceAdminTokenExpiresAt = expiresAt + _, err = client.NewActionsServiceRequest(ctx, http.MethodGet, "my-path", nil) + require.Error(t, err) + assert.Contains(t, err.Error(), errMessage) + assert.Equal(t, client.ActionsServiceAdminToken, expiringToken) + assert.Equal(t, client.ActionsServiceAdminTokenExpiresAt, expiresAt) + }) + t.Run("token is currently valid", func(t *testing.T) { tokenThatShouldNotBeFetched := defaultActionsToken(t) server := testserver.New(t, nil, testserver.WithActionsToken(tokenThatShouldNotBeFetched)) diff --git a/github/actions/testserver/server.go b/github/actions/testserver/server.go index 49ff7073..e5148e41 100644 --- a/github/actions/testserver/server.go +++ b/github/actions/testserver/server.go @@ -35,6 +35,8 @@ func NewUnstarted(t ginkgo.GinkgoTInterface, handler http.Handler, options ...ac server.Close() }) + server.setDefaults(t) + for _, option := range options { option(server) } @@ -42,18 +44,13 @@ func NewUnstarted(t ginkgo.GinkgoTInterface, handler http.Handler, options ...ac h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // handle getRunnerRegistrationToken if strings.HasSuffix(r.URL.Path, "/runners/registration-token") { - w.WriteHeader(http.StatusCreated) - w.Write([]byte(`{"token":"token"}`)) + server.runnerRegistrationTokenHandler(w, r) return } // handle getActionsServiceAdminConnection if strings.HasSuffix(r.URL.Path, "/actions/runner-registration") { - if server.token == "" { - server.token = DefaultActionsToken(t) - } - - w.Write([]byte(`{"url":"` + s.URL + `/tenant/123/","token":"` + server.token + `"}`)) + server.actionRegistrationTokenHandler(w, r) return } @@ -73,10 +70,44 @@ func WithActionsToken(token string) actionsServerOption { } } +func WithRunnerRegistrationTokenHandler(h http.HandlerFunc) actionsServerOption { + return func(s *actionsServer) { + s.runnerRegistrationTokenHandler = h + } +} + +func WithActionsRegistrationTokenHandler(h http.HandlerFunc) actionsServerOption { + return func(s *actionsServer) { + s.actionRegistrationTokenHandler = h + } +} + type actionsServer struct { *httptest.Server - token string + token string + runnerRegistrationTokenHandler http.HandlerFunc + actionRegistrationTokenHandler http.HandlerFunc +} + +func (s *actionsServer) setDefaults(t ginkgo.GinkgoTInterface) { + if s.runnerRegistrationTokenHandler == nil { + s.runnerRegistrationTokenHandler = func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"token":"token"}`)) + } + } + + if s.actionRegistrationTokenHandler == nil { + s.actionRegistrationTokenHandler = func(w http.ResponseWriter, r *http.Request) { + if s.token == "" { + s.token = DefaultActionsToken(t) + } + + w.WriteHeader(http.StatusCreated) + w.Write([]byte(`{"url":"` + s.URL + `/tenant/123/","token":"` + s.token + `"}`)) + } + } } func (s *actionsServer) ConfigURLForOrg(org string) string {