From 7f30b0508dcfbb1cfb93f2a5ed474b55e6edbd03 Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Tue, 14 Sep 2021 20:49:46 +0200 Subject: [PATCH 1/5] Add support for apps webhook configuration endpoints --- github/apps_hooks.go | 43 +++++++++++++++ github/apps_hooks_test.go | 98 +++++++++++++++++++++++++++++++++ github/doc.go | 21 +++++++ github/github-accessors.go | 8 +++ github/github-accessors_test.go | 10 ++++ github/orgs_audit_log.go | 3 + 6 files changed, 183 insertions(+) create mode 100644 github/apps_hooks.go create mode 100644 github/apps_hooks_test.go diff --git a/github/apps_hooks.go b/github/apps_hooks.go new file mode 100644 index 00000000000..2b2c309cdde --- /dev/null +++ b/github/apps_hooks.go @@ -0,0 +1,43 @@ +package github + +import ( + "context" +) + +// GetHookConfig returns the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/apps#get-a-webhook-configuration-for-an-app +func (s *AppsService) GetHookConfig(ctx context.Context) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("GET", "app/hook/config", nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, &config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// UpdateHookConfig updates the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/en/free-pro-team@latest/rest/reference/apps#update-a-webhook-configuration-for-an-app +func (s *AppsService) UpdateHookConfig(ctx context.Context, config *HookConfig) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("PATCH", "app/hook/config", config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/github/apps_hooks_test.go b/github/apps_hooks_test.go new file mode 100644 index 00000000000..4d49051256d --- /dev/null +++ b/github/apps_hooks_test.go @@ -0,0 +1,98 @@ +package github + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestAppsService_GetHookConfig(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc("/app/hook/config", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `{ + "content_type": "json", + "insecure_ssl": "0", + "secret": "********", + "url": "https://example.com/webhook" + }`) + }) + + ctx := context.Background() + config, _, err := client.Apps.GetHookConfig(ctx) + if err != nil { + t.Errorf("Apps.GetHookConfig returned error: %v", err) + } + + want := &HookConfig{ + ContentType: String("json"), + InsecureSSL: String("0"), + Secret: String("********"), + URL: String("https://example.com/webhook"), + } + if !cmp.Equal(config, want) { + t.Errorf("Apps.GetHookConfig returned %+v, want %+v", config, want) + } + + const methodName = "GetHookConfig" + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Apps.GetHookConfig(ctx) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} + +func TestAppsService_UpdateHookConfig(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + input := &HookConfig{ + ContentType: String("json"), + InsecureSSL: String("1"), + Secret: String("s"), + URL: String("u"), + } + + mux.HandleFunc("/app/hook/config", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "PATCH") + testBody(t, r, `{"content_type":"json","insecure_ssl":"1","url":"u","secret":"s"}`+"\n") + fmt.Fprint(w, `{ + "content_type": "json", + "insecure_ssl": "1", + "secret": "********", + "url": "u" + }`) + }) + + ctx := context.Background() + config, _, err := client.Apps.UpdateHookConfig(ctx, input) + if err != nil { + t.Errorf("Apps.UpdateHookConfig returned error: %v", err) + } + + want := &HookConfig{ + ContentType: String("json"), + InsecureSSL: String("1"), + Secret: String("********"), + URL: String("u"), + } + if !cmp.Equal(config, want) { + t.Errorf("Apps.UpdateHookConfig returned %+v, want %+v", config, want) + } + + const methodName = "UpdateHookConfig" + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Apps.UpdateHookConfig(ctx, input) + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} diff --git a/github/doc.go b/github/doc.go index 44658741175..85209c6f7e3 100644 --- a/github/doc.go +++ b/github/doc.go @@ -73,6 +73,10 @@ BasicAuthTransport. GitHub Apps authentication can be provided by the https://github.com/bradleyfalzon/ghinstallation package. +It supports both authentication as an installation, using an installation access token +and as an app, using a JWT. + +To authenticate as an installation: import "github.com/bradleyfalzon/ghinstallation" @@ -89,6 +93,23 @@ https://github.com/bradleyfalzon/ghinstallation package. // Use client... } +To authenticate as an app, using a JWT: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the application ID 1. + atr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use app transport with client + client := github.NewClient(&http.Client{Transport: atr}) + + // Use client... + } + Rate Limiting GitHub imposes a rate limit on all API clients. Unauthenticated clients are diff --git a/github/github-accessors.go b/github/github-accessors.go index 8422d6a7975..3695416ae07 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -4988,6 +4988,14 @@ func (h *HookConfig) GetInsecureSSL() string { return *h.InsecureSSL } +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetSecret() string { + if h == nil || h.Secret == nil { + return "" + } + return *h.Secret +} + // GetURL returns the URL field if it's non-nil, zero value otherwise. func (h *HookConfig) GetURL() string { if h == nil || h.URL == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index df604c449e2..d23414fe13f 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -5840,6 +5840,16 @@ func TestHookConfig_GetInsecureSSL(tt *testing.T) { h.GetInsecureSSL() } +func TestHookConfig_GetSecret(tt *testing.T) { + var zeroValue string + h := &HookConfig{Secret: &zeroValue} + h.GetSecret() + h = &HookConfig{} + h.GetSecret() + h = nil + h.GetSecret() +} + func TestHookConfig_GetURL(tt *testing.T) { var zeroValue string h := &HookConfig{URL: &zeroValue} diff --git a/github/orgs_audit_log.go b/github/orgs_audit_log.go index 81f0edac9bc..6947a5567f6 100644 --- a/github/orgs_audit_log.go +++ b/github/orgs_audit_log.go @@ -24,6 +24,9 @@ type HookConfig struct { ContentType *string `json:"content_type,omitempty"` InsecureSSL *string `json:"insecure_ssl,omitempty"` URL *string `json:"url,omitempty"` + + // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests + Secret *string `json:"secret,omitempty"` } // AuditEntry describes the fields that may be represented by various audit-log "action" entries. From def1026edcf1a7bf346d79f2e6397c955f733e8f Mon Sep 17 00:00:00 2001 From: Ronan Pelliard Date: Wed, 15 Sep 2021 14:05:48 +0200 Subject: [PATCH 2/5] Fix comment Co-authored-by: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> --- github/orgs_audit_log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/orgs_audit_log.go b/github/orgs_audit_log.go index 6947a5567f6..4b98ba690e3 100644 --- a/github/orgs_audit_log.go +++ b/github/orgs_audit_log.go @@ -25,7 +25,7 @@ type HookConfig struct { InsecureSSL *string `json:"insecure_ssl,omitempty"` URL *string `json:"url,omitempty"` - // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests + // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests. Secret *string `json:"secret,omitempty"` } From c54c06b710db72155fdfac5b1171638f2fb9a8dc Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:04:09 +0000 Subject: [PATCH 3/5] Update github/apps_hooks_test.go --- github/apps_hooks_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/github/apps_hooks_test.go b/github/apps_hooks_test.go index 4d49051256d..b00a74b73e9 100644 --- a/github/apps_hooks_test.go +++ b/github/apps_hooks_test.go @@ -1,3 +1,8 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package github import ( From e18619db57c243e8c00b6a8987a34379fdc1477b Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:04:17 +0000 Subject: [PATCH 4/5] Update github/apps_hooks.go --- github/apps_hooks.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/github/apps_hooks.go b/github/apps_hooks.go index 2b2c309cdde..ed8396f4425 100644 --- a/github/apps_hooks.go +++ b/github/apps_hooks.go @@ -1,3 +1,8 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package github import ( From d51a8db94915b143627721cc47bae7227b6fce04 Mon Sep 17 00:00:00 2001 From: Glenn Lewis <6598971+gmlewis@users.noreply.github.com> Date: Wed, 29 Sep 2021 14:17:32 +0000 Subject: [PATCH 5/5] Update github/doc.go Co-authored-by: Parker77 --- github/doc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github/doc.go b/github/doc.go index 85209c6f7e3..87eda1dec70 100644 --- a/github/doc.go +++ b/github/doc.go @@ -73,7 +73,7 @@ BasicAuthTransport. GitHub Apps authentication can be provided by the https://github.com/bradleyfalzon/ghinstallation package. -It supports both authentication as an installation, using an installation access token +It supports both authentication as an installation, using an installation access token, and as an app, using a JWT. To authenticate as an installation: