danger-l10nlint 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shellwords'
4
+ require_relative '../ext/l10nlint/l10nlint'
5
+
6
+ module Danger
7
+ # This is your plugin class. Any attributes or methods you expose here will
8
+ # be available from within your Dangerfile.
9
+ #
10
+ # To be published on the Danger plugins site, you will need to have
11
+ # the public interface documented. Danger uses [YARD](http://yardoc.org/)
12
+ # for generating documentation from your plugin source, and you can verify
13
+ # by running `danger plugins lint` or `bundle exec rake spec`.
14
+ #
15
+ # You should replace these comments with a public description of your library.
16
+ #
17
+ # @example Ensure people are well warned about merging on Mondays
18
+ #
19
+ # my_plugin.warn_on_mondays
20
+ #
21
+ # @see Kazumasa Shimomura/danger-l10nlint
22
+ # @tags monday, weekends, time, rattata
23
+ #
24
+ class DangerL10nlint < Plugin
25
+ # The path to L10nLint's execution
26
+ attr_accessor :binary_path
27
+
28
+ # The path to L10nLint's configuration file
29
+ attr_accessor :config_file
30
+
31
+ # Maximum number of issues to be reported.
32
+ attr_accessor :max_num_violations
33
+
34
+ # Provides additional logging diagnostic information.
35
+ attr_accessor :verbose
36
+
37
+ # Whether we should fail on warnings
38
+ attr_accessor :strict
39
+
40
+ # Warnings found
41
+ attr_accessor :warnings
42
+
43
+ # Errors found
44
+ attr_accessor :errors
45
+
46
+ # All issues found
47
+ attr_accessor :issues
48
+
49
+ # Lints Localizable.strings
50
+ # @return [void]
51
+ #
52
+ def lint_files(inline_mode: false, fail_on_error: false, additional_l10nlint_args: '')
53
+ raise 'l10nlint is not installed' unless l10nlint.installed?
54
+
55
+ config_file_path = config_file
56
+ if config_file_path
57
+ log "Using config file: #{config_file_path}"
58
+ else
59
+ log 'config file was not specified'
60
+ end
61
+
62
+ # Prepare l10nlint options
63
+ options = {
64
+ # Make sure we don't fail when config path has spaces
65
+ config: config_file_path ? Shellwords.escape(config_file_path) : nil,
66
+ reporter: 'json'
67
+ }
68
+
69
+ log "linting with options: #{options}"
70
+
71
+ issues = run_l10nlint(options, additional_l10nlint_args)
72
+
73
+ @issues = issues
74
+ other_issues_count = 0
75
+ unless @max_num_violations.nil? || no_comment
76
+ other_issues_count = issues.count - @max_num_violations if issues.count > @max_num_violations
77
+ issues = issues.take(@max_num_violations)
78
+ end
79
+ log "Received from L10nLint: #{issues}"
80
+
81
+ # Filter warnings and errors
82
+ @warnings = issues.select { |issue| issue['severity'] == 'warning' }
83
+ @errors = issues.select { |issue| issue['severity'] == 'error' }
84
+
85
+ if inline_mode
86
+ # Report with inline comment
87
+ send_inline_comment(warnings, strict ? :fail : :warn)
88
+ send_inline_comment(errors, (fail_on_error || strict) ? :fail : :warn)
89
+ warn other_issues_message(other_issues_count) if other_issues_count > 0
90
+ elsif warnings.count > 0 || errors.count > 0
91
+ # Report if any warning or error
92
+ message = "### L10nLint found issues\n\n".dup
93
+ message << markdown_issues(warnings, 'Warnings') unless warnings.empty?
94
+ message << markdown_issues(errors, 'Errors') unless errors.empty?
95
+ message << "\n#{other_issues_message(other_issues_count)}" if other_issues_count > 0
96
+ markdown message
97
+
98
+ # Fail danger on errors
99
+ should_fail_by_errors = fail_on_error && errors.count > 0
100
+ # Fail danger if any warnings or errors and we are strict
101
+ should_fail_by_strict = strict && (errors.count > 0 || warnings.count > 0)
102
+ if should_fail_by_errors || should_fail_by_strict
103
+ fail 'Failed due to L10nLint errors'
104
+ end
105
+ end
106
+ end
107
+
108
+ # Make L10nLint object for binary_path
109
+ #
110
+ # @return [L10nLint]
111
+ def l10nlint
112
+ L10nLint.new(binary_path)
113
+ end
114
+
115
+ def log(text)
116
+ puts text if @verbose
117
+ end
118
+
119
+ # Run l10nlint on all files and returns the issues
120
+ #
121
+ # @return [Array] l10nlint issues
122
+ def run_l10nlint(options, additional_l10nlint_args)
123
+ result = l10nlint.lint(options, additional_l10nlint_args)
124
+ if result == ''
125
+ {}
126
+ else
127
+ JSON.parse(result)
128
+ end
129
+ end
130
+
131
+ # Create a markdown table from l10nlint issues
132
+ #
133
+ # @return [String]
134
+ def markdown_issues(results, heading)
135
+ message = "#### #{heading}\n\n".dup
136
+
137
+ message << "File | Line | Reason |\n"
138
+ message << "| --- | ----- | ----- |\n"
139
+
140
+ results.each do |r|
141
+ puts r
142
+
143
+ filename = r['location']['file'].split('/').last(2).join("/")
144
+ line = r['location']['line']
145
+ reason = r['reason']
146
+ rule = r['ruleIdentifier']
147
+ # Other available properties can be found int L10nLint/…/JSONReporter.swift
148
+ message << "#{filename} | #{line} | #{reason} (#{rule})\n"
149
+ end
150
+
151
+ message
152
+ end
153
+
154
+ # Send inline comment with danger's warn or fail method
155
+ #
156
+ # @return [void]
157
+ def send_inline_comment(results, method)
158
+ dir = "#{Dir.pwd}/"
159
+ results.each do |r|
160
+ github_filename = r['location']['file'].gsub(dir, '')
161
+ message = "#{r['reason']}".dup
162
+
163
+ # extended content here
164
+ filename = r['location']['file'].split('/').last
165
+ message << "\n"
166
+ message << "`#{r['ruleIdentifier']}`"
167
+ message << " `#{filename}:#{r['location']['line']}`" # file:line for pasting into Xcode Quick Open
168
+
169
+ send(method, message, file: github_filename, line: r['line'])
170
+ end
171
+ end
172
+
173
+ def other_issues_message(issues_count)
174
+ violations = issues_count == 1 ? 'violation' : 'violations'
175
+ "L10nLint also found #{issues_count} more #{violations} with this PR."
176
+ end
177
+ end
178
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DangerL10nLint
4
+ VERSION = '0.0.5'
5
+ L10NLINT_VERSION = '0.0.5'
6
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path("spec_helper", __dir__)
4
+
5
+ module Danger
6
+ describe Danger::DangerL10nLint do
7
+ it "should be a plugin" do
8
+ expect(Danger::DangerL10nLint.new(nil)).to be_a Danger::Plugin
9
+ end
10
+
11
+ #
12
+ # You should test your custom attributes and methods here
13
+ #
14
+ describe "with Dangerfile" do
15
+ before do
16
+ @dangerfile = testing_dangerfile
17
+ @l10nlint = @dangerfile.l10nlint
18
+
19
+ # mock the PR data
20
+ # you can then use this, eg. github.pr_author, later in the spec
21
+ json = File.read("#{File.dirname(__FILE__)}/support/fixtures/github_pr.json") # example json: `curl https://api.github.com/repos/danger/danger-plugin-template/pulls/18 > github_pr.json`
22
+ allow(@l10nlint.github).to receive(:pr_json).and_return(json)
23
+ end
24
+
25
+ it 'handles l10nlint not being installed' do
26
+ allow_any_instance_of(L10nLint).to receive(:installed?).and_return(false)
27
+ expect { @l10nlint.lint_files }.to raise_error('l10nlint is not installed')
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ ROOT = Pathname.new(File.expand_path("..", __dir__))
5
+ $:.unshift("#{ROOT}lib".to_s)
6
+ $:.unshift("#{ROOT}spec".to_s)
7
+
8
+ require "bundler/setup"
9
+ require "pry"
10
+
11
+ require "rspec"
12
+ require "danger"
13
+
14
+ if `git remote -v` == ""
15
+ puts "You cannot run tests without setting a local git remote on this repo"
16
+ puts "It's a weird side-effect of Danger's internals."
17
+ exit(0)
18
+ end
19
+
20
+ # Use coloured output, it's the best.
21
+ RSpec.configure do |config|
22
+ config.filter_gems_from_backtrace "bundler"
23
+ config.color = true
24
+ config.tty = true
25
+ end
26
+
27
+ require "danger_plugin"
28
+
29
+ # These functions are a subset of https://github.com/danger/danger/blob/master/spec/spec_helper.rb
30
+ # If you are expanding these files, see if it's already been done ^.
31
+
32
+ # A silent version of the user interface,
33
+ # it comes with an extra function `.string` which will
34
+ # strip all ANSI colours from the string.
35
+
36
+ # rubocop:disable Lint/NestedMethodDefinition
37
+ def testing_ui
38
+ @output = StringIO.new
39
+ def @output.winsize
40
+ [20, 9999]
41
+ end
42
+
43
+ cork = Cork::Board.new(out: @output)
44
+ def cork.string
45
+ out.string.gsub(/\e\[([;\d]+)?m/, "")
46
+ end
47
+ cork
48
+ end
49
+ # rubocop:enable Lint/NestedMethodDefinition
50
+
51
+ # Example environment (ENV) that would come from
52
+ # running a PR on TravisCI
53
+ def testing_env
54
+ {
55
+ "HAS_JOSH_K_SEAL_OF_APPROVAL" => "true",
56
+ "TRAVIS_PULL_REQUEST" => "800",
57
+ "TRAVIS_REPO_SLUG" => "artsy/eigen",
58
+ "TRAVIS_COMMIT_RANGE" => "759adcbd0d8f...13c4dc8bb61d",
59
+ "DANGER_GITHUB_API_TOKEN" => "123sbdq54erfsd3422gdfio"
60
+ }
61
+ end
62
+
63
+ # A stubbed out Dangerfile for use in tests
64
+ def testing_dangerfile
65
+ env = Danger::EnvironmentManager.new(testing_env)
66
+ Danger::Dangerfile.new(env, testing_ui)
67
+ end
@@ -0,0 +1,278 @@
1
+ {
2
+ "url": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18",
3
+ "id": 185317229,
4
+ "node_id": "MDExOlB1bGxSZXF1ZXN0MTg1MzE3MjI5",
5
+ "html_url": "https://github.com/danger/danger-plugin-template/pull/18",
6
+ "diff_url": "https://github.com/danger/danger-plugin-template/pull/18.diff",
7
+ "patch_url": "https://github.com/danger/danger-plugin-template/pull/18.patch",
8
+ "issue_url": "https://api.github.com/repos/danger/danger-plugin-template/issues/18",
9
+ "number": 18,
10
+ "state": "closed",
11
+ "locked": false,
12
+ "title": "add exmaple of how to mock PRs",
13
+ "user": {
14
+ "login": "wilrnh",
15
+ "id": 555966,
16
+ "node_id": "MDQ6VXNlcjU1NTk2Ng==",
17
+ "avatar_url": "https://avatars.githubusercontent.com/u/555966?v=4",
18
+ "gravatar_id": "",
19
+ "url": "https://api.github.com/users/wilrnh",
20
+ "html_url": "https://github.com/wilrnh",
21
+ "followers_url": "https://api.github.com/users/wilrnh/followers",
22
+ "following_url": "https://api.github.com/users/wilrnh/following{/other_user}",
23
+ "gists_url": "https://api.github.com/users/wilrnh/gists{/gist_id}",
24
+ "starred_url": "https://api.github.com/users/wilrnh/starred{/owner}{/repo}",
25
+ "subscriptions_url": "https://api.github.com/users/wilrnh/subscriptions",
26
+ "organizations_url": "https://api.github.com/users/wilrnh/orgs",
27
+ "repos_url": "https://api.github.com/users/wilrnh/repos",
28
+ "events_url": "https://api.github.com/users/wilrnh/events{/privacy}",
29
+ "received_events_url": "https://api.github.com/users/wilrnh/received_events",
30
+ "type": "User",
31
+ "site_admin": false
32
+ },
33
+ "body": "Fixes danger/danger#661\r\n\r\nadd example how to mock PRs",
34
+ "created_at": "2018-05-02T01:52:26Z",
35
+ "updated_at": "2018-05-02T10:37:04Z",
36
+ "closed_at": "2018-05-02T10:37:04Z",
37
+ "merged_at": "2018-05-02T10:37:04Z",
38
+ "merge_commit_sha": "39eacac22d52a2b70fc49bd8aba19eb7d2864717",
39
+ "assignee": null,
40
+ "assignees": [
41
+
42
+ ],
43
+ "requested_reviewers": [
44
+
45
+ ],
46
+ "requested_teams": [
47
+
48
+ ],
49
+ "labels": [
50
+
51
+ ],
52
+ "milestone": null,
53
+ "draft": false,
54
+ "commits_url": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18/commits",
55
+ "review_comments_url": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18/comments",
56
+ "review_comment_url": "https://api.github.com/repos/danger/danger-plugin-template/pulls/comments{/number}",
57
+ "comments_url": "https://api.github.com/repos/danger/danger-plugin-template/issues/18/comments",
58
+ "statuses_url": "https://api.github.com/repos/danger/danger-plugin-template/statuses/abe89bee0cdc5f45b1dee62c60e74c70f3fcb5d5",
59
+ "head": {
60
+ "label": "wilrnh:661-mocking-prs",
61
+ "ref": "661-mocking-prs",
62
+ "sha": "abe89bee0cdc5f45b1dee62c60e74c70f3fcb5d5",
63
+ "user": {
64
+ "login": "wilrnh",
65
+ "id": 555966,
66
+ "node_id": "MDQ6VXNlcjU1NTk2Ng==",
67
+ "avatar_url": "https://avatars.githubusercontent.com/u/555966?v=4",
68
+ "gravatar_id": "",
69
+ "url": "https://api.github.com/users/wilrnh",
70
+ "html_url": "https://github.com/wilrnh",
71
+ "followers_url": "https://api.github.com/users/wilrnh/followers",
72
+ "following_url": "https://api.github.com/users/wilrnh/following{/other_user}",
73
+ "gists_url": "https://api.github.com/users/wilrnh/gists{/gist_id}",
74
+ "starred_url": "https://api.github.com/users/wilrnh/starred{/owner}{/repo}",
75
+ "subscriptions_url": "https://api.github.com/users/wilrnh/subscriptions",
76
+ "organizations_url": "https://api.github.com/users/wilrnh/orgs",
77
+ "repos_url": "https://api.github.com/users/wilrnh/repos",
78
+ "events_url": "https://api.github.com/users/wilrnh/events{/privacy}",
79
+ "received_events_url": "https://api.github.com/users/wilrnh/received_events",
80
+ "type": "User",
81
+ "site_admin": false
82
+ },
83
+ "repo": null
84
+ },
85
+ "base": {
86
+ "label": "danger:master",
87
+ "ref": "master",
88
+ "sha": "30bd69c1c09d927abde0695fcb39dd70d4cc0f81",
89
+ "user": {
90
+ "login": "danger",
91
+ "id": 17147106,
92
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjE3MTQ3MTA2",
93
+ "avatar_url": "https://avatars.githubusercontent.com/u/17147106?v=4",
94
+ "gravatar_id": "",
95
+ "url": "https://api.github.com/users/danger",
96
+ "html_url": "https://github.com/danger",
97
+ "followers_url": "https://api.github.com/users/danger/followers",
98
+ "following_url": "https://api.github.com/users/danger/following{/other_user}",
99
+ "gists_url": "https://api.github.com/users/danger/gists{/gist_id}",
100
+ "starred_url": "https://api.github.com/users/danger/starred{/owner}{/repo}",
101
+ "subscriptions_url": "https://api.github.com/users/danger/subscriptions",
102
+ "organizations_url": "https://api.github.com/users/danger/orgs",
103
+ "repos_url": "https://api.github.com/users/danger/repos",
104
+ "events_url": "https://api.github.com/users/danger/events{/privacy}",
105
+ "received_events_url": "https://api.github.com/users/danger/received_events",
106
+ "type": "Organization",
107
+ "site_admin": false
108
+ },
109
+ "repo": {
110
+ "id": 60424063,
111
+ "node_id": "MDEwOlJlcG9zaXRvcnk2MDQyNDA2Mw==",
112
+ "name": "danger-plugin-template",
113
+ "full_name": "danger/danger-plugin-template",
114
+ "private": false,
115
+ "owner": {
116
+ "login": "danger",
117
+ "id": 17147106,
118
+ "node_id": "MDEyOk9yZ2FuaXphdGlvbjE3MTQ3MTA2",
119
+ "avatar_url": "https://avatars.githubusercontent.com/u/17147106?v=4",
120
+ "gravatar_id": "",
121
+ "url": "https://api.github.com/users/danger",
122
+ "html_url": "https://github.com/danger",
123
+ "followers_url": "https://api.github.com/users/danger/followers",
124
+ "following_url": "https://api.github.com/users/danger/following{/other_user}",
125
+ "gists_url": "https://api.github.com/users/danger/gists{/gist_id}",
126
+ "starred_url": "https://api.github.com/users/danger/starred{/owner}{/repo}",
127
+ "subscriptions_url": "https://api.github.com/users/danger/subscriptions",
128
+ "organizations_url": "https://api.github.com/users/danger/orgs",
129
+ "repos_url": "https://api.github.com/users/danger/repos",
130
+ "events_url": "https://api.github.com/users/danger/events{/privacy}",
131
+ "received_events_url": "https://api.github.com/users/danger/received_events",
132
+ "type": "Organization",
133
+ "site_admin": false
134
+ },
135
+ "html_url": "https://github.com/danger/danger-plugin-template",
136
+ "description": "An opinionated template for creating a Danger plugin",
137
+ "fork": false,
138
+ "url": "https://api.github.com/repos/danger/danger-plugin-template",
139
+ "forks_url": "https://api.github.com/repos/danger/danger-plugin-template/forks",
140
+ "keys_url": "https://api.github.com/repos/danger/danger-plugin-template/keys{/key_id}",
141
+ "collaborators_url": "https://api.github.com/repos/danger/danger-plugin-template/collaborators{/collaborator}",
142
+ "teams_url": "https://api.github.com/repos/danger/danger-plugin-template/teams",
143
+ "hooks_url": "https://api.github.com/repos/danger/danger-plugin-template/hooks",
144
+ "issue_events_url": "https://api.github.com/repos/danger/danger-plugin-template/issues/events{/number}",
145
+ "events_url": "https://api.github.com/repos/danger/danger-plugin-template/events",
146
+ "assignees_url": "https://api.github.com/repos/danger/danger-plugin-template/assignees{/user}",
147
+ "branches_url": "https://api.github.com/repos/danger/danger-plugin-template/branches{/branch}",
148
+ "tags_url": "https://api.github.com/repos/danger/danger-plugin-template/tags",
149
+ "blobs_url": "https://api.github.com/repos/danger/danger-plugin-template/git/blobs{/sha}",
150
+ "git_tags_url": "https://api.github.com/repos/danger/danger-plugin-template/git/tags{/sha}",
151
+ "git_refs_url": "https://api.github.com/repos/danger/danger-plugin-template/git/refs{/sha}",
152
+ "trees_url": "https://api.github.com/repos/danger/danger-plugin-template/git/trees{/sha}",
153
+ "statuses_url": "https://api.github.com/repos/danger/danger-plugin-template/statuses/{sha}",
154
+ "languages_url": "https://api.github.com/repos/danger/danger-plugin-template/languages",
155
+ "stargazers_url": "https://api.github.com/repos/danger/danger-plugin-template/stargazers",
156
+ "contributors_url": "https://api.github.com/repos/danger/danger-plugin-template/contributors",
157
+ "subscribers_url": "https://api.github.com/repos/danger/danger-plugin-template/subscribers",
158
+ "subscription_url": "https://api.github.com/repos/danger/danger-plugin-template/subscription",
159
+ "commits_url": "https://api.github.com/repos/danger/danger-plugin-template/commits{/sha}",
160
+ "git_commits_url": "https://api.github.com/repos/danger/danger-plugin-template/git/commits{/sha}",
161
+ "comments_url": "https://api.github.com/repos/danger/danger-plugin-template/comments{/number}",
162
+ "issue_comment_url": "https://api.github.com/repos/danger/danger-plugin-template/issues/comments{/number}",
163
+ "contents_url": "https://api.github.com/repos/danger/danger-plugin-template/contents/{+path}",
164
+ "compare_url": "https://api.github.com/repos/danger/danger-plugin-template/compare/{base}...{head}",
165
+ "merges_url": "https://api.github.com/repos/danger/danger-plugin-template/merges",
166
+ "archive_url": "https://api.github.com/repos/danger/danger-plugin-template/{archive_format}{/ref}",
167
+ "downloads_url": "https://api.github.com/repos/danger/danger-plugin-template/downloads",
168
+ "issues_url": "https://api.github.com/repos/danger/danger-plugin-template/issues{/number}",
169
+ "pulls_url": "https://api.github.com/repos/danger/danger-plugin-template/pulls{/number}",
170
+ "milestones_url": "https://api.github.com/repos/danger/danger-plugin-template/milestones{/number}",
171
+ "notifications_url": "https://api.github.com/repos/danger/danger-plugin-template/notifications{?since,all,participating}",
172
+ "labels_url": "https://api.github.com/repos/danger/danger-plugin-template/labels{/name}",
173
+ "releases_url": "https://api.github.com/repos/danger/danger-plugin-template/releases{/id}",
174
+ "deployments_url": "https://api.github.com/repos/danger/danger-plugin-template/deployments",
175
+ "created_at": "2016-06-04T18:17:02Z",
176
+ "updated_at": "2021-10-27T08:26:48Z",
177
+ "pushed_at": "2022-09-04T13:16:52Z",
178
+ "git_url": "git://github.com/danger/danger-plugin-template.git",
179
+ "ssh_url": "git@github.com:danger/danger-plugin-template.git",
180
+ "clone_url": "https://github.com/danger/danger-plugin-template.git",
181
+ "svn_url": "https://github.com/danger/danger-plugin-template",
182
+ "homepage": null,
183
+ "size": 42,
184
+ "stargazers_count": 19,
185
+ "watchers_count": 19,
186
+ "language": "Ruby",
187
+ "has_issues": true,
188
+ "has_projects": true,
189
+ "has_downloads": true,
190
+ "has_wiki": true,
191
+ "has_pages": false,
192
+ "has_discussions": false,
193
+ "forks_count": 13,
194
+ "mirror_url": null,
195
+ "archived": false,
196
+ "disabled": false,
197
+ "open_issues_count": 2,
198
+ "license": {
199
+ "key": "other",
200
+ "name": "Other",
201
+ "spdx_id": "NOASSERTION",
202
+ "url": null,
203
+ "node_id": "MDc6TGljZW5zZTA="
204
+ },
205
+ "allow_forking": true,
206
+ "is_template": false,
207
+ "web_commit_signoff_required": false,
208
+ "topics": [
209
+
210
+ ],
211
+ "visibility": "public",
212
+ "forks": 13,
213
+ "open_issues": 2,
214
+ "watchers": 19,
215
+ "default_branch": "master"
216
+ }
217
+ },
218
+ "_links": {
219
+ "self": {
220
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18"
221
+ },
222
+ "html": {
223
+ "href": "https://github.com/danger/danger-plugin-template/pull/18"
224
+ },
225
+ "issue": {
226
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/issues/18"
227
+ },
228
+ "comments": {
229
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/issues/18/comments"
230
+ },
231
+ "review_comments": {
232
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18/comments"
233
+ },
234
+ "review_comment": {
235
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/pulls/comments{/number}"
236
+ },
237
+ "commits": {
238
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/pulls/18/commits"
239
+ },
240
+ "statuses": {
241
+ "href": "https://api.github.com/repos/danger/danger-plugin-template/statuses/abe89bee0cdc5f45b1dee62c60e74c70f3fcb5d5"
242
+ }
243
+ },
244
+ "author_association": "CONTRIBUTOR",
245
+ "auto_merge": null,
246
+ "active_lock_reason": null,
247
+ "merged": true,
248
+ "mergeable": null,
249
+ "rebaseable": null,
250
+ "mergeable_state": "unknown",
251
+ "merged_by": {
252
+ "login": "orta",
253
+ "id": 49038,
254
+ "node_id": "MDQ6VXNlcjQ5MDM4",
255
+ "avatar_url": "https://avatars.githubusercontent.com/u/49038?v=4",
256
+ "gravatar_id": "",
257
+ "url": "https://api.github.com/users/orta",
258
+ "html_url": "https://github.com/orta",
259
+ "followers_url": "https://api.github.com/users/orta/followers",
260
+ "following_url": "https://api.github.com/users/orta/following{/other_user}",
261
+ "gists_url": "https://api.github.com/users/orta/gists{/gist_id}",
262
+ "starred_url": "https://api.github.com/users/orta/starred{/owner}{/repo}",
263
+ "subscriptions_url": "https://api.github.com/users/orta/subscriptions",
264
+ "organizations_url": "https://api.github.com/users/orta/orgs",
265
+ "repos_url": "https://api.github.com/users/orta/repos",
266
+ "events_url": "https://api.github.com/users/orta/events{/privacy}",
267
+ "received_events_url": "https://api.github.com/users/orta/received_events",
268
+ "type": "User",
269
+ "site_admin": false
270
+ },
271
+ "comments": 2,
272
+ "review_comments": 0,
273
+ "maintainer_can_modify": false,
274
+ "commits": 2,
275
+ "additions": 5,
276
+ "deletions": 0,
277
+ "changed_files": 1
278
+ }