Repository: srvaroa/labeler
Pull request #9 (2020-05-10 22:53:21)

Add pr file matchers
Covers issue #5 

This adds matching against files in the PR.  One point of discussion would be should we print the list of pr file names?  for large PRs this could get long...

**Config**
```yaml
Label:
  files:
    - "cmd/.*.go"
    - "pkg/.*.go"
```

![image](https://user-images.githubusercontent.com/5356206/81512565-0c51a780-92e7-11ea-9bc2-9e25aaca5e4d.png)


Stoom: Merge conflicts should be fixed now
srvaroa: > One point of discussion would be should we print the list of pr file names? for large PRs this could get long...

I don't have a strong opinion here, it's true this could happen, but it's quite easy to silence the log of allow adding a log level in the config if it starts getting annoying.  If you prefer keeping it, go ahead.
Stoom: > I don't have a strong opinion here, it's true this could happen, but it's quite easy to silence the log of allow adding a log level in the config if it starts getting annoying. If you prefer keeping it, go ahead.

It's nice to see when debugging for sure
Stoom: @srvaroa All comments should be addressed
jnothman: I'd like to use this feature if you merge and release, thanks :)
srvaroa: Hi @jnothman, I can resolve conflicts and push later today probably, unless @stoom wants to do it in the PR earlier.

Patch:
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 9be56d7..7b49b57 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -1,2 +1,7 @@
-  TestLabel:
-        title: ".*"
+TestLabel:
+  title: ".*"
+TestFileMatch:
+  files: 
+    - "cmd/.*.go"
+    - "pkg/.*.go"
+  
\ No newline at end of file
diff --git a/README.md b/README.md
index e8137fb..cfc5808 100644
--- a/README.md
+++ b/README.md
@@ -85,6 +85,21 @@ This condition is satisfied when the PR title matches on the given regex.
     WIP:
       title: "^WIP:.*"
 
+### Regex on branch
+
+This condition is satisfied when the PR branch matches on the given regex.
+
+    Feature:
+      branch: "^feature/.*"
+
+### Regex on PR files
+
+This condition is satisfied when any of the PR files matches on the given regexs.
+
+    Tests:
+      files: 
+        - "cmd/.*_tests.go"
+
 ### Mergeable status
 
 This condition is satisfied when the PR is in a [mergeable state](https://developer.github.com/v3/pulls/#response-1).
diff --git a/go.mod b/go.mod
index baa29a4..312b8b0 100644
--- a/go.mod
+++ b/go.mod
@@ -9,5 +9,5 @@ require (
 	github.com/kr/pretty v0.1.0 // indirect
 	golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
-	gopkg.in/yaml.v2 v2.2.2 // indirect
+	github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d
 )
diff --git a/go.sum b/go.sum
index f3aeae1..e742021 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
 github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
 github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
@@ -13,6 +15,11 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d h1:xQcF7b7cZLWZG/+7A4G7un1qmEDYHIvId9qxRS1mZMs=
+github.com/waigani/diffparser v0.0.0-20190828052634-7391f219313d/go.mod h1:BzSc3WEF8R+lCaP5iGFRxd5kIXy4JKOZAwNe1w0cdc0=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
diff --git a/pkg/labeler.go b/pkg/labeler.go
index 49d478c..7b3077f 100644
--- a/pkg/labeler.go
+++ b/pkg/labeler.go
@@ -2,18 +2,24 @@ package labeler
 
 import (
 	"fmt"
+	"io/ioutil"
 	"log"
 	"math"
+	"net/http"
+	"os"
 	"regexp"
 	"strconv"
+	"strings"
 
 	gh "github.com/google/go-github/v27/github"
+	"github.com/waigani/diffparser"
 )
 
 type LabelerConfig map[string]LabelMatcher
 type LabelMatcher struct {
 	Title     string
 	Branch    string
+	Files     []string
 	Mergeable string
 	SizeBelow string `yaml:"size-below"`
 	SizeAbove string `yaml:"size-above"`
@@ -68,6 +74,41 @@ func NewBranchCondition() Condition {
 	}
 }
 
+func NewFilesCondition() Condition {
+	prFiles := []string{}
+
+	return Condition{
+		GetName: func() string {
+			return "File matches regex"
+		},
+		Evaluate: func(pr *gh.PullRequest, matcher LabelMatcher) (bool, error) {
+			if len(matcher.Files) <= 0 {
+				return false, fmt.Errorf("Files are not set in config")
+			}
+
+			if len(prFiles) == 0 {
+				var err error
+				prFiles, err = getPrFileNames(pr)
+				if err != nil {
+					return false, err
+				}
+			}
+
+			log.Printf("Matching `%s` against: %s", strings.Join(matcher.Files, ", "), strings.Join(prFiles, ", "))
+			for _, fileMatcher := range matcher.Files {
+				for _, prFile := range prFiles {
+					isMatched, _ := regexp.Match(fileMatcher, []byte(prFile))
+					if isMatched {
+						log.Printf("Matched `%s` against: `%s`", prFile, fileMatcher)
+						return isMatched, nil
+					}
+				}
+			}
+			return false, nil
+		},
+	}
+}
+
 func NewIsMergeableCondition() Condition {
 	return Condition{
 		GetName: func() string {
@@ -184,6 +225,7 @@ func (l *Labeler) findMatches(pr *gh.PullRequest, config *LabelerConfig) (LabelU
 		NewBranchCondition(),
 		NewIsMergeableCondition(),
 		NewSizeCondition(),
+		NewFilesCondition(),
 	}
 
 	for label, matcher := range *config {
@@ -204,3 +246,46 @@ func (l *Labeler) findMatches(pr *gh.PullRequest, config *LabelerConfig) (LabelU
 
 	return labelUpdates, nil
 }
+
+// getPrFileNames returns all of the file names (old and new) of files changed in the given PR
+func getPrFileNames(pr *gh.PullRequest) ([]string, error) {
+	ghToken := os.Getenv("GITHUB_TOKEN")
+	diffReq, err := http.NewRequest("GET", pr.GetDiffURL(), nil)
+
+	if err != nil {
+		return nil, err
+	}
+
+	diffReq.Header.Add("Authorization", "Bearer "+ghToken)
+	diffRes, err := http.DefaultClient.Do(diffReq)
+
+	if err != nil {
+		return nil, err
+	}
+
+	defer diffRes.Body.Close()
+
+	var diffRaw []byte
+	prFiles := make([]string, 0)
+	if diffRes.StatusCode == http.StatusOK {
+		diffRaw, err = ioutil.ReadAll(diffRes.Body)
+
+		if err != nil {
+			return nil, err
+		}
+
+		diff, _ := diffparser.Parse(string(diffRaw))
+		prFilesSet := map[string]struct{}{}
+		// Place in a set to remove duplicates
+		for _, file := range diff.Files {
+			prFilesSet[file.OrigName] = struct{}{}
+			prFilesSet[file.NewName] = struct{}{}
+		}
+		// Convert to list to make it easier to consume
+		for k := range prFilesSet {
+			prFiles = append(prFiles, k)
+		}
+	}
+
+	return prFiles, nil
+}


Test patch:
diff --git a/pkg/labeler_test.go b/pkg/labeler_test.go
index 7525134..7675f21 100644
--- a/pkg/labeler_test.go
+++ b/pkg/labeler_test.go
@@ -172,6 +172,19 @@ func TestHandleEvent(t *testing.T) {
 			initialLabels:  []string{},
 			expectedLabels: []string{},
 		},
+		TestCase{
+			payloads: []string{"diff_pr"},
+			name:     "Test the branch rule",
+			config: LabelerConfig{
+				"Files": LabelMatcher{
+					Files: []string{
+						"^pkg/.*_test.go",
+					},
+				},
+			},
+			initialLabels:  []string{},
+			expectedLabels: []string{"Files"},
+		},
 	}
 
 	for _, tc := range testCases {
diff --git a/test_data/diff_pr_payload b/test_data/diff_pr_payload
new file mode 100644
index 0000000..d2367dc
--- /dev/null
+++ b/test_data/diff_pr_payload
@@ -0,0 +1,495 @@
+{
+   "action": "reopened",
+   "number": 1,
+   "pull_request": {
+     "_links": {
+       "comments": {
+         "href": "https://api.github.com/repos/srvaroa/test/issues/1/comments"
+       },
+       "commits": {
+         "href": "https://api.github.com/repos/srvaroa/test/pulls/1/commits"
+       },
+       "html": {
+         "href": "https://github.com/srvaroa/test/pull/1"
+       },
+       "issue": {
+         "href": "https://api.github.com/repos/srvaroa/test/issues/1"
+       },
+       "review_comment": {
+         "href": "https://api.github.com/repos/srvaroa/test/pulls/comments{/number}"
+       },
+       "review_comments": {
+         "href": "https://api.github.com/repos/srvaroa/test/pulls/1/comments"
+       },
+       "self": {
+         "href": "https://api.github.com/repos/srvaroa/test/pulls/1"
+       },
+       "statuses": {
+         "href": "https://api.github.com/repos/srvaroa/test/statuses/9e70f2ce79dad397cd51cf68df06bb8e81f1dcae"
+       }
+     },
+     "additions": 3,
+     "assignee": {
+       "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+       "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+       "followers_url": "https://api.github.com/users/srvaroa/followers",
+       "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+       "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+       "gravatar_id": "",
+       "html_url": "https://github.com/srvaroa",
+       "id": 346110,
+       "login": "srvaroa",
+       "node_id": "MDQ6VXNlcjM0NjExMA==",
+       "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+       "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+       "repos_url": "https://api.github.com/users/srvaroa/repos",
+       "site_admin": false,
+       "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+       "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+       "type": "User",
+       "url": "https://api.github.com/users/srvaroa"
+     },
+     "assignees": [
+       {
+         "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+         "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+         "followers_url": "https://api.github.com/users/srvaroa/followers",
+         "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+         "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+         "gravatar_id": "",
+         "html_url": "https://github.com/srvaroa",
+         "id": 346110,
+         "login": "srvaroa",
+         "node_id": "MDQ6VXNlcjM0NjExMA==",
+         "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+         "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+         "repos_url": "https://api.github.com/users/srvaroa/repos",
+         "site_admin": false,
+         "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+         "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+         "type": "User",
+         "url": "https://api.github.com/users/srvaroa"
+       }
+     ],
+     "author_association": "OWNER",
+     "base": {
+       "label": "srvaroa:master",
+       "ref": "master",
+       "repo": {
+         "archive_url": "https://api.github.com/repos/srvaroa/test/{archive_format}{/ref}",
+         "archived": false,
+         "assignees_url": "https://api.github.com/repos/srvaroa/test/assignees{/user}",
+         "blobs_url": "https://api.github.com/repos/srvaroa/test/git/blobs{/sha}",
+         "branches_url": "https://api.github.com/repos/srvaroa/test/branches{/branch}",
+         "clone_url": "https://github.com/srvaroa/test.git",
+         "collaborators_url": "https://api.github.com/repos/srvaroa/test/collaborators{/collaborator}",
+         "comments_url": "https://api.github.com/repos/srvaroa/test/comments{/number}",
+         "commits_url": "https://api.github.com/repos/srvaroa/test/commits{/sha}",
+         "compare_url": "https://api.github.com/repos/srvaroa/test/compare/{base}...{head}",
+         "contents_url": "https://api.github.com/repos/srvaroa/test/contents/{+path}",
+         "contributors_url": "https://api.github.com/repos/srvaroa/test/contributors",
+         "created_at": "2019-08-21T22:50:07Z",
+         "default_branch": "master",
+         "deployments_url": "https://api.github.com/repos/srvaroa/test/deployments",
+         "description": null,
+         "disabled": false,
+         "downloads_url": "https://api.github.com/repos/srvaroa/test/downloads",
+         "events_url": "https://api.github.com/repos/srvaroa/test/events",
+         "fork": false,
+         "forks": 0,
+         "forks_count": 0,
+         "forks_url": "https://api.github.com/repos/srvaroa/test/forks",
+         "full_name": "srvaroa/test",
+         "git_commits_url": "https://api.github.com/repos/srvaroa/test/git/commits{/sha}",
+         "git_refs_url": "https://api.github.com/repos/srvaroa/test/git/refs{/sha}",
+         "git_tags_url": "https://api.github.com/repos/srvaroa/test/git/tags{/sha}",
+         "git_url": "git://github.com/srvaroa/test.git",
+         "has_downloads": true,
+         "has_issues": true,
+         "has_pages": false,
+         "has_projects": true,
+         "has_wiki": true,
+         "homepage": null,
+         "hooks_url": "https://api.github.com/repos/srvaroa/test/hooks",
+         "html_url": "https://github.com/srvaroa/test",
+         "id": 203675431,
+         "issue_comment_url": "https://api.github.com/repos/srvaroa/test/issues/comments{/number}",
+         "issue_events_url": "https://api.github.com/repos/srvaroa/test/issues/events{/number}",
+         "issues_url": "https://api.github.com/repos/srvaroa/test/issues{/number}",
+         "keys_url": "https://api.github.com/repos/srvaroa/test/keys{/key_id}",
+         "labels_url": "https://api.github.com/repos/srvaroa/test/labels{/name}",
+         "language": null,
+         "languages_url": "https://api.github.com/repos/srvaroa/test/languages",
+         "license": null,
+         "merges_url": "https://api.github.com/repos/srvaroa/test/merges",
+         "milestones_url": "https://api.github.com/repos/srvaroa/test/milestones{/number}",
+         "mirror_url": null,
+         "name": "test",
+         "node_id": "MDEwOlJlcG9zaXRvcnkyMDM2NzU0MzE=",
+         "notifications_url": "https://api.github.com/repos/srvaroa/test/notifications{?since,all,participating}",
+         "open_issues": 1,
+         "open_issues_count": 1,
+         "owner": {
+           "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+           "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+           "followers_url": "https://api.github.com/users/srvaroa/followers",
+           "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+           "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+           "gravatar_id": "",
+           "html_url": "https://github.com/srvaroa",
+           "id": 346110,
+           "login": "srvaroa",
+           "node_id": "MDQ6VXNlcjM0NjExMA==",
+           "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+           "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+           "repos_url": "https://api.github.com/users/srvaroa/repos",
+           "site_admin": false,
+           "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+           "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+           "type": "User",
+           "url": "https://api.github.com/users/srvaroa"
+         },
+         "private": true,
+         "pulls_url": "https://api.github.com/repos/srvaroa/test/pulls{/number}",
+         "pushed_at": "2019-08-22T22:08:28Z",
+         "releases_url": "https://api.github.com/repos/srvaroa/test/releases{/id}",
+         "size": 3,
+         "ssh_url": "git@github.com:srvaroa/test.git",
+         "stargazers_count": 0,
+         "stargazers_url": "https://api.github.com/repos/srvaroa/test/stargazers",
+         "statuses_url": "https://api.github.com/repos/srvaroa/test/statuses/{sha}",
+         "subscribers_url": "https://api.github.com/repos/srvaroa/test/subscribers",
+         "subscription_url": "https://api.github.com/repos/srvaroa/test/subscription",
+         "svn_url": "https://github.com/srvaroa/test",
+         "tags_url": "https://api.github.com/repos/srvaroa/test/tags",
+         "teams_url": "https://api.github.com/repos/srvaroa/test/teams",
+         "trees_url": "https://api.github.com/repos/srvaroa/test/git/trees{/sha}",
+         "updated_at": "2019-08-22T22:05:35Z",
+         "url": "https://api.github.com/repos/srvaroa/test",
+         "watchers": 0,
+         "watchers_count": 0
+       },
+       "sha": "e3a8471a3505efc9fbe75a81759812f7e1daf449",
+       "user": {
+         "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+         "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+         "followers_url": "https://api.github.com/users/srvaroa/followers",
+         "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+         "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+         "gravatar_id": "",
+         "html_url": "https://github.com/srvaroa",
+         "id": 346110,
+         "login": "srvaroa",
+         "node_id": "MDQ6VXNlcjM0NjExMA==",
+         "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+         "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+         "repos_url": "https://api.github.com/users/srvaroa/repos",
+         "site_admin": false,
+         "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+         "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+         "type": "User",
+         "url": "https://api.github.com/users/srvaroa"
+       }
+     },
+     "body": "",
+     "changed_files": 2,
+     "closed_at": null,
+     "comments": 0,
+     "comments_url": "https://api.github.com/repos/srvaroa/test/issues/1/comments",
+     "commits": 3,
+     "commits_url": "https://api.github.com/repos/srvaroa/test/pulls/1/commits",
+     "created_at": "2019-08-21T22:56:32Z",
+     "deletions": 1,
+     "diff_url": "https://github.com/srvaroa/labeler/pull/2.diff",
+     "draft": false,
+     "head": {
+       "label": "srvaroa:srvaroa-patch-1",
+       "ref": "srvaroa-patch-1",
+       "repo": {
+         "archive_url": "https://api.github.com/repos/srvaroa/test/{archive_format}{/ref}",
+         "archived": false,
+         "assignees_url": "https://api.github.com/repos/srvaroa/test/assignees{/user}",
+         "blobs_url": "https://api.github.com/repos/srvaroa/test/git/blobs{/sha}",
+         "branches_url": "https://api.github.com/repos/srvaroa/test/branches{/branch}",
+         "clone_url": "https://github.com/srvaroa/test.git",
+         "collaborators_url": "https://api.github.com/repos/srvaroa/test/collaborators{/collaborator}",
+         "comments_url": "https://api.github.com/repos/srvaroa/test/comments{/number}",
+         "commits_url": "https://api.github.com/repos/srvaroa/test/commits{/sha}",
+         "compare_url": "https://api.github.com/repos/srvaroa/test/compare/{base}...{head}",
+         "contents_url": "https://api.github.com/repos/srvaroa/test/contents/{+path}",
+         "contributors_url": "https://api.github.com/repos/srvaroa/test/contributors",
+         "created_at": "2019-08-21T22:50:07Z",
+         "default_branch": "master",
+         "deployments_url": "https://api.github.com/repos/srvaroa/test/deployments",
+         "description": null,
+         "disabled": false,
+         "downloads_url": "https://api.github.com/repos/srvaroa/test/downloads",
+         "events_url": "https://api.github.com/repos/srvaroa/test/events",
+         "fork": false,
+         "forks": 0,
+         "forks_count": 0,
+         "forks_url": "https://api.github.com/repos/srvaroa/test/forks",
+         "full_name": "srvaroa/test",
+         "git_commits_url": "https://api.github.com/repos/srvaroa/test/git/commits{/sha}",
+         "git_refs_url": "https://api.github.com/repos/srvaroa/test/git/refs{/sha}",
+         "git_tags_url": "https://api.github.com/repos/srvaroa/test/git/tags{/sha}",
+         "git_url": "git://github.com/srvaroa/test.git",
+         "has_downloads": true,
+         "has_issues": true,
+         "has_pages": false,
+         "has_projects": true,
+         "has_wiki": true,
+         "homepage": null,
+         "hooks_url": "https://api.github.com/repos/srvaroa/test/hooks",
+         "html_url": "https://github.com/srvaroa/test",
+         "id": 203675431,
+         "issue_comment_url": "https://api.github.com/repos/srvaroa/test/issues/comments{/number}",
+         "issue_events_url": "https://api.github.com/repos/srvaroa/test/issues/events{/number}",
+         "issues_url": "https://api.github.com/repos/srvaroa/test/issues{/number}",
+         "keys_url": "https://api.github.com/repos/srvaroa/test/keys{/key_id}",
+         "labels_url": "https://api.github.com/repos/srvaroa/test/labels{/name}",
+         "language": null,
+         "languages_url": "https://api.github.com/repos/srvaroa/test/languages",
+         "license": null,
+         "merges_url": "https://api.github.com/repos/srvaroa/test/merges",
+         "milestones_url": "https://api.github.com/repos/srvaroa/test/milestones{/number}",
+         "mirror_url": null,
+         "name": "test",
+         "node_id": "MDEwOlJlcG9zaXRvcnkyMDM2NzU0MzE=",
+         "notifications_url": "https://api.github.com/repos/srvaroa/test/notifications{?since,all,participating}",
+         "open_issues": 1,
+         "open_issues_count": 1,
+         "owner": {
+           "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+           "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+           "followers_url": "https://api.github.com/users/srvaroa/followers",
+           "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+           "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+           "gravatar_id": "",
+           "html_url": "https://github.com/srvaroa",
+           "id": 346110,
+           "login": "srvaroa",
+           "node_id": "MDQ6VXNlcjM0NjExMA==",
+           "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+           "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+           "repos_url": "https://api.github.com/users/srvaroa/repos",
+           "site_admin": false,
+           "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+           "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+           "type": "User",
+           "url": "https://api.github.com/users/srvaroa"
+         },
+         "private": true,
+         "pulls_url": "https://api.github.com/repos/srvaroa/test/pulls{/number}",
+         "pushed_at": "2019-08-22T22:08:28Z",
+         "releases_url": "https://api.github.com/repos/srvaroa/test/releases{/id}",
+         "size": 3,
+         "ssh_url": "git@github.com:srvaroa/test.git",
+         "stargazers_count": 0,
+         "stargazers_url": "https://api.github.com/repos/srvaroa/test/stargazers",
+         "statuses_url": "https://api.github.com/repos/srvaroa/test/statuses/{sha}",
+         "subscribers_url": "https://api.github.com/repos/srvaroa/test/subscribers",
+         "subscription_url": "https://api.github.com/repos/srvaroa/test/subscription",
+         "svn_url": "https://github.com/srvaroa/test",
+         "tags_url": "https://api.github.com/repos/srvaroa/test/tags",
+         "teams_url": "https://api.github.com/repos/srvaroa/test/teams",
+         "trees_url": "https://api.github.com/repos/srvaroa/test/git/trees{/sha}",
+         "updated_at": "2019-08-22T22:05:35Z",
+         "url": "https://api.github.com/repos/srvaroa/test",
+         "watchers": 0,
+         "watchers_count": 0
+       },
+       "sha": "9e70f2ce79dad397cd51cf68df06bb8e81f1dcae",
+       "user": {
+         "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+         "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+         "followers_url": "https://api.github.com/users/srvaroa/followers",
+         "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+         "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+         "gravatar_id": "",
+         "html_url": "https://github.com/srvaroa",
+         "id": 346110,
+         "login": "srvaroa",
+         "node_id": "MDQ6VXNlcjM0NjExMA==",
+         "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+         "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+         "repos_url": "https://api.github.com/users/srvaroa/repos",
+         "site_admin": false,
+         "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+         "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+         "type": "User",
+         "url": "https://api.github.com/users/srvaroa"
+       }
+     },
+     "html_url": "https://github.com/srvaroa/test/pull/1",
+     "id": 309718413,
+     "issue_url": "https://api.github.com/repos/srvaroa/test/issues/1",
+     "labels": [
+       {
+         "color": "d73a4a",
+         "default": true,
+         "id": 1512553797,
+         "name": "bug",
+         "node_id": "MDU6TGFiZWwxNTEyNTUzNzk3",
+         "url": "https://api.github.com/repos/srvaroa/test/labels/bug"
+       }
+     ],
+     "locked": false,
+     "maintainer_can_modify": false,
+     "merge_commit_sha": "21f10b93703d510906e2f36c73a93dad3d63c7cf",
+     "mergeable": null,
+     "mergeable_state": "unknown",
+     "merged": false,
+     "merged_at": null,
+     "merged_by": null,
+     "milestone": null,
+     "node_id": "MDExOlB1bGxSZXF1ZXN0MzA5NzE4NDEz",
+     "number": 1,
+     "patch_url": "https://github.com/srvaroa/test/pull/1.patch",
+     "rebaseable": null,
+     "requested_reviewers": [],
+     "requested_teams": [],
+     "review_comment_url": "https://api.github.com/repos/srvaroa/test/pulls/comments{/number}",
+     "review_comments": 0,
+     "review_comments_url": "https://api.github.com/repos/srvaroa/test/pulls/1/comments",
+     "state": "open",
+     "statuses_url": "https://api.github.com/repos/srvaroa/test/statuses/9e70f2ce79dad397cd51cf68df06bb8e81f1dcae",
+     "title": "WIP: Update README",
+     "updated_at": "2019-08-23T18:55:36Z",
+     "url": "https://api.github.com/repos/srvaroa/test/pulls/1",
+     "user": {
+       "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+       "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+       "followers_url": "https://api.github.com/users/srvaroa/followers",
+       "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+       "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+       "gravatar_id": "",
+       "html_url": "https://github.com/srvaroa",
+       "id": 346110,
+       "login": "srvaroa",
+       "node_id": "MDQ6VXNlcjM0NjExMA==",
+       "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+       "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+       "repos_url": "https://api.github.com/users/srvaroa/repos",
+       "site_admin": false,
+       "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+       "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+       "type": "User",
+       "url": "https://api.github.com/users/srvaroa"
+     }
+   },
+   "repository": {
+     "archive_url": "https://api.github.com/repos/srvaroa/test/{archive_format}{/ref}",
+     "archived": false,
+     "assignees_url": "https://api.github.com/repos/srvaroa/test/assignees{/user}",
+     "blobs_url": "https://api.github.com/repos/srvaroa/test/git/blobs{/sha}",
+     "branches_url": "https://api.github.com/repos/srvaroa/test/branches{/branch}",
+     "clone_url": "https://github.com/srvaroa/test.git",
+     "collaborators_url": "https://api.github.com/repos/srvaroa/test/collaborators{/collaborator}",
+     "comments_url": "https://api.github.com/repos/srvaroa/test/comments{/number}",
+     "commits_url": "https://api.github.com/repos/srvaroa/test/commits{/sha}",
+     "compare_url": "https://api.github.com/repos/srvaroa/test/compare/{base}...{head}",
+     "contents_url": "https://api.github.com/repos/srvaroa/test/contents/{+path}",
+     "contributors_url": "https://api.github.com/repos/srvaroa/test/contributors",
+     "created_at": "2019-08-21T22:50:07Z",
+     "default_branch": "master",
+     "deployments_url": "https://api.github.com/repos/srvaroa/test/deployments",
+     "description": null,
+     "disabled": false,
+     "downloads_url": "https://api.github.com/repos/srvaroa/test/downloads",
+     "events_url": "https://api.github.com/repos/srvaroa/test/events",
+     "fork": false,
+     "forks": 0,
+     "forks_count": 0,
+     "forks_url": "https://api.github.com/repos/srvaroa/test/forks",
+     "full_name": "srvaroa/test",
+     "git_commits_url": "https://api.github.com/repos/srvaroa/test/git/commits{/sha}",
+     "git_refs_url": "https://api.github.com/repos/srvaroa/test/git/refs{/sha}",
+     "git_tags_url": "https://api.github.com/repos/srvaroa/test/git/tags{/sha}",
+     "git_url": "git://github.com/srvaroa/test.git",
+     "has_downloads": true,
+     "has_issues": true,
+     "has_pages": false,
+     "has_projects": true,
+     "has_wiki": true,
+     "homepage": null,
+     "hooks_url": "https://api.github.com/repos/srvaroa/test/hooks",
+     "html_url": "https://github.com/srvaroa/test",
+     "id": 203675431,
+     "issue_comment_url": "https://api.github.com/repos/srvaroa/test/issues/comments{/number}",
+     "issue_events_url": "https://api.github.com/repos/srvaroa/test/issues/events{/number}",
+     "issues_url": "https://api.github.com/repos/srvaroa/test/issues{/number}",
+     "keys_url": "https://api.github.com/repos/srvaroa/test/keys{/key_id}",
+     "labels_url": "https://api.github.com/repos/srvaroa/test/labels{/name}",
+     "language": null,
+     "languages_url": "https://api.github.com/repos/srvaroa/test/languages",
+     "license": null,
+     "merges_url": "https://api.github.com/repos/srvaroa/test/merges",
+     "milestones_url": "https://api.github.com/repos/srvaroa/test/milestones{/number}",
+     "mirror_url": null,
+     "name": "test",
+     "node_id": "MDEwOlJlcG9zaXRvcnkyMDM2NzU0MzE=",
+     "notifications_url": "https://api.github.com/repos/srvaroa/test/notifications{?since,all,participating}",
+     "open_issues": 1,
+     "open_issues_count": 1,
+     "owner": {
+       "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+       "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+       "followers_url": "https://api.github.com/users/srvaroa/followers",
+       "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+       "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+       "gravatar_id": "",
+       "html_url": "https://github.com/srvaroa",
+       "id": 346110,
+       "login": "srvaroa",
+       "node_id": "MDQ6VXNlcjM0NjExMA==",
+       "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+       "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+       "repos_url": "https://api.github.com/users/srvaroa/repos",
+       "site_admin": false,
+       "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+       "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+       "type": "User",
+       "url": "https://api.github.com/users/srvaroa"
+     },
+     "private": true,
+     "pulls_url": "https://api.github.com/repos/srvaroa/test/pulls{/number}",
+     "pushed_at": "2019-08-22T22:08:28Z",
+     "releases_url": "https://api.github.com/repos/srvaroa/test/releases{/id}",
+     "size": 3,
+     "ssh_url": "git@github.com:srvaroa/test.git",
+     "stargazers_count": 0,
+     "stargazers_url": "https://api.github.com/repos/srvaroa/test/stargazers",
+     "statuses_url": "https://api.github.com/repos/srvaroa/test/statuses/{sha}",
+     "subscribers_url": "https://api.github.com/repos/srvaroa/test/subscribers",
+     "subscription_url": "https://api.github.com/repos/srvaroa/test/subscription",
+     "svn_url": "https://github.com/srvaroa/test",
+     "tags_url": "https://api.github.com/repos/srvaroa/test/tags",
+     "teams_url": "https://api.github.com/repos/srvaroa/test/teams",
+     "trees_url": "https://api.github.com/repos/srvaroa/test/git/trees{/sha}",
+     "updated_at": "2019-08-22T22:05:35Z",
+     "url": "https://api.github.com/repos/srvaroa/test",
+     "watchers": 0,
+     "watchers_count": 0
+   },
+   "sender": {
+     "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4",
+     "events_url": "https://api.github.com/users/srvaroa/events{/privacy}",
+     "followers_url": "https://api.github.com/users/srvaroa/followers",
+     "following_url": "https://api.github.com/users/srvaroa/following{/other_user}",
+     "gists_url": "https://api.github.com/users/srvaroa/gists{/gist_id}",
+     "gravatar_id": "",
+     "html_url": "https://github.com/srvaroa",
+     "id": 346110,
+     "login": "srvaroa",
+     "node_id": "MDQ6VXNlcjM0NjExMA==",
+     "organizations_url": "https://api.github.com/users/srvaroa/orgs",
+     "received_events_url": "https://api.github.com/users/srvaroa/received_events",
+     "repos_url": "https://api.github.com/users/srvaroa/repos",
+     "site_admin": false,
+     "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}",
+     "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions",
+     "type": "User",
+     "url": "https://api.github.com/users/srvaroa"
+   }
+ }