From 9fd2561ab6b63a1979de113a567a5de405b7f7d2 Mon Sep 17 00:00:00 2001 From: Galo Navarro Date: Mon, 20 Feb 2023 19:02:11 +0100 Subject: [PATCH] New rule to match on whether author can merge Allow matching on whether the author of a PR can merge it. For now, implementing it using the author_association field in the PR. Which gives a value among these [1](https://docs.github.com/en/graphql/reference/enums#commentauthorassociation). Not sure if it's the best way of achieving it, but let's see. Signed-off-by: Galo Navarro --- README.md | 18 +- cmd/action_test.go | 4 + pkg/condition_author_can_merge.go | 25 ++ pkg/labeler.go | 38 ++- pkg/labeler_test.go | 32 ++ test_data/config_v1.yml | 6 +- test_data/create_pr_non_owner_payload | 454 ++++++++++++++++++++++++++ 7 files changed, 553 insertions(+), 24 deletions(-) create mode 100644 pkg/condition_author_can_merge.go create mode 100644 test_data/create_pr_non_owner_payload diff --git a/README.md b/README.md index fc9c626..fc2243d 100644 --- a/README.md +++ b/README.md @@ -284,13 +284,13 @@ state](https://developer.github.com/v3/pulls/#response-1) matches that of the PR. ```yaml -draft: true +draft: True ``` Matches if the PR is a draft. ```yaml -draft: false +draft: False ``` Matches if the PR is not a draft. @@ -302,13 +302,13 @@ state](https://developer.github.com/v3/pulls/#response-1) matches that of the PR. ```yaml -mergeable: true +mergeable: True ``` Will match if the label is mergeable. ```yaml -mergeable: false +mergeable: False ``` Will match if the label is not mergeable. @@ -322,6 +322,16 @@ any of the given usernames. authors: ["serubin"] ``` +### Author can merge (PRs) + +This condition is satisfied when the author of the PR can merge it. +This is implemented by checking if the author is an owner of the repo. + +```yaml +author-can-merge: True +``` + + ### Size (PRs only) This condition is satisfied when the total number of changed lines in diff --git a/cmd/action_test.go b/cmd/action_test.go index d9f33d9..a742914 100644 --- a/cmd/action_test.go +++ b/cmd/action_test.go @@ -140,6 +140,10 @@ func TestGetLabelerConfigV1(t *testing.T) { Label: "TestMergeable", Mergeable: "True", }, + { + Label: "TestAuthorCanMerge", + AuthorCanMerge: "True", + }, }, } diff --git a/pkg/condition_author_can_merge.go b/pkg/condition_author_can_merge.go new file mode 100644 index 0000000..995cee5 --- /dev/null +++ b/pkg/condition_author_can_merge.go @@ -0,0 +1,25 @@ +package labeler + +import ( + "fmt" +) + +func AuthorCanMergeCondition() Condition { + return Condition{ + GetName: func() string { + return "Author can merge" + }, + CanEvaluate: func(target *Target) bool { + return true + }, + Evaluate: func(target *Target, matcher LabelMatcher) (bool, error) { + if len(matcher.AuthorCanMerge) <= 0 { + return false, fmt.Errorf("AuthorCanMerge not set in repository") + } + ghRepo := target.ghPR.GetAuthorAssociation() + canMerge := ghRepo == "OWNER" + fmt.Printf("User: %s can merge? %t\n", target.Author, canMerge) + return canMerge, nil + }, + } +} diff --git a/pkg/labeler.go b/pkg/labeler.go index 0adcad9..caddc19 100644 --- a/pkg/labeler.go +++ b/pkg/labeler.go @@ -9,18 +9,19 @@ import ( ) type LabelMatcher struct { - Label string - Negate bool - Title string - Branch string - BaseBranch string `yaml:"base-branch"` - Body string - Files []string - Authors []string - Mergeable string - Draft string - SizeBelow string `yaml:"size-below"` - SizeAbove string `yaml:"size-above"` + AuthorCanMerge string `yaml:"author-can-merge"` + Authors []string + BaseBranch string `yaml:"base-branch"` + Body string + Branch string + Draft string + Files []string + Label string + Mergeable string + Negate bool + SizeAbove string `yaml:"size-above"` + SizeBelow string `yaml:"size-below"` + Title string } type LabelerConfigV0 map[string]LabelMatcher @@ -183,15 +184,16 @@ func (l *Labeler) findMatches(target *Target, config *LabelerConfigV1) (LabelUpd set: map[string]bool{}, } conditions := []Condition{ - TitleCondition(), - BranchCondition(), + AuthorCondition(), + AuthorCanMergeCondition(), BaseBranchCondition(), - IsMergeableCondition(), - IsDraftCondition(), - SizeCondition(), BodyCondition(), + BranchCondition(), FilesCondition(l), - AuthorCondition(), + IsDraftCondition(), + IsMergeableCondition(), + SizeCondition(), + TitleCondition(), } for _, matcher := range config.Labels { diff --git a/pkg/labeler_test.go b/pkg/labeler_test.go index affea20..9ded733 100644 --- a/pkg/labeler_test.go +++ b/pkg/labeler_test.go @@ -499,6 +499,38 @@ func TestHandleEvent(t *testing.T) { // BUT because AppendOnly is set, we do not erase it expectedLabels: []string{"Fix"}, }, + { + event: "pull_request", + payloads: []string{"create_pr", "reopen_pr"}, + name: "Add a label when the author can merge", + config: LabelerConfigV1{ + Version: 1, + Labels: []LabelMatcher{ + { + Label: "Test", + AuthorCanMerge: "True", + }, + }, + }, + initialLabels: []string{}, + expectedLabels: []string{"Test"}, + }, + { + event: "pull_request", + payloads: []string{"create_pr_non_owner"}, + name: "Add a label when the author cannot merge", + config: LabelerConfigV1{ + Version: 1, + Labels: []LabelMatcher{ + { + Label: "Test", + AuthorCanMerge: "True", + }, + }, + }, + initialLabels: []string{"Test"}, + expectedLabels: []string{}, + }, // Issues diff --git a/test_data/config_v1.yml b/test_data/config_v1.yml index 1c4599b..c7a0743 100644 --- a/test_data/config_v1.yml +++ b/test_data/config_v1.yml @@ -22,6 +22,8 @@ labels: - "Test1" - "Test2" - label: "TestDraft" - draft: "True" + draft: True - label: "TestMergeable" - mergeable: "True" + mergeable: True + - label: "TestAuthorCanMerge" + author-can-merge: True diff --git a/test_data/create_pr_non_owner_payload b/test_data/create_pr_non_owner_payload new file mode 100644 index 0000000..3201f86 --- /dev/null +++ b/test_data/create_pr_non_owner_payload @@ -0,0 +1,454 @@ +{ + "action": "opened", + "number": 2, + "pull_request": { + "url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2", + "id": 288571928, + "node_id": "MDExOlB1bGxSZXF1ZXN0Mjg4NTcxOTI4", + "html_url": "https://github.com/srvaroa/jsonrouter/pull/2", + "diff_url": "https://github.com/srvaroa/jsonrouter/pull/2.diff", + "patch_url": "https://github.com/srvaroa/jsonrouter/pull/2.patch", + "issue_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/2", + "number": 2, + "state": "open", + "locked": false, + "title": "WIP: this is a test", + "user": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "body": "Signed-off-by: Galo Navarro ", + "created_at": "2019-06-15T17:52:33Z", + "updated_at": "2019-06-15T17:52:33Z", + "closed_at": null, + "merged_at": null, + "merge_commit_sha": null, + "assignee": null, + "assignees": [ + + ], + "requested_reviewers": [ + + ], + "requested_teams": [ + + ], + "labels": [ + + ], + "milestone": null, + "commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2/commits", + "review_comments_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2/comments", + "review_comment_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/2/comments", + "statuses_url": "https://api.github.com/repos/srvaroa/jsonrouter/statuses/77b472948e9aa504c1b584c3073318b3aa58bc0b", + "head": { + "label": "srvaroa:m", + "ref": "m", + "sha": "77b472948e9aa504c1b584c3073318b3aa58bc0b", + "user": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 190467543, + "node_id": "MDEwOlJlcG9zaXRvcnkxOTA0Njc1NDM=", + "name": "jsonrouter", + "full_name": "srvaroa/jsonrouter", + "private": false, + "owner": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/srvaroa/jsonrouter", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/srvaroa/jsonrouter", + "forks_url": "https://api.github.com/repos/srvaroa/jsonrouter/forks", + "keys_url": "https://api.github.com/repos/srvaroa/jsonrouter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/srvaroa/jsonrouter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/srvaroa/jsonrouter/teams", + "hooks_url": "https://api.github.com/repos/srvaroa/jsonrouter/hooks", + "issue_events_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/events{/number}", + "events_url": "https://api.github.com/repos/srvaroa/jsonrouter/events", + "assignees_url": "https://api.github.com/repos/srvaroa/jsonrouter/assignees{/user}", + "branches_url": "https://api.github.com/repos/srvaroa/jsonrouter/branches{/branch}", + "tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/tags", + "blobs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/srvaroa/jsonrouter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/srvaroa/jsonrouter/languages", + "stargazers_url": "https://api.github.com/repos/srvaroa/jsonrouter/stargazers", + "contributors_url": "https://api.github.com/repos/srvaroa/jsonrouter/contributors", + "subscribers_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscribers", + "subscription_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscription", + "commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/srvaroa/jsonrouter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/srvaroa/jsonrouter/contents/{+path}", + "compare_url": "https://api.github.com/repos/srvaroa/jsonrouter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/srvaroa/jsonrouter/merges", + "archive_url": "https://api.github.com/repos/srvaroa/jsonrouter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/srvaroa/jsonrouter/downloads", + "issues_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues{/number}", + "pulls_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/srvaroa/jsonrouter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/srvaroa/jsonrouter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/srvaroa/jsonrouter/labels{/name}", + "releases_url": "https://api.github.com/repos/srvaroa/jsonrouter/releases{/id}", + "deployments_url": "https://api.github.com/repos/srvaroa/jsonrouter/deployments", + "created_at": "2019-06-05T20:57:56Z", + "updated_at": "2019-06-15T17:48:32Z", + "pushed_at": "2019-06-15T17:52:28Z", + "git_url": "git://github.com/srvaroa/jsonrouter.git", + "ssh_url": "git@github.com:srvaroa/jsonrouter.git", + "clone_url": "https://github.com/srvaroa/jsonrouter.git", + "svn_url": "https://github.com/srvaroa/jsonrouter", + "homepage": null, + "size": 4, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Go", + "has_issues": false, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": null, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "base": { + "label": "srvaroa:master", + "ref": "master", + "sha": "54806dc574efef6487d8ac7dd26e96712f1781e5", + "user": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "repo": { + "id": 190467543, + "node_id": "MDEwOlJlcG9zaXRvcnkxOTA0Njc1NDM=", + "name": "jsonrouter", + "full_name": "srvaroa/jsonrouter", + "private": false, + "owner": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/srvaroa/jsonrouter", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/srvaroa/jsonrouter", + "forks_url": "https://api.github.com/repos/srvaroa/jsonrouter/forks", + "keys_url": "https://api.github.com/repos/srvaroa/jsonrouter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/srvaroa/jsonrouter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/srvaroa/jsonrouter/teams", + "hooks_url": "https://api.github.com/repos/srvaroa/jsonrouter/hooks", + "issue_events_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/events{/number}", + "events_url": "https://api.github.com/repos/srvaroa/jsonrouter/events", + "assignees_url": "https://api.github.com/repos/srvaroa/jsonrouter/assignees{/user}", + "branches_url": "https://api.github.com/repos/srvaroa/jsonrouter/branches{/branch}", + "tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/tags", + "blobs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/srvaroa/jsonrouter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/srvaroa/jsonrouter/languages", + "stargazers_url": "https://api.github.com/repos/srvaroa/jsonrouter/stargazers", + "contributors_url": "https://api.github.com/repos/srvaroa/jsonrouter/contributors", + "subscribers_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscribers", + "subscription_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscription", + "commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/srvaroa/jsonrouter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/srvaroa/jsonrouter/contents/{+path}", + "compare_url": "https://api.github.com/repos/srvaroa/jsonrouter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/srvaroa/jsonrouter/merges", + "archive_url": "https://api.github.com/repos/srvaroa/jsonrouter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/srvaroa/jsonrouter/downloads", + "issues_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues{/number}", + "pulls_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/srvaroa/jsonrouter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/srvaroa/jsonrouter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/srvaroa/jsonrouter/labels{/name}", + "releases_url": "https://api.github.com/repos/srvaroa/jsonrouter/releases{/id}", + "deployments_url": "https://api.github.com/repos/srvaroa/jsonrouter/deployments", + "created_at": "2019-06-05T20:57:56Z", + "updated_at": "2019-06-15T17:48:32Z", + "pushed_at": "2019-06-15T17:52:28Z", + "git_url": "git://github.com/srvaroa/jsonrouter.git", + "ssh_url": "git@github.com:srvaroa/jsonrouter.git", + "clone_url": "https://github.com/srvaroa/jsonrouter.git", + "svn_url": "https://github.com/srvaroa/jsonrouter", + "homepage": null, + "size": 4, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Go", + "has_issues": false, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": null, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2" + }, + "html": { + "href": "https://github.com/srvaroa/jsonrouter/pull/2" + }, + "issue": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/issues/2" + }, + "comments": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/issues/2/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/pulls/2/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/srvaroa/jsonrouter/statuses/77b472948e9aa504c1b584c3073318b3aa58bc0b" + } + }, + "author_association": "CONTRIBUTOR", + "draft": false, + "merged": false, + "mergeable": null, + "rebaseable": null, + "mergeable_state": "unknown", + "merged_by": null, + "comments": 0, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 1, + "additions": 0, + "deletions": 0, + "changed_files": 0 + }, + "repository": { + "id": 190467543, + "node_id": "MDEwOlJlcG9zaXRvcnkxOTA0Njc1NDM=", + "name": "jsonrouter", + "full_name": "srvaroa/jsonrouter", + "private": false, + "owner": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/srvaroa/jsonrouter", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/srvaroa/jsonrouter", + "forks_url": "https://api.github.com/repos/srvaroa/jsonrouter/forks", + "keys_url": "https://api.github.com/repos/srvaroa/jsonrouter/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/srvaroa/jsonrouter/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/srvaroa/jsonrouter/teams", + "hooks_url": "https://api.github.com/repos/srvaroa/jsonrouter/hooks", + "issue_events_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/events{/number}", + "events_url": "https://api.github.com/repos/srvaroa/jsonrouter/events", + "assignees_url": "https://api.github.com/repos/srvaroa/jsonrouter/assignees{/user}", + "branches_url": "https://api.github.com/repos/srvaroa/jsonrouter/branches{/branch}", + "tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/tags", + "blobs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/srvaroa/jsonrouter/statuses/{sha}", + "languages_url": "https://api.github.com/repos/srvaroa/jsonrouter/languages", + "stargazers_url": "https://api.github.com/repos/srvaroa/jsonrouter/stargazers", + "contributors_url": "https://api.github.com/repos/srvaroa/jsonrouter/contributors", + "subscribers_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscribers", + "subscription_url": "https://api.github.com/repos/srvaroa/jsonrouter/subscription", + "commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/srvaroa/jsonrouter/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/srvaroa/jsonrouter/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/srvaroa/jsonrouter/contents/{+path}", + "compare_url": "https://api.github.com/repos/srvaroa/jsonrouter/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/srvaroa/jsonrouter/merges", + "archive_url": "https://api.github.com/repos/srvaroa/jsonrouter/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/srvaroa/jsonrouter/downloads", + "issues_url": "https://api.github.com/repos/srvaroa/jsonrouter/issues{/number}", + "pulls_url": "https://api.github.com/repos/srvaroa/jsonrouter/pulls{/number}", + "milestones_url": "https://api.github.com/repos/srvaroa/jsonrouter/milestones{/number}", + "notifications_url": "https://api.github.com/repos/srvaroa/jsonrouter/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/srvaroa/jsonrouter/labels{/name}", + "releases_url": "https://api.github.com/repos/srvaroa/jsonrouter/releases{/id}", + "deployments_url": "https://api.github.com/repos/srvaroa/jsonrouter/deployments", + "created_at": "2019-06-05T20:57:56Z", + "updated_at": "2019-06-15T17:48:32Z", + "pushed_at": "2019-06-15T17:52:28Z", + "git_url": "git://github.com/srvaroa/jsonrouter.git", + "ssh_url": "git@github.com:srvaroa/jsonrouter.git", + "clone_url": "https://github.com/srvaroa/jsonrouter.git", + "svn_url": "https://github.com/srvaroa/jsonrouter", + "homepage": null, + "size": 4, + "stargazers_count": 0, + "watchers_count": 0, + "language": "Go", + "has_issues": false, + "has_projects": false, + "has_downloads": true, + "has_wiki": false, + "has_pages": false, + "forks_count": 0, + "mirror_url": null, + "archived": false, + "disabled": false, + "open_issues_count": 1, + "license": null, + "forks": 0, + "open_issues": 1, + "watchers": 0, + "default_branch": "master" + }, + "sender": { + "login": "srvaroa", + "id": 346110, + "node_id": "MDQ6VXNlcjM0NjExMA==", + "avatar_url": "https://avatars2.githubusercontent.com/u/346110?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/srvaroa", + "html_url": "https://github.com/srvaroa", + "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}", + "starred_url": "https://api.github.com/users/srvaroa/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/srvaroa/subscriptions", + "organizations_url": "https://api.github.com/users/srvaroa/orgs", + "repos_url": "https://api.github.com/users/srvaroa/repos", + "events_url": "https://api.github.com/users/srvaroa/events{/privacy}", + "received_events_url": "https://api.github.com/users/srvaroa/received_events", + "type": "User", + "site_admin": false + } +}