Browse Source

Initial support for more comprehensive github webhooks

tags/v0.3.0
Russ Garrett 5 years ago
parent
commit
a484c38707
No account linked to committer's email address

+ 6
- 4
examples/irccat.json View File

@@ -9,10 +9,12 @@
9 9
     "tls_cert": "",
10 10
     "listeners": {
11 11
       "grafana": "#channel",
12
-      "github-releases": {
13
-	    "irccat": "#irccat-dev",
14
-	    "go": "#go-nuts"
15
-	  }
12
+      "github": {
13
+	"secret": "test",
14
+	"repositories": {
15
+	    "irccat": "#irccat-dev"
16
+	}
17
+       }
16 18
     }
17 19
   },
18 20
   "irc": {

+ 0
- 56
httplistener/github-releases.go View File

@@ -1,56 +0,0 @@
1
-package httplistener
2
-
3
-import (
4
-	"bytes"
5
-	"encoding/json"
6
-	"fmt"
7
-	"github.com/spf13/viper"
8
-	"net/http"
9
-)
10
-
11
-type githubRepository struct {
12
-	Name        string
13
-	Description string
14
-}
15
-
16
-type githubRelease struct {
17
-	Html_url string
18
-	Tag_name string
19
-	Name     string
20
-}
21
-
22
-type githubPayload struct {
23
-	Action     string
24
-	Release    githubRelease
25
-	Repository githubRepository
26
-}
27
-
28
-func (hl *HTTPListener) githubReleasesHandler(w http.ResponseWriter, request *http.Request) {
29
-	if request.Method != "POST" {
30
-		http.NotFound(w, request)
31
-		return
32
-	}
33
-
34
-	var payload githubPayload
35
-	buf := new(bytes.Buffer)
36
-	buf.ReadFrom(request.Body)
37
-	json.Unmarshal(buf.Bytes(), &payload)
38
-
39
-	if payload.Action == "published" {
40
-		name := payload.Repository.Description
41
-		if name == "" {
42
-			name = payload.Repository.Name
43
-		}
44
-		release := payload.Release.Name
45
-		if release == "" {
46
-			release = payload.Release.Tag_name
47
-		}
48
-
49
-		msg := fmt.Sprintf("[\x02Release\x0f] \x02%s\x0f version \x02%s\x0f has been published: %s", name, release, payload.Release.Html_url)
50
-
51
-		channelKey := fmt.Sprintf("http.listeners.github-releases.%s", payload.Repository.Name)
52
-		channel := viper.GetString(channelKey)
53
-		log.Infof("%s [%s] GitHub Release", request.RemoteAddr, channel)
54
-		hl.irc.Privmsgf(channel, msg)
55
-	}
56
-}

+ 139
- 0
httplistener/github.go View File

@@ -0,0 +1,139 @@
1
+package httplistener
2
+
3
+import (
4
+	"fmt"
5
+	"github.com/irccloud/irccat/util"
6
+	"github.com/spf13/viper"
7
+	"gopkg.in/go-playground/webhooks.v5/github"
8
+	"net/http"
9
+	"strings"
10
+)
11
+
12
+func formatRef(ref string) string {
13
+	parts := strings.Split(ref, "/")
14
+	res := ""
15
+	if parts[1] == "heads" {
16
+		res = "branch "
17
+	} else if parts[1] == "tags" {
18
+		res = "tag "
19
+	}
20
+	return res + parts[2]
21
+}
22
+
23
+func handleRelease(payload github.ReleasePayload) ([]string, string, bool) {
24
+	if payload.Action != "published" {
25
+		return []string{""}, "", false
26
+	}
27
+
28
+	var release string
29
+	if payload.Release.Name != nil {
30
+		release = *payload.Release.Name
31
+	}
32
+	if release == "" {
33
+		release = payload.Release.TagName
34
+	}
35
+
36
+	msg := fmt.Sprintf("[\x02%s\x0f] release \x02%s\x0f has been published by %s: %s",
37
+		payload.Repository.Name, release, payload.Release.Author.Login, payload.Release.HTMLURL)
38
+	return []string{msg}, payload.Repository.Name, true
39
+}
40
+
41
+func handlePush(payload github.PushPayload) ([]string, string, bool) {
42
+	var msgs []string
43
+
44
+	msgs = append(msgs, fmt.Sprintf("[\x02%s\x0f] %s pushed %d new commits to %s: %s",
45
+		payload.Repository.Name, payload.Sender.Login, len(payload.Commits),
46
+		formatRef(payload.Ref), payload.Compare))
47
+
48
+	commits_shown := 0
49
+	for _, commit := range payload.Commits {
50
+		if commits_shown == 3 {
51
+			break
52
+		}
53
+		if !commit.Distinct {
54
+			continue
55
+		}
56
+		msgs = append(msgs, fmt.Sprintf("\t%s: %s", commit.Author.Username, commit.Message))
57
+		commits_shown++
58
+	}
59
+	return msgs, payload.Repository.Name, true
60
+}
61
+
62
+func handleIssue(payload github.IssuesPayload) ([]string, string, bool) {
63
+	msg := fmt.Sprintf("[\x02%s\x0f] %s ", payload.Repository.Name, payload.Sender.Login)
64
+	issue_id := fmt.Sprintf("issue #%d", payload.Issue.Number)
65
+
66
+	show := true
67
+	switch payload.Action {
68
+	case "opened":
69
+		msg = msg + "opened " + issue_id
70
+	case "closed":
71
+		msg = msg + "closed " + issue_id
72
+	default:
73
+		// Don't know what to do with this, so don't show it
74
+		show = false
75
+	}
76
+
77
+	msg = msg + fmt.Sprintf(": %s %s", payload.Issue.Title, payload.Issue.HTMLURL)
78
+	return []string{msg}, payload.Repository.Name, show
79
+}
80
+
81
+func handleIssueComment(payload github.IssueCommentPayload) ([]string, string, bool) {
82
+	if payload.Action != "created" {
83
+		return []string{}, payload.Repository.Name, false
84
+	}
85
+
86
+	msg := fmt.Sprintf("[\x02%s\x0f] %s commented on issue %d: %s",
87
+		payload.Repository.Name, payload.Comment.User.Login,
88
+		payload.Issue.Number, util.Truncate(payload.Comment.Body, 150))
89
+	return []string{msg}, payload.Repository.Name, true
90
+}
91
+
92
+func (hl *HTTPListener) githubHandler(w http.ResponseWriter, request *http.Request) {
93
+	if request.Method != "POST" {
94
+		http.NotFound(w, request)
95
+		return
96
+	}
97
+	hook, err := github.New() // TODO: webhook secret
98
+	if err != nil {
99
+		return
100
+	}
101
+
102
+	// All valid events we want to receive need to be listed here.
103
+	payload, err := hook.Parse(request,
104
+		github.ReleaseEvent, github.PushEvent, github.IssuesEvent, github.IssueCommentEvent)
105
+
106
+	if err != nil {
107
+		log.Errorf("Error parsing github webhook: %s", err)
108
+		return
109
+	}
110
+
111
+	msgs := []string{}
112
+	repo := ""
113
+	send := false
114
+
115
+	switch payload.(type) {
116
+	case github.ReleasePayload:
117
+		msgs, repo, send = handleRelease(payload.(github.ReleasePayload))
118
+	case github.PushPayload:
119
+		msgs, repo, send = handlePush(payload.(github.PushPayload))
120
+	case github.IssuesPayload:
121
+		msgs, repo, send = handleIssue(payload.(github.IssuesPayload))
122
+	case github.IssueCommentPayload:
123
+		msgs, repo, send = handleIssueComment(payload.(github.IssueCommentPayload))
124
+	}
125
+
126
+	if send {
127
+		repo = strings.ToLower(repo)
128
+		channelKey := fmt.Sprintf("http.listeners.github.repositories.%s", repo)
129
+		channel := viper.GetString(channelKey)
130
+		if channel == "" {
131
+			log.Infof("%s GitHub event for unrecognised repository %s", request.RemoteAddr, repo)
132
+			return
133
+		}
134
+		log.Infof("%s [%s -> %s] GitHub event received", request.RemoteAddr, repo, channel)
135
+		for _, msg := range msgs {
136
+			hl.irc.Privmsgf(channel, msg)
137
+		}
138
+	}
139
+}

+ 4
- 2
httplistener/httplistener.go View File

@@ -24,11 +24,13 @@ func New(irc *irc.Connection) (*HTTPListener, error) {
24 24
 	mux.HandleFunc("/send", hl.genericHandler)
25 25
 
26 26
 	if viper.IsSet("http.listeners.grafana") {
27
+		log.Infof("Listening for Grafana webhooks at /grafana")
27 28
 		mux.HandleFunc("/grafana", hl.grafanaAlertHandler)
28 29
 	}
29 30
 
30
-	if viper.IsSet("http.listeners.github-releases") {
31
-		mux.HandleFunc("/github-releases", hl.githubReleasesHandler)
31
+	if viper.IsSet("http.listeners.github") {
32
+		log.Infof("Listening for GitHub webhooks at /github")
33
+		mux.HandleFunc("/github", hl.githubHandler)
32 34
 	}
33 35
 
34 36
 	hl.http.Handler = mux

+ 21
- 0
util/string.go View File

@@ -0,0 +1,21 @@
1
+package util
2
+
3
+import (
4
+	"unicode"
5
+)
6
+
7
+func Truncate(in string, length int) string {
8
+	if len(in) <= length {
9
+		return in
10
+	}
11
+
12
+	runes := []rune(in)
13
+
14
+	for i := len(runes) - 1; i > 1; i-- {
15
+		if unicode.IsSpace(runes[i]) && len(string(runes[:i])) < length {
16
+			return string(runes[:i]) + "…"
17
+		}
18
+	}
19
+
20
+	return ""
21
+}

+ 21
- 0
util/string_test.go View File

@@ -0,0 +1,21 @@
1
+package util
2
+
3
+import (
4
+	"testing"
5
+)
6
+
7
+func TestTruncate(t *testing.T) {
8
+	if Truncate("Test", 5) != "Test" {
9
+		t.Fail()
10
+	}
11
+	if Truncate("Test", 3) != "" {
12
+		t.Fail()
13
+	}
14
+	if Truncate("This is a test", 9) != "This is…" {
15
+		t.Fail()
16
+	}
17
+	if Truncate("This is a test", 10) != "This is a…" {
18
+		t.Fail()
19
+	}
20
+
21
+}

+ 202
- 0
webhook_test_data/github/issue_comment.json View File

@@ -0,0 +1,202 @@
1
+{
2
+  "action": "created",
3
+  "issue": {
4
+    "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2",
5
+    "repository_url": "https://api.github.com/repos/Codertocat/Hello-World",
6
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}",
7
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments",
8
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events",
9
+    "html_url": "https://github.com/Codertocat/Hello-World/issues/2",
10
+    "id": 327883527,
11
+    "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=",
12
+    "number": 2,
13
+    "title": "Spelling error in the README file",
14
+    "user": {
15
+      "login": "Codertocat",
16
+      "id": 21031067,
17
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
18
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
19
+      "gravatar_id": "",
20
+      "url": "https://api.github.com/users/Codertocat",
21
+      "html_url": "https://github.com/Codertocat",
22
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
23
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
24
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
25
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
26
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
27
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
28
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
29
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
30
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
31
+      "type": "User",
32
+      "site_admin": false
33
+    },
34
+    "labels": [
35
+      {
36
+        "id": 949737505,
37
+        "node_id": "MDU6TGFiZWw5NDk3Mzc1MDU=",
38
+        "url": "https://api.github.com/repos/Codertocat/Hello-World/labels/bug",
39
+        "name": "bug",
40
+        "color": "d73a4a",
41
+        "default": true
42
+      }
43
+    ],
44
+    "state": "open",
45
+    "locked": false,
46
+    "assignee": null,
47
+    "assignees": [
48
+
49
+    ],
50
+    "milestone": null,
51
+    "comments": 0,
52
+    "created_at": "2018-05-30T20:18:32Z",
53
+    "updated_at": "2018-05-30T20:18:32Z",
54
+    "closed_at": null,
55
+    "author_association": "OWNER",
56
+    "body": "It looks like you accidently spelled 'commit' with two 't's."
57
+  },
58
+  "comment": {
59
+    "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments/393304133",
60
+    "html_url": "https://github.com/Codertocat/Hello-World/issues/2#issuecomment-393304133",
61
+    "issue_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2",
62
+    "id": 393304133,
63
+    "node_id": "MDEyOklzc3VlQ29tbWVudDM5MzMwNDEzMw==",
64
+    "user": {
65
+      "login": "Codertocat",
66
+      "id": 21031067,
67
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
68
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
69
+      "gravatar_id": "",
70
+      "url": "https://api.github.com/users/Codertocat",
71
+      "html_url": "https://github.com/Codertocat",
72
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
73
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
74
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
75
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
76
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
77
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
78
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
79
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
80
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
81
+      "type": "User",
82
+      "site_admin": false
83
+    },
84
+    "created_at": "2018-05-30T20:18:32Z",
85
+    "updated_at": "2018-05-30T20:18:32Z",
86
+    "author_association": "OWNER",
87
+    "body": "You are totally right! I'll get this fixed right away."
88
+  },
89
+  "repository": {
90
+    "id": 135493233,
91
+    "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
92
+    "name": "Hello-World",
93
+    "full_name": "Codertocat/Hello-World",
94
+    "owner": {
95
+      "login": "Codertocat",
96
+      "id": 21031067,
97
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
98
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
99
+      "gravatar_id": "",
100
+      "url": "https://api.github.com/users/Codertocat",
101
+      "html_url": "https://github.com/Codertocat",
102
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
103
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
104
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
105
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
106
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
107
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
108
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
109
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
110
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
111
+      "type": "User",
112
+      "site_admin": false
113
+    },
114
+    "private": false,
115
+    "html_url": "https://github.com/Codertocat/Hello-World",
116
+    "description": null,
117
+    "fork": false,
118
+    "url": "https://api.github.com/repos/Codertocat/Hello-World",
119
+    "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks",
120
+    "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}",
121
+    "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}",
122
+    "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams",
123
+    "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks",
124
+    "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}",
125
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events",
126
+    "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}",
127
+    "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}",
128
+    "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags",
129
+    "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}",
130
+    "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}",
131
+    "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}",
132
+    "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}",
133
+    "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}",
134
+    "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages",
135
+    "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers",
136
+    "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors",
137
+    "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers",
138
+    "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription",
139
+    "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}",
140
+    "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}",
141
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}",
142
+    "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}",
143
+    "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}",
144
+    "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}",
145
+    "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges",
146
+    "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}",
147
+    "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads",
148
+    "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}",
149
+    "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}",
150
+    "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}",
151
+    "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
152
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}",
153
+    "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}",
154
+    "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments",
155
+    "created_at": "2018-05-30T20:18:04Z",
156
+    "updated_at": "2018-05-30T20:18:10Z",
157
+    "pushed_at": "2018-05-30T20:18:30Z",
158
+    "git_url": "git://github.com/Codertocat/Hello-World.git",
159
+    "ssh_url": "git@github.com:Codertocat/Hello-World.git",
160
+    "clone_url": "https://github.com/Codertocat/Hello-World.git",
161
+    "svn_url": "https://github.com/Codertocat/Hello-World",
162
+    "homepage": null,
163
+    "size": 0,
164
+    "stargazers_count": 0,
165
+    "watchers_count": 0,
166
+    "language": null,
167
+    "has_issues": true,
168
+    "has_projects": true,
169
+    "has_downloads": true,
170
+    "has_wiki": true,
171
+    "has_pages": true,
172
+    "forks_count": 0,
173
+    "mirror_url": null,
174
+    "archived": false,
175
+    "open_issues_count": 2,
176
+    "license": null,
177
+    "forks": 0,
178
+    "open_issues": 2,
179
+    "watchers": 0,
180
+    "default_branch": "master"
181
+  },
182
+  "sender": {
183
+    "login": "Codertocat",
184
+    "id": 21031067,
185
+    "node_id": "MDQ6VXNlcjIxMDMxMDY3",
186
+    "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
187
+    "gravatar_id": "",
188
+    "url": "https://api.github.com/users/Codertocat",
189
+    "html_url": "https://github.com/Codertocat",
190
+    "followers_url": "https://api.github.com/users/Codertocat/followers",
191
+    "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
192
+    "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
193
+    "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
194
+    "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
195
+    "organizations_url": "https://api.github.com/users/Codertocat/orgs",
196
+    "repos_url": "https://api.github.com/users/Codertocat/repos",
197
+    "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
198
+    "received_events_url": "https://api.github.com/users/Codertocat/received_events",
199
+    "type": "User",
200
+    "site_admin": false
201
+  }
202
+}

+ 173
- 0
webhook_test_data/github/issues.json View File

@@ -0,0 +1,173 @@
1
+{
2
+  "action": "opened",
3
+  "issue": {
4
+    "url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2",
5
+    "repository_url": "https://api.github.com/repos/Codertocat/Hello-World",
6
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/labels{/name}",
7
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/comments",
8
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/2/events",
9
+    "html_url": "https://github.com/Codertocat/Hello-World/issues/2",
10
+    "id": 327883527,
11
+    "node_id": "MDU6SXNzdWUzMjc4ODM1Mjc=",
12
+    "number": 2,
13
+    "title": "Spelling error in the README file",
14
+    "user": {
15
+      "login": "Codertocat",
16
+      "id": 21031067,
17
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
18
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
19
+      "gravatar_id": "",
20
+      "url": "https://api.github.com/users/Codertocat",
21
+      "html_url": "https://github.com/Codertocat",
22
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
23
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
24
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
25
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
26
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
27
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
28
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
29
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
30
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
31
+      "type": "User",
32
+      "site_admin": false
33
+    },
34
+    "labels": [
35
+      {
36
+        "id": 949737505,
37
+        "node_id": "MDU6TGFiZWw5NDk3Mzc1MDU=",
38
+        "url": "https://api.github.com/repos/Codertocat/Hello-World/labels/bug",
39
+        "name": "bug",
40
+        "color": "d73a4a",
41
+        "default": true
42
+      }
43
+    ],
44
+    "state": "open",
45
+    "locked": false,
46
+    "assignee": null,
47
+    "assignees": [
48
+
49
+    ],
50
+    "milestone": null,
51
+    "comments": 0,
52
+    "created_at": "2018-05-30T20:18:32Z",
53
+    "updated_at": "2018-05-30T20:18:32Z",
54
+    "closed_at": null,
55
+    "author_association": "OWNER",
56
+    "body": "It looks like you accidently spelled 'commit' with two 't's."
57
+  },
58
+  "changes": {
59
+  },
60
+  "repository": {
61
+    "id": 135493233,
62
+    "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
63
+    "name": "Hello-World",
64
+    "full_name": "Codertocat/Hello-World",
65
+    "owner": {
66
+      "login": "Codertocat",
67
+      "id": 21031067,
68
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
69
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
70
+      "gravatar_id": "",
71
+      "url": "https://api.github.com/users/Codertocat",
72
+      "html_url": "https://github.com/Codertocat",
73
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
74
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
75
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
76
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
77
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
78
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
79
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
80
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
81
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
82
+      "type": "User",
83
+      "site_admin": false
84
+    },
85
+    "private": false,
86
+    "html_url": "https://github.com/Codertocat/Hello-World",
87
+    "description": null,
88
+    "fork": false,
89
+    "url": "https://api.github.com/repos/Codertocat/Hello-World",
90
+    "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks",
91
+    "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}",
92
+    "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}",
93
+    "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams",
94
+    "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks",
95
+    "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}",
96
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events",
97
+    "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}",
98
+    "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}",
99
+    "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags",
100
+    "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}",
101
+    "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}",
102
+    "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}",
103
+    "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}",
104
+    "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}",
105
+    "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages",
106
+    "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers",
107
+    "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors",
108
+    "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers",
109
+    "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription",
110
+    "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}",
111
+    "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}",
112
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}",
113
+    "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}",
114
+    "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}",
115
+    "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}",
116
+    "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges",
117
+    "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}",
118
+    "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads",
119
+    "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}",
120
+    "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}",
121
+    "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}",
122
+    "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
123
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}",
124
+    "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}",
125
+    "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments",
126
+    "created_at": "2018-05-30T20:18:04Z",
127
+    "updated_at": "2018-05-30T20:18:10Z",
128
+    "pushed_at": "2018-05-30T20:18:30Z",
129
+    "git_url": "git://github.com/Codertocat/Hello-World.git",
130
+    "ssh_url": "git@github.com:Codertocat/Hello-World.git",
131
+    "clone_url": "https://github.com/Codertocat/Hello-World.git",
132
+    "svn_url": "https://github.com/Codertocat/Hello-World",
133
+    "homepage": null,
134
+    "size": 0,
135
+    "stargazers_count": 0,
136
+    "watchers_count": 0,
137
+    "language": null,
138
+    "has_issues": true,
139
+    "has_projects": true,
140
+    "has_downloads": true,
141
+    "has_wiki": true,
142
+    "has_pages": true,
143
+    "forks_count": 0,
144
+    "mirror_url": null,
145
+    "archived": false,
146
+    "open_issues_count": 2,
147
+    "license": null,
148
+    "forks": 0,
149
+    "open_issues": 2,
150
+    "watchers": 0,
151
+    "default_branch": "master"
152
+  },
153
+  "sender": {
154
+    "login": "Codertocat",
155
+    "id": 21031067,
156
+    "node_id": "MDQ6VXNlcjIxMDMxMDY3",
157
+    "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
158
+    "gravatar_id": "",
159
+    "url": "https://api.github.com/users/Codertocat",
160
+    "html_url": "https://github.com/Codertocat",
161
+    "followers_url": "https://api.github.com/users/Codertocat/followers",
162
+    "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
163
+    "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
164
+    "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
165
+    "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
166
+    "organizations_url": "https://api.github.com/users/Codertocat/orgs",
167
+    "repos_url": "https://api.github.com/users/Codertocat/repos",
168
+    "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
169
+    "received_events_url": "https://api.github.com/users/Codertocat/received_events",
170
+    "type": "User",
171
+    "site_admin": false
172
+  }
173
+}

+ 174
- 0
webhook_test_data/github/push.json View File

@@ -0,0 +1,174 @@
1
+{
2
+  "ref": "refs/tags/simple-tag",
3
+  "before": "a10867b14bb761a232cd80139fbd4c0d33264240",
4
+  "after": "0000000000000000000000000000000000000000",
5
+  "created": false,
6
+  "deleted": true,
7
+  "forced": false,
8
+  "base_ref": null,
9
+  "compare": "https://github.com/Codertocat/Hello-World/compare/a10867b14bb7...000000000000",
10
+  "commits": [
11
+	  {
12
+		"sha": "a10867b14bb761a232cd80139fbd4c0d33264240",
13
+		"id": "1234",
14
+		"tree_id": "1234",
15
+		"distinct": true,
16
+		"message": "Test Commit 1",
17
+		"url": "https://example.com",
18
+		"author": {"username": "Codertocat"},
19
+		"commiter": {}
20
+	  },
21
+	  {
22
+		"sha": "a10867b14bb761a232cd80139fbd4c0d33264240",
23
+		"id": "1234",
24
+		"tree_id": "1234",
25
+		"distinct": true,
26
+		"message": "Test Commit 2",
27
+		"url": "https://example.com",
28
+		"author": {"username": "Codertocat"},
29
+		"commiter": {}
30
+	  },
31
+	  {
32
+		"sha": "a10867b14bb761a232cd80139fbd4c0d33264240",
33
+		"id": "1234",
34
+		"tree_id": "1234",
35
+		"distinct": true,
36
+		"message": "Test Commit 3",
37
+		"url": "https://example.com",
38
+		"author": {"username": "Codertocat"},
39
+		"commiter": {}
40
+	  },
41
+	  {
42
+		"sha": "a10867b14bb761a232cd80139fbd4c0d33264240",
43
+		"id": "1234",
44
+		"tree_id": "1234",
45
+		"distinct": true,
46
+		"message": "Test Commit 4",
47
+		"url": "https://example.com",
48
+		"author": {"username": "Codertocat"},
49
+		"commiter": {}
50
+	  }
51
+  ],
52
+  "head_commit": null,
53
+  "repository": {
54
+    "id": 135493233,
55
+    "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
56
+    "name": "Hello-World",
57
+    "full_name": "Codertocat/Hello-World",
58
+    "owner": {
59
+      "name": "Codertocat",
60
+      "email": "21031067+Codertocat@users.noreply.github.com",
61
+      "login": "Codertocat",
62
+      "id": 21031067,
63
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
64
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
65
+      "gravatar_id": "",
66
+      "url": "https://api.github.com/users/Codertocat",
67
+      "html_url": "https://github.com/Codertocat",
68
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
69
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
70
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
71
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
72
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
73
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
74
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
75
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
76
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
77
+      "type": "User",
78
+      "site_admin": false
79
+    },
80
+    "private": false,
81
+    "html_url": "https://github.com/Codertocat/Hello-World",
82
+    "description": null,
83
+    "fork": false,
84
+    "url": "https://github.com/Codertocat/Hello-World",
85
+    "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks",
86
+    "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}",
87
+    "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}",
88
+    "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams",
89
+    "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks",
90
+    "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}",
91
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events",
92
+    "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}",
93
+    "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}",
94
+    "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags",
95
+    "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}",
96
+    "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}",
97
+    "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}",
98
+    "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}",
99
+    "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}",
100
+    "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages",
101
+    "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers",
102
+    "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors",
103
+    "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers",
104
+    "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription",
105
+    "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}",
106
+    "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}",
107
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}",
108
+    "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}",
109
+    "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}",
110
+    "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}",
111
+    "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges",
112
+    "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}",
113
+    "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads",
114
+    "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}",
115
+    "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}",
116
+    "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}",
117
+    "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
118
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}",
119
+    "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}",
120
+    "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments",
121
+    "created_at": 1527711484,
122
+    "updated_at": "2018-05-30T20:18:35Z",
123
+    "pushed_at": 1527711528,
124
+    "git_url": "git://github.com/Codertocat/Hello-World.git",
125
+    "ssh_url": "git@github.com:Codertocat/Hello-World.git",
126
+    "clone_url": "https://github.com/Codertocat/Hello-World.git",
127
+    "svn_url": "https://github.com/Codertocat/Hello-World",
128
+    "homepage": null,
129
+    "size": 0,
130
+    "stargazers_count": 0,
131
+    "watchers_count": 0,
132
+    "language": null,
133
+    "has_issues": true,
134
+    "has_projects": true,
135
+    "has_downloads": true,
136
+    "has_wiki": true,
137
+    "has_pages": true,
138
+    "forks_count": 0,
139
+    "mirror_url": null,
140
+    "archived": false,
141
+    "open_issues_count": 2,
142
+    "license": null,
143
+    "forks": 0,
144
+    "open_issues": 2,
145
+    "watchers": 0,
146
+    "default_branch": "master",
147
+    "stargazers": 0,
148
+    "master_branch": "master"
149
+  },
150
+  "pusher": {
151
+    "name": "Codertocat",
152
+    "email": "21031067+Codertocat@users.noreply.github.com"
153
+  },
154
+  "sender": {
155
+    "login": "Codertocat",
156
+    "id": 21031067,
157
+    "node_id": "MDQ6VXNlcjIxMDMxMDY3",
158
+    "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
159
+    "gravatar_id": "",
160
+    "url": "https://api.github.com/users/Codertocat",
161
+    "html_url": "https://github.com/Codertocat",
162
+    "followers_url": "https://api.github.com/users/Codertocat/followers",
163
+    "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
164
+    "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
165
+    "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
166
+    "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
167
+    "organizations_url": "https://api.github.com/users/Codertocat/orgs",
168
+    "repos_url": "https://api.github.com/users/Codertocat/repos",
169
+    "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
170
+    "received_events_url": "https://api.github.com/users/Codertocat/received_events",
171
+    "type": "User",
172
+    "site_admin": false
173
+  }
174
+}

+ 157
- 0
webhook_test_data/github/release.json View File

@@ -0,0 +1,157 @@
1
+{
2
+  "action": "published",
3
+  "release": {
4
+    "url": "https://api.github.com/repos/Codertocat/Hello-World/releases/11248810",
5
+    "assets_url": "https://api.github.com/repos/Codertocat/Hello-World/releases/11248810/assets",
6
+    "upload_url": "https://uploads.github.com/repos/Codertocat/Hello-World/releases/11248810/assets{?name,label}",
7
+    "html_url": "https://github.com/Codertocat/Hello-World/releases/tag/0.0.1",
8
+    "id": 11248810,
9
+    "node_id": "MDc6UmVsZWFzZTExMjQ4ODEw",
10
+    "tag_name": "0.0.1",
11
+    "target_commitish": "master",
12
+    "name": null,
13
+    "draft": false,
14
+    "author": {
15
+      "login": "Codertocat",
16
+      "id": 21031067,
17
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
18
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
19
+      "gravatar_id": "",
20
+      "url": "https://api.github.com/users/Codertocat",
21
+      "html_url": "https://github.com/Codertocat",
22
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
23
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
24
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
25
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
26
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
27
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
28
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
29
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
30
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
31
+      "type": "User",
32
+      "site_admin": false
33
+    },
34
+    "prerelease": false,
35
+    "created_at": "2018-05-30T20:18:05Z",
36
+    "published_at": "2018-05-30T20:18:44Z",
37
+    "assets": [
38
+
39
+    ],
40
+    "tarball_url": "https://api.github.com/repos/Codertocat/Hello-World/tarball/0.0.1",
41
+    "zipball_url": "https://api.github.com/repos/Codertocat/Hello-World/zipball/0.0.1",
42
+    "body": null
43
+  },
44
+  "repository": {
45
+    "id": 135493233,
46
+    "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=",
47
+    "name": "Hello-World",
48
+    "full_name": "Codertocat/Hello-World",
49
+    "owner": {
50
+      "login": "Codertocat",
51
+      "id": 21031067,
52
+      "node_id": "MDQ6VXNlcjIxMDMxMDY3",
53
+      "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
54
+      "gravatar_id": "",
55
+      "url": "https://api.github.com/users/Codertocat",
56
+      "html_url": "https://github.com/Codertocat",
57
+      "followers_url": "https://api.github.com/users/Codertocat/followers",
58
+      "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
59
+      "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
60
+      "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
61
+      "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
62
+      "organizations_url": "https://api.github.com/users/Codertocat/orgs",
63
+      "repos_url": "https://api.github.com/users/Codertocat/repos",
64
+      "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
65
+      "received_events_url": "https://api.github.com/users/Codertocat/received_events",
66
+      "type": "User",
67
+      "site_admin": false
68
+    },
69
+    "private": false,
70
+    "html_url": "https://github.com/Codertocat/Hello-World",
71
+    "description": null,
72
+    "fork": false,
73
+    "url": "https://api.github.com/repos/Codertocat/Hello-World",
74
+    "forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks",
75
+    "keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}",
76
+    "collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}",
77
+    "teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams",
78
+    "hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks",
79
+    "issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}",
80
+    "events_url": "https://api.github.com/repos/Codertocat/Hello-World/events",
81
+    "assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}",
82
+    "branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}",
83
+    "tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags",
84
+    "blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}",
85
+    "git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}",
86
+    "git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}",
87
+    "trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}",
88
+    "statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}",
89
+    "languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages",
90
+    "stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers",
91
+    "contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors",
92
+    "subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers",
93
+    "subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription",
94
+    "commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}",
95
+    "git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}",
96
+    "comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}",
97
+    "issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}",
98
+    "contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}",
99
+    "compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}",
100
+    "merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges",
101
+    "archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}",
102
+    "downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads",
103
+    "issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}",
104
+    "pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}",
105
+    "milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}",
106
+    "notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
107
+    "labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}",
108
+    "releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}",
109
+    "deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments",
110
+    "created_at": "2018-05-30T20:18:04Z",
111
+    "updated_at": "2018-05-30T20:18:35Z",
112
+    "pushed_at": "2018-05-30T20:18:44Z",
113
+    "git_url": "git://github.com/Codertocat/Hello-World.git",
114
+    "ssh_url": "git@github.com:Codertocat/Hello-World.git",
115
+    "clone_url": "https://github.com/Codertocat/Hello-World.git",
116
+    "svn_url": "https://github.com/Codertocat/Hello-World",
117
+    "homepage": null,
118
+    "size": 0,
119
+    "stargazers_count": 0,
120
+    "watchers_count": 0,
121
+    "language": null,
122
+    "has_issues": true,
123
+    "has_projects": true,
124
+    "has_downloads": true,
125
+    "has_wiki": true,
126
+    "has_pages": true,
127
+    "forks_count": 0,
128
+    "mirror_url": null,
129
+    "archived": false,
130
+    "open_issues_count": 2,
131
+    "license": null,
132
+    "forks": 0,
133
+    "open_issues": 2,
134
+    "watchers": 0,
135
+    "default_branch": "master"
136
+  },
137
+  "sender": {
138
+    "login": "Codertocat",
139
+    "id": 21031067,
140
+    "node_id": "MDQ6VXNlcjIxMDMxMDY3",
141
+    "avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
142
+    "gravatar_id": "",
143
+    "url": "https://api.github.com/users/Codertocat",
144
+    "html_url": "https://github.com/Codertocat",
145
+    "followers_url": "https://api.github.com/users/Codertocat/followers",
146
+    "following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
147
+    "gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
148
+    "starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
149
+    "subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
150
+    "organizations_url": "https://api.github.com/users/Codertocat/orgs",
151
+    "repos_url": "https://api.github.com/users/Codertocat/repos",
152
+    "events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
153
+    "received_events_url": "https://api.github.com/users/Codertocat/received_events",
154
+    "type": "User",
155
+    "site_admin": false
156
+  }
157
+}

Loading…
Cancel
Save