github.com/google/go-github/v49@v49.1.0/github/repos_hooks.go (about) 1 // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "fmt" 11 "net/http" 12 "net/url" 13 "strings" 14 "time" 15 ) 16 17 // WebHookPayload represents the data that is received from GitHub when a push 18 // event hook is triggered. The format of these payloads pre-date most of the 19 // GitHub v3 API, so there are lots of minor incompatibilities with the types 20 // defined in the rest of the API. Therefore, several types are duplicated 21 // here to account for these differences. 22 // 23 // GitHub API docs: https://help.github.com/articles/post-receive-hooks 24 // 25 // Deprecated: Please use PushEvent instead. 26 type WebHookPayload = PushEvent 27 28 // WebHookCommit represents the commit variant we receive from GitHub in a 29 // WebHookPayload. 30 // 31 // Deprecated: Please use HeadCommit instead. 32 type WebHookCommit = HeadCommit 33 34 // WebHookAuthor represents the author or committer of a commit, as specified 35 // in a WebHookCommit. The commit author may not correspond to a GitHub User. 36 // 37 // Deprecated: Please use CommitAuthor instead. 38 // NOTE Breaking API change: the `Username` field is now called `Login`. 39 type WebHookAuthor = CommitAuthor 40 41 // Hook represents a GitHub (web and service) hook for a repository. 42 type Hook struct { 43 CreatedAt *time.Time `json:"created_at,omitempty"` 44 UpdatedAt *time.Time `json:"updated_at,omitempty"` 45 URL *string `json:"url,omitempty"` 46 ID *int64 `json:"id,omitempty"` 47 Type *string `json:"type,omitempty"` 48 Name *string `json:"name,omitempty"` 49 TestURL *string `json:"test_url,omitempty"` 50 PingURL *string `json:"ping_url,omitempty"` 51 LastResponse map[string]interface{} `json:"last_response,omitempty"` 52 53 // Only the following fields are used when creating a hook. 54 // Config is required. 55 Config map[string]interface{} `json:"config,omitempty"` 56 Events []string `json:"events,omitempty"` 57 Active *bool `json:"active,omitempty"` 58 } 59 60 func (h Hook) String() string { 61 return Stringify(h) 62 } 63 64 // createHookRequest is a subset of Hook and is used internally 65 // by CreateHook to pass only the known fields for the endpoint. 66 // 67 // See https://github.com/google/go-github/issues/1015 for more 68 // information. 69 type createHookRequest struct { 70 // Config is required. 71 Name string `json:"name"` 72 Config map[string]interface{} `json:"config,omitempty"` 73 Events []string `json:"events,omitempty"` 74 Active *bool `json:"active,omitempty"` 75 } 76 77 // CreateHook creates a Hook for the specified repository. 78 // Config is a required field. 79 // 80 // Note that only a subset of the hook fields are used and hook must 81 // not be nil. 82 // 83 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#create-a-repository-webhook 84 func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { 85 u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) 86 87 hookReq := &createHookRequest{ 88 Name: "web", 89 Events: hook.Events, 90 Active: hook.Active, 91 Config: hook.Config, 92 } 93 94 req, err := s.client.NewRequest("POST", u, hookReq) 95 if err != nil { 96 return nil, nil, err 97 } 98 99 h := new(Hook) 100 resp, err := s.client.Do(ctx, req, h) 101 if err != nil { 102 return nil, resp, err 103 } 104 105 return h, resp, nil 106 } 107 108 // ListHooks lists all Hooks for the specified repository. 109 // 110 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#list-repository-webhooks 111 func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) { 112 u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) 113 u, err := addOptions(u, opts) 114 if err != nil { 115 return nil, nil, err 116 } 117 118 req, err := s.client.NewRequest("GET", u, nil) 119 if err != nil { 120 return nil, nil, err 121 } 122 123 var hooks []*Hook 124 resp, err := s.client.Do(ctx, req, &hooks) 125 if err != nil { 126 return nil, resp, err 127 } 128 129 return hooks, resp, nil 130 } 131 132 // GetHook returns a single specified Hook. 133 // 134 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#get-a-repository-webhook 135 func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { 136 u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) 137 req, err := s.client.NewRequest("GET", u, nil) 138 if err != nil { 139 return nil, nil, err 140 } 141 h := new(Hook) 142 resp, err := s.client.Do(ctx, req, h) 143 if err != nil { 144 return nil, resp, err 145 } 146 147 return h, resp, nil 148 } 149 150 // EditHook updates a specified Hook. 151 // 152 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#update-a-repository-webhook 153 func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { 154 u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) 155 req, err := s.client.NewRequest("PATCH", u, hook) 156 if err != nil { 157 return nil, nil, err 158 } 159 h := new(Hook) 160 resp, err := s.client.Do(ctx, req, h) 161 if err != nil { 162 return nil, resp, err 163 } 164 165 return h, resp, nil 166 } 167 168 // DeleteHook deletes a specified Hook. 169 // 170 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#delete-a-repository-webhook 171 func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { 172 u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) 173 req, err := s.client.NewRequest("DELETE", u, nil) 174 if err != nil { 175 return nil, err 176 } 177 return s.client.Do(ctx, req, nil) 178 } 179 180 // PingHook triggers a 'ping' event to be sent to the Hook. 181 // 182 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#ping-a-repository-webhook 183 func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { 184 u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) 185 req, err := s.client.NewRequest("POST", u, nil) 186 if err != nil { 187 return nil, err 188 } 189 return s.client.Do(ctx, req, nil) 190 } 191 192 // TestHook triggers a test Hook by github. 193 // 194 // GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#test-the-push-repository-webhook 195 func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { 196 u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) 197 req, err := s.client.NewRequest("POST", u, nil) 198 if err != nil { 199 return nil, err 200 } 201 return s.client.Do(ctx, req, nil) 202 } 203 204 // Subscribe lets servers register to receive updates when a topic is updated. 205 // 206 // GitHub API docs: https://docs.github.com/en/rest/webhooks#pubsubhubbub 207 func (s *RepositoriesService) Subscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { 208 req, err := s.createWebSubRequest("subscribe", owner, repo, event, callback, secret) 209 if err != nil { 210 return nil, err 211 } 212 213 return s.client.Do(ctx, req, nil) 214 } 215 216 // Unsubscribe lets servers unregister to no longer receive updates when a topic is updated. 217 // 218 // GitHub API docs: https://docs.github.com/en/rest/webhooks#pubsubhubbub 219 func (s *RepositoriesService) Unsubscribe(ctx context.Context, owner, repo, event, callback string, secret []byte) (*Response, error) { 220 req, err := s.createWebSubRequest("unsubscribe", owner, repo, event, callback, secret) 221 if err != nil { 222 return nil, err 223 } 224 225 return s.client.Do(ctx, req, nil) 226 } 227 228 // createWebSubRequest returns a subscribe/unsubscribe request that implements 229 // the WebSub (formerly PubSubHubbub) protocol. 230 // 231 // See: https://www.w3.org/TR/websub/#subscriber-sends-subscription-request 232 func (s *RepositoriesService) createWebSubRequest(hubMode, owner, repo, event, callback string, secret []byte) (*http.Request, error) { 233 topic := fmt.Sprintf( 234 "https://github.com/%s/%s/events/%s", 235 owner, 236 repo, 237 event, 238 ) 239 form := url.Values{} 240 form.Add("hub.mode", hubMode) 241 form.Add("hub.topic", topic) 242 form.Add("hub.callback", callback) 243 if secret != nil { 244 form.Add("hub.secret", string(secret)) 245 } 246 body := strings.NewReader(form.Encode()) 247 248 req, err := s.client.NewFormRequest("hub", body) 249 if err != nil { 250 return nil, err 251 } 252 253 return req, nil 254 }