Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hooks support for PubSubHubBub API. #1540

Open
wants to merge 1 commit into
base: master
from

Conversation

@joshuabezaleel
Copy link
Contributor

joshuabezaleel commented May 27, 2020

Add support for repository webhooks via GitHub's PubSubHubBub API.

Fixes: #1265

@googlebot googlebot added the cla: yes label May 27, 2020
@codecov
Copy link

codecov bot commented May 27, 2020

Codecov Report

Merging #1540 into master will increase coverage by 0.02%.
The diff coverage is 82.35%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1540      +/-   ##
==========================================
+ Coverage   68.01%   68.04%   +0.02%     
==========================================
  Files          94       94              
  Lines        8560     8577      +17     
==========================================
+ Hits         5822     5836      +14     
- Misses       1852     1854       +2     
- Partials      886      887       +1     
Impacted Files Coverage Δ
github/repos_hooks.go 77.35% <82.35%> (+0.95%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a37dd2d...ad4e159. Read the comment docs.

@joshuabezaleel joshuabezaleel marked this pull request as draft May 27, 2020
@joshuabezaleel joshuabezaleel marked this pull request as ready for review May 27, 2020
Copy link
Contributor

nightlark left a comment

A few comment nits. Some of the other structs for requests have a comment mentioning fields that are required and a list of possible choices (e.g. modes).

// CreatePubSubHubBubrequest lets servers register receive updates when a topic is updated
// using publish/subscribe protocol with GitHub as the hub for the repositories.
Comment on lines +253 to +254

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
// CreatePubSubHubBubrequest lets servers register receive updates when a topic is updated
// using publish/subscribe protocol with GitHub as the hub for the repositories.
// CreatePubSubHubbubRequest lets servers register to receive updates when a topic is updated
// using a publish/subscribe protocol with GitHub as the hub for the repositories.
// PubSubHubBubRequest represents the request to be send
// for the GitHub's publish/subscribe hub protocol.
Comment on lines +101 to +102

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
// PubSubHubBubRequest represents the request to be send
// for the GitHub's publish/subscribe hub protocol.
// PubSubHubbubRequest represents the request to be sent
// for GitHub's publish/subscribe hub protocol.
Copy link
Contributor

nightlark left a comment

Not sure if this is a change you'd want to make, but it looks like the name in the docs and github repo on the protocol is PubSubHubbub because hubbub is a (surprisingly fitting) word.

// for the GitHub's publish/subscribe hub protocol.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#subscribing
type PubSubHubBubRequest struct {

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
type PubSubHubBubRequest struct {
type PubSubHubbubRequest struct {
Event string `json:"events,omitempty"`
}

type pubSubHubBubPayload struct {

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
type pubSubHubBubPayload struct {
type pubSubHubbubPayload struct {
// using publish/subscribe protocol with GitHub as the hub for the repositories.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#pubsubhubbub
func (s *RepositoriesService) CreatePubSubHubBubRequest(ctx context.Context, request *PubSubHubBubRequest) (*Response, error) {

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
func (s *RepositoriesService) CreatePubSubHubBubRequest(ctx context.Context, request *PubSubHubBubRequest) (*Response, error) {
func (s *RepositoriesService) CreatePubSubHubbubRequest(ctx context.Context, request *PubSubHubbubRequest) (*Response, error) {

hubTopic := fmt.Sprintf("/%v/%v/events/%v", request.HubTopic.Owner, request.HubTopic.Repo, request.HubTopic.Event)

pubSubHubBubReq := &pubSubHubBubPayload{

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
pubSubHubBubReq := &pubSubHubBubPayload{
pubSubHubbubReq := &pubSubHubbubPayload{
HubSecret: request.HubSecret,
}

req, err := s.client.NewRequest("POST", u, pubSubHubBubReq)

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
req, err := s.client.NewRequest("POST", u, pubSubHubBubReq)
req, err := s.client.NewRequest("POST", u, pubSubHubbubReq)
@@ -197,3 +197,27 @@ func TestRepositoriesService_TestHook_invalidOwner(t *testing.T) {
_, err := client.Repositories.TestHook(context.Background(), "%", "%", 1)
testURLParseError(t, err)
}

func TestRepositoriesService_TestPubSubHubBub(t *testing.T) {

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
func TestRepositoriesService_TestPubSubHubBub(t *testing.T) {
func TestRepositoriesService_TestPubSubHubbub(t *testing.T) {
testMethod(t, r, "POST")
})

pubSubHubBubreq := &PubSubHubBubRequest{

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
pubSubHubBubreq := &PubSubHubBubRequest{
pubSubHubbubreq := &PubSubHubbubRequest{
HubCallback: "http://postbin.org/123",
}

_, err := client.Repositories.CreatePubSubHubBubRequest(context.Background(), pubSubHubBubreq)

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
_, err := client.Repositories.CreatePubSubHubBubRequest(context.Background(), pubSubHubBubreq)
_, err := client.Repositories.CreatePubSubHubbubRequest(context.Background(), pubSubHubbubreq)

_, err := client.Repositories.CreatePubSubHubBubRequest(context.Background(), pubSubHubBubreq)
if err != nil {
t.Errorf("Repositories.CreatePubSubHubBubrequest returned error: %v", err)

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
t.Errorf("Repositories.CreatePubSubHubBubrequest returned error: %v", err)
t.Errorf("Repositories.CreatePubSubHubbubRequest returned error: %v", err)
HubCallback: "http://postbin.org/123",
}

_, err := client.Repositories.CreatePubSubHubBubRequest(context.Background(), pubSubHubBubreq)

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor
Suggested change
_, err := client.Repositories.CreatePubSubHubBubRequest(context.Background(), pubSubHubBubreq)
_, err := client.Repositories.CreatePubSubHubbubRequest(context.Background(), pubSubHubbubreq)
Copy link
Collaborator

gmlewis left a comment

Thank you, @joshuabezaleel - you are off to a good start.
Have you been able to test this out? It would be interesting to see if this works.

I'm not sure that it will, however, because the examples given show curl -F which from the man pages emulates a form-field using Content-Type multipart/form-data according to RFC 2388.

In other words, to get this working you will probably at the very least need to add this "Content-Type" to the request headers. Check around this repo, as there are other places where we do this kind of thing.

So please try to get it working after you've addressed my feedback before we continue. If you run into problems, you can give details here and we can try to work through them.

Thank you!

@@ -224,3 +249,27 @@ func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string,
}
return s.client.Do(ctx, req, nil)
}

// CreatePubSubHubBubrequest lets servers register receive updates when a topic is updated

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

How about this (note the spelling - the GitHub docs don't capitalize "Bub"):

// SubscribePubSubHubbub lets servers register to receive updates when a topic is updated
// using the publish/subscribe protocol with GitHub as the hub for the repositories.
// using publish/subscribe protocol with GitHub as the hub for the repositories.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#pubsubhubbub
func (s *RepositoriesService) CreatePubSubHubBubRequest(ctx context.Context, request *PubSubHubBubRequest) (*Response, error) {

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Let's change request *PubSubHubBubRequest to:
opts *SubscribePubSubHubbubOpts.

@@ -98,6 +98,31 @@ type createHookRequest struct {
Active *bool `json:"active,omitempty"`
}

// PubSubHubBubRequest represents the request to be send

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Let's please change this to SubscribePubSubHubbubOpts (Note the lower-case "bub").

SubscribePubSubHubbubOpts represents the options to be sent for the SubscribePubSubHubbub endpoint.
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#subscribing
type PubSubHubBubRequest struct {
HubMode string `json:"hub_mode,omitempty"`
HubTopic Topic `json:"hub_topic,omitempty"`

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Please delete HubTopic since it is completely ignored.

HubSecret string `json:"hub_secret,omitempty"`
}

// Topic represents GitHub repository and its particular event.

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Please delete Topic entirely since it is never used.

Event string `json:"events,omitempty"`
}

type pubSubHubBubPayload struct {

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Bub => bub

This comment has been minimized.

Copy link
@nightlark

nightlark May 28, 2020

Contributor

@gmlewis can decide if this is a change that makes sense.

If the CreatePubSubHubBubRequest request/opts parameter gets replaced with owner, repo, event string, opts PubSubHububOpts (matching the way owner/repo args are used by other functions in go-github) then pubSubHubBubPayload could get turned into PubSubHubbubOpts as was suggested elsewhere by gmlewis, and PubSubHubbubRequest could be removed entirely.

//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#subscribing
type PubSubHubBubRequest struct {
HubMode string `json:"hub_mode,omitempty"`

This comment has been minimized.

Copy link
@gmlewis

gmlewis May 28, 2020

Collaborator

Please remove all the json tags, as they are unused.

@joshuabezaleel
Copy link
Contributor Author

joshuabezaleel commented Jun 3, 2020

Hi @gmlewis @nightlark , thank you very much for the really thorough and thoughtful review! Truly appreciate it 🙂

Truly sorry that I missed the multipart/form-data part, I think that was why I got 200 instead of the expected 204.
Please correct me if I am wrong on this but I found that nearly all of the request constructed on the methods are using NewRequest which specifies the body's Content-Type to application/json. The only one that I see using NewUploadRequest which enables the request to specify its own Content-Type is UploadReleaseAsset.

I searched that the way we can construct a multipart/form-data request and specify its Content-Type is by using mime/multipart's NewWriter to a buffer and add the writer.FormDataContentType() as request's header (reference 1, reference 2). Should I use this method or can I reuse NewUploadRequest?

Thank you very much in advance 🙂

@gmlewis
Copy link
Collaborator

gmlewis commented Jun 3, 2020

I don't have time now to dig into this, but if NewUploadRequest looks usable without modifying its behavior, I would suggest you try it out and then test locally to see if it works. If not, try the other route and again test locally to make sure it all works. Then please report back here with what you tried, what worked, and what failed. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

4 participants
You can’t perform that action at this time.