pronto 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c46191096dc80dd16c7d74cb071776e3d527c58030b205f13ef7cdd814bc2a75
4
- data.tar.gz: c0e30815ad2b8e4cc4dc5b0e3f020347346a2e27463855951399b270b136015b
3
+ metadata.gz: 46470dd7ac5341cc9bebbf13127f62c06d5d5a19cf55578a40439265761d59b3
4
+ data.tar.gz: a6a51d6593f9c4e521c8adf4a7fca559c3342931e7b207659e620d8d3585678a
5
5
  SHA512:
6
- metadata.gz: 005ccdcd8d549c490828c473658708c273f982fca0923897444cb84d02e2757b539d1acdf2accbe87220e08a55d5d2b3168780090c996e0449416cde798eaf92
7
- data.tar.gz: 4b3b8aefc717056f27840f5ad1693f6d053e4988c4d892b281dadb55ac6dbbe9824dd97bccc609caab3d2e772e60802bb45c0021772ef64fb19883219bd4f62e
6
+ metadata.gz: e500bc433123227725e318c285995986ba6cf4a5281cbcb2be92aaac130515a788be5fabdd957d9d95e2f58fb95708bed6db193ab340c123760d8210471f4995
7
+ data.tar.gz: 1342570798515c8efdfcc17eaf383c308c8875031dd61cb4eef5821513c8e3a748b411b7112d5c210dabda11afc0831fc5767f08729dcad8d452e9c1215c60c1
@@ -0,0 +1,3 @@
1
+ # Order is important. The last matching pattern takes the most precedence.
2
+ # Default owners for everything in the repo.
3
+ * @prontolabs/core
@@ -2,6 +2,35 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.11.0
6
+
7
+ ### New features
8
+
9
+ * [#304](https://github.com/prontolabs/pronto/pull/304) add option to limit comments per PR review
10
+ * [#333](https://github.com/prontolabs/pronto/pull/333) add github_combined_status formatter
11
+ * [#334](https://github.com/prontolabs/pronto/pull/334) add configurable review_type for GitHub (with REQUEST_CHANGES as default)
12
+ * [#351](https://github.com/prontolabs/pronto/pull/351) add gitLab_mr formatter
13
+ * [#369](https://github.com/prontolabs/pronto/pull/369) make Pronto::Git::Patch#new_file_path public
14
+ * update to the BitBucket 2.0 API (_as the 1.0 API was deprecated_) via [#347](https://github.com/prontolabs/pronto/pull/347), [#348](https://github.com/prontolabs/pronto/pull/348), [#352](https://github.com/prontolabs/pronto/pull/352) and [#354](https://github.com/prontolabs/pronto/pull/354)
15
+
16
+ ### Bugs fixed
17
+
18
+ * [#344](https://github.com/prontolabs/pronto/pull/344) treat Gemfile and .gemspecs as Ruby
19
+ * [#380](https://github.com/prontolabs/pronto/pull/380) fix compatibility with rugged >= 0.99
20
+ * [#387](https://github.com/prontolabs/pronto/pull/387) fix running pronto inside git submodules
21
+
22
+ ### Changes
23
+
24
+ * [#370](https://github.com/prontolabs/pronto/pull/370) allow thor 1.x gem versions
25
+ * [#379](https://github.com/prontolabs/pronto/pull/379) allow rugged 1.0.x gem versions
26
+ * [#386](https://github.com/prontolabs/pronto/pull/386) add ruby 2.7 to CI
27
+ * [#390](https://github.com/prontolabs/pronto/pull/390) fix issue with generating Sorbet RBI
28
+ * [#396](https://github.com/prontolabs/pronto/pull/396) add support for Ruby 3.0
29
+ * document/improve GitHub Actions integration in README.md via [#360](https://github.com/prontolabs/pronto/pull/360), [#378](https://github.com/prontolabs/pronto/pull/378) and [#389](https://github.com/prontolabs/pronto/pull/389)
30
+ * add links to additional pronto runners in README.md
31
+
32
+ ## 0.10.0
33
+
5
34
  ### New features
6
35
 
7
36
  * [#301](https://github.com/prontolabs/pronto/pull/301): add ability to auto approve Bitbucket pull requests.
data/README.md CHANGED
@@ -110,18 +110,40 @@ If you want comments to appear on pull request diff, instead of commit:
110
110
  $ PRONTO_GITHUB_ACCESS_TOKEN=token pronto run -f github_pr -c origin/master
111
111
  ```
112
112
 
113
- If you want review to appear on pull request diff, instead of comments:
113
+ If you want review to appear on pull request diff, instead of separate comments:
114
114
 
115
115
  ```sh
116
116
  $ PRONTO_GITHUB_ACCESS_TOKEN=token pronto run -f github_pr_review -c origin/master
117
117
  ```
118
118
 
119
+ All the **N** pending comments will be now separated into **X** number of PR reviews.
120
+ The number of the PR reviews will be controlled by an additional environment variable or with the help of a config setting.
121
+ This way, by a single pronto run, all the comments will be published to the PR, but divided into small reviews
122
+ in order to avoid the rate limit of the providers.
123
+
124
+ ```
125
+ X = N / {PRONTO_WARNINGS_PER_REVIEW || warnings_per_review || 30})
126
+ ```
127
+
128
+ Note: In case no environment variable or config setting is specified in `.pronto.yml`,
129
+ a default value of `30` will be used.
130
+
131
+ ```sh
132
+ $ PRONTO_WARNINGS_PER_REVIEW=30 PRONTO_GITHUB_ACCESS_TOKEN=token pronto run -f github_pr_review -c origin/master
133
+ ```
134
+
119
135
  Use `GithubStatusFormatter` to submit [commit status](https://github.com/blog/1227-commit-status-api):
120
136
 
121
137
  ```sh
122
138
  $ PRONTO_GITHUB_ACCESS_TOKEN=token pronto run -f github_status -c origin/master
123
139
  ```
124
140
 
141
+ If you want to show a one single status for all runners, instead of status per runner:
142
+
143
+ ```sh
144
+ $ PRONTO_GITHUB_ACCESS_TOKEN=token pronto run -f github_combined_status -c origin/master
145
+ ```
146
+
125
147
  It's possible to combine multiple formatters.
126
148
  To get both pull request comments and commit status summary use:
127
149
 
@@ -140,6 +162,39 @@ formatters = [formatter, status_formatter]
140
162
  Pronto.run('origin/master', '.', formatters)
141
163
  ```
142
164
 
165
+ #### GitHub Actions Integration
166
+
167
+ You can also run Pronto as a GitHub action.
168
+
169
+ Here's an example `.github/workflows/pronto.yml` workflow file using the `github_status` and `github_pr` formatters and running on each GitHub PR, with `pronto-rubocop` as the runner:
170
+
171
+
172
+ ```yml
173
+ name: Pronto
174
+ on: [pull_request]
175
+
176
+ jobs:
177
+ pronto:
178
+
179
+ runs-on: ubuntu-latest
180
+
181
+ steps:
182
+ - name: Checkout code
183
+ uses: actions/checkout@v2
184
+ - run: |
185
+ git fetch --no-tags --prune --depth=10 origin +refs/heads/*:refs/remotes/origin/*
186
+ - name: Setup Ruby
187
+ uses: ruby/setup-ruby@v1
188
+ - name: Setup pronto
189
+ run: gem install pronto pronto-rubocop
190
+ - name: Run Pronto
191
+ run: pronto run -f github_status github_pr -c origin/${{ github.base_ref }}
192
+ env:
193
+ PRONTO_PULL_REQUEST_ID: ${{ github.event.pull_request.number }}
194
+ PRONTO_GITHUB_ACCESS_TOKEN: "${{ github.token }}"
195
+ ```
196
+ check Wiki on [GitHub Actions Integration](https://github.com/prontolabs/pronto/wiki/GitHub-Actions-Integration) for more info.
197
+
143
198
  ### GitLab Integration
144
199
 
145
200
  You can run Pronto as a step of your CI builds and get the results as comments
@@ -159,6 +214,29 @@ Then just run it:
159
214
  $ PRONTO_GITLAB_API_PRIVATE_TOKEN=token pronto run -f gitlab -c origin/master
160
215
  ```
161
216
 
217
+ **note: this requires at least Gitlab 11.6+**
218
+
219
+ Merge request integration:
220
+
221
+ ```sh
222
+ $ PRONTO_GITLAB_API_PRIVATE_TOKEN=token PRONTO_PULL_REQUEST_ID=id pronto run -f gitlab_mr -c origin/master
223
+ ```
224
+
225
+ On GitLabCI make make sure to run Pronto in a [merge request pipeline](https://docs.gitlab.com/ce/ci/merge_request_pipelines/):
226
+
227
+ ```yml
228
+ lint:
229
+ image: ruby
230
+ variables:
231
+ PRONTO_GITLAB_API_ENDPOINT: "https://gitlab.com/api/v4"
232
+ PRONTO_GITLAB_API_PRIVATE_TOKEN: token
233
+ only:
234
+ - merge_requests
235
+ script:
236
+ - bundle install
237
+ - bundle exec pronto run -f gitlab_mr -c origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
238
+ ```
239
+
162
240
  ### Bitbucket Integration
163
241
 
164
242
  You can run Pronto as a step of your CI builds and get the results as comments
@@ -210,6 +288,7 @@ bitbucket:
210
288
  password: pass
211
289
  web_endpoint: https://bitbucket.org/
212
290
  max_warnings: 150
291
+ warnings_per_review: 30
213
292
  verbose: false
214
293
  ```
215
294
 
@@ -260,13 +339,17 @@ The following values are available only to the text formatter:
260
339
  Pronto can run various tools and libraries, as long as there's a runner for it.
261
340
  Currently available:
262
341
 
342
+ * [pronto-bigfiles](https://github.com/apiology/pronto-bigfiles)
263
343
  * [pronto-blacklist](https://github.com/pbstriker38/pronto-blacklist)
264
344
  * [pronto-brakeman](https://github.com/prontolabs/pronto-brakeman)
345
+ * [pronto-bundler_audit](https://github.com/pdobb/pronto-bundler_audit)
346
+ * [pronto-checkstyle](https://github.com/seikichi/pronto-checkstyle)
265
347
  * [pronto-coffeelint](https://github.com/siebertm/pronto-coffeelint)
266
348
  * [pronto-clang_format](https://github.com/micjabbour/pronto-clang_format)
267
349
  * [pronto-clang_tidy](https://github.com/micjabbour/pronto-clang_tidy)
268
350
  * [pronto-clippy](https://github.com/hauleth/pronto-clippy)
269
351
  * [pronto-credo](https://github.com/carakan/pronto-credo)
352
+ * [pronto-dialyxir](https://github.com/Apelsinka223/pronto-dialyxir)
270
353
  * [pronto-dialyzer](https://github.com/iurifq/pronto-dialyzer)
271
354
  * [pronto-dirty_words](https://github.com/kevinjalbert/pronto-dirty_words)
272
355
  * [pronto-dogma](https://github.com/iurifq/pronto-dogma)
@@ -274,11 +357,15 @@ Currently available:
274
357
  * [pronto-eslint](https://github.com/prontolabs/pronto-eslint) (uses [eslintrb](https://github.com/zendesk/eslintrb))
275
358
  * [pronto-eslint_npm](https://github.com/doits/pronto-eslint_npm) (uses eslint installed from npm)
276
359
  * [pronto-fasterer](https://github.com/prontolabs/pronto-fasterer)
360
+ * [pronto-findbugs](https://github.com/seikichi/pronto-findbugs)
277
361
  * [pronto-flake8](https://github.com/scoremedia/pronto-flake8)
278
362
  * [pronto-flay](https://github.com/prontolabs/pronto-flay)
279
363
  * [pronto-flow](https://github.com/kevinjalbert/pronto-flow)
280
364
  * [pronto-foodcritic](https://github.com/prontolabs/pronto-foodcritic)
365
+ * [pronto-goodcheck](https://github.com/aergonaut/pronto-goodcheck)
281
366
  * [pronto-haml](https://github.com/prontolabs/pronto-haml)
367
+ * [pronto-hlint](https://github.com/fretlink/pronto-hlint/) (uses Haskell code suggestions [hlint](https://github.com/ndmitchell/hlint))
368
+ * [pronto-infer](https://github.com/seikichi/pronto-infer)
282
369
  * [pronto-inspec](https://github.com/stiller-leser/pronto-inspec)
283
370
  * [pronto-jscs](https://github.com/spajus/pronto-jscs)
284
371
  * [pronto-jshint](https://github.com/prontolabs/pronto-jshint)
@@ -289,7 +376,9 @@ Currently available:
289
376
  * [pronto-phpmd](https://github.com/EllisV/pronto-phpmd)
290
377
  * [pronto-phpstan](https://github.com/Powerhamster/pronto-phpstan)
291
378
  * [pronto-poper](https://github.com/prontolabs/pronto-poper)
379
+ * [pronto-punchlist](https://github.com/apiology/pronto-punchlist)
292
380
  * [pronto-rails_best_practices](https://github.com/prontolabs/pronto-rails_best_practices)
381
+ * [pronto-rails_data_schema](https://github.com/mbajur/pronto-rails_data_schema)
293
382
  * [pronto-rails_schema](https://github.com/raimondasv/pronto-rails_schema)
294
383
  * [pronto-reek](https://github.com/prontolabs/pronto-reek)
295
384
  * [pronto-rubocop](https://github.com/prontolabs/pronto-rubocop)
@@ -297,15 +386,17 @@ Currently available:
297
386
  * [pronto-shellcheck](https://github.com/pclalv/pronto-shellcheck)
298
387
  * [pronto-slim](https://github.com/nysthee/pronto-slim)
299
388
  * [pronto-slim_lint](https://github.com/ibrahima/pronto-slim_lint)
389
+ * [pronto-sorbet](https://github.com/teamsimplepay/pronto-sorbet)
300
390
  * [pronto-spell](https://github.com/prontolabs/pronto-spell)
391
+ * [pronto-standardrb](https://github.com/julianrubisch/pronto-standardrb)
301
392
  * [pronto-stylelint](https://github.com/kevinjalbert/pronto-stylelint)
302
393
  * [pronto-swiftlint](https://github.com/ajanauskas/pronto-swiftlint)
303
394
  * [pronto-tailor](https://github.com/ajanauskas/pronto-tailor)
304
395
  * [pronto-textlint](https://github.com/seikichi/pronto-textlint)
305
396
  * [pronto-tslint_npm](https://github.com/eprislac/pronto-tslint_npm)
306
397
  * [pronto-yamllint](https://github.com/pauliusm/pronto-yamllint)
307
- * [pronto-goodcheck](https://github.com/aergonaut/pronto-goodcheck)
308
398
  * [pronto-undercover](https://github.com/grodowski/pronto-undercover)
399
+ * [pronto-xmllint](https://github.com/pauliusm/pronto-xmllint)
309
400
 
310
401
  ## Articles
311
402
 
@@ -42,9 +42,11 @@ require 'pronto/formatter/commit_formatter'
42
42
  require 'pronto/formatter/pull_request_formatter'
43
43
  require 'pronto/formatter/github_formatter'
44
44
  require 'pronto/formatter/github_status_formatter'
45
+ require 'pronto/formatter/github_combined_status_formatter'
45
46
  require 'pronto/formatter/github_pull_request_formatter'
46
47
  require 'pronto/formatter/github_pull_request_review_formatter'
47
48
  require 'pronto/formatter/gitlab_formatter'
49
+ require 'pronto/formatter/gitlab_merge_request_review_formatter'
48
50
  require 'pronto/formatter/bitbucket_formatter'
49
51
  require 'pronto/formatter/bitbucket_pull_request_formatter'
50
52
  require 'pronto/formatter/bitbucket_server_pull_request_formatter'
@@ -1,28 +1,39 @@
1
1
  class BitbucketClient
2
2
  include HTTParty
3
- base_uri 'https://api.bitbucket.org/1.0/repositories'
3
+ base_uri 'https://api.bitbucket.org/2.0/repositories'
4
4
 
5
5
  def initialize(username, password)
6
6
  self.class.basic_auth(username, password)
7
7
  end
8
8
 
9
9
  def commit_comments(slug, sha)
10
- response = get("/#{slug}/changesets/#{sha}/comments")
11
- openstruct(response)
10
+ response = get("/#{slug}/commit/#{sha}/comments?pagelen=100")
11
+ result = parse_comments(openstruct(response))
12
+ while (response['next'])
13
+ response = get response['next']
14
+ result.concat(parse_comments(openstruct(response)))
15
+ end
16
+ result
12
17
  end
13
18
 
14
19
  def create_commit_comment(slug, sha, body, path, position)
15
- post("/#{slug}/changesets/#{sha}/comments", body, path, position)
20
+ post("/#{slug}/commit/#{sha}/comments", body, path, position)
16
21
  end
17
22
 
18
23
  def pull_comments(slug, pull_id)
19
- response = get("/#{slug}/pullrequests/#{pull_id}/comments")
20
- openstruct(response)
24
+ response = get("/#{slug}/pullrequests/#{pull_id}/comments?pagelen=100")
25
+ parse_comments(openstruct(response))
26
+ result = parse_comments(openstruct(response))
27
+ while (response['next'])
28
+ response = get response['next']
29
+ result.concat(parse_comments(openstruct(response)))
30
+ end
31
+ result
21
32
  end
22
33
 
23
34
  def pull_requests(slug)
24
- response = get("#{pull_request_api(slug)}/pullrequests?state=OPEN")
25
- openstruct(response['values'])
35
+ response = get("/#{slug}/pullrequests?state=OPEN")
36
+ openstruct(response)
26
37
  end
27
38
 
28
39
  def create_pull_comment(slug, pull_id, body, path, position)
@@ -30,29 +41,46 @@ class BitbucketClient
30
41
  end
31
42
 
32
43
  def approve_pull_request(slug, pull_id)
33
- self.class.post("#{pull_request_api(slug)}/pullrequests/#{pull_id}/approve")
44
+ self.class.post("/#{slug}/pullrequests/#{pull_id}/approve")
34
45
  end
35
46
 
36
47
  def unapprove_pull_request(slug, pull_id)
37
- self.class.delete("#{pull_request_api(slug)}/pullrequests/#{pull_id}/approve")
48
+ self.class.delete("/#{slug}/pullrequests/#{pull_id}/approve")
38
49
  end
39
50
 
40
51
  private
41
52
 
42
- def pull_request_api(slug)
43
- "https://api.bitbucket.org/2.0/repositories/#{slug}"
44
- end
45
-
46
53
  def openstruct(response)
47
- response.map { |r| OpenStruct.new(r) }
54
+ if response['values']
55
+ response['values'].map { |r| OpenStruct.new(r) }
56
+ else
57
+ p response
58
+ raise 'BitBucket response invalid'
59
+ end
48
60
  end
49
61
 
62
+ def parse_comments(values)
63
+ values.each do |value|
64
+ value.content = value.content['raw']
65
+ value.line_to = value.inline ? value.inline['to'] : 0
66
+ value.filename = value.inline ? value.inline['path'] : ''
67
+ end
68
+ values
69
+ end
70
+
50
71
  def post(url, body, path, position)
51
72
  options = {
52
73
  body: {
53
- content: body,
54
- line_to: position,
55
- filename: path
74
+ content: {
75
+ raw: body
76
+ },
77
+ inline: {
78
+ to: position,
79
+ path: path
80
+ }
81
+ }.to_json,
82
+ headers: {
83
+ 'Content-Type': 'application/json'
56
84
  }
57
85
  }
58
86
  self.class.post(url, options)
@@ -18,6 +18,18 @@ module Pronto
18
18
  consolidated
19
19
  end
20
20
 
21
+ def github_review_type
22
+ review_type =
23
+ ENV['PRONTO_GITHUB_REVIEW_TYPE'] ||
24
+ @config_hash.fetch('github_review_type', false)
25
+
26
+ if review_type == 'request_changes'
27
+ 'REQUEST_CHANGES'
28
+ else
29
+ 'COMMENT'
30
+ end
31
+ end
32
+
21
33
  def excluded_files(runner)
22
34
  files =
23
35
  if runner == 'all'
@@ -39,6 +51,10 @@ module Pronto
39
51
  URI.parse(bitbucket_web_endpoint).host
40
52
  end
41
53
 
54
+ def warnings_per_review
55
+ ENV['PRONTO_WARNINGS_PER_REVIEW'] && Integer(ENV['PRONTO_WARNINGS_PER_REVIEW']) || @config_hash['warnings_per_review']
56
+ end
57
+
42
58
  def max_warnings
43
59
  ENV['PRONTO_MAX_WARNINGS'] && Integer(ENV['PRONTO_MAX_WARNINGS']) || @config_hash['max_warnings']
44
60
  end
@@ -1,6 +1,7 @@
1
1
  module Pronto
2
2
  class ConfigFile
3
3
  DEFAULT_MESSAGE_FORMAT = '%{msg}'.freeze
4
+ DEFAULT_WARNINGS_PER_REVIEW = 30
4
5
 
5
6
  EMPTY = {
6
7
  'all' => {
@@ -11,7 +12,8 @@ module Pronto
11
12
  'slug' => nil,
12
13
  'access_token' => nil,
13
14
  'api_endpoint' => 'https://api.github.com/',
14
- 'web_endpoint' => 'https://github.com/'
15
+ 'web_endpoint' => 'https://github.com/',
16
+ 'review_type' => 'request_changes'
15
17
  },
16
18
  'gitlab' => {
17
19
  'slug' => nil,
@@ -32,6 +34,7 @@ module Pronto
32
34
  'runners' => [],
33
35
  'formatters' => [],
34
36
  'max_warnings' => nil,
37
+ 'warnings_per_review' => DEFAULT_WARNINGS_PER_REVIEW,
35
38
  'verbose' => false,
36
39
  'format' => DEFAULT_MESSAGE_FORMAT
37
40
  }.freeze
@@ -7,7 +7,7 @@ module Pronto
7
7
  @output = ''
8
8
  end
9
9
 
10
- def format(messages, _, _)
10
+ def format(messages, _repo, _patches)
11
11
  open_xml
12
12
  process_messages(messages)
13
13
  close_xml
@@ -13,9 +13,11 @@ module Pronto
13
13
  FORMATTERS = {
14
14
  'github' => GithubFormatter,
15
15
  'github_status' => GithubStatusFormatter,
16
+ 'github_combined_status' => GithubCombinedStatusFormatter,
16
17
  'github_pr' => GithubPullRequestFormatter,
17
18
  'github_pr_review' => GithubPullRequestReviewFormatter,
18
19
  'gitlab' => GitlabFormatter,
20
+ 'gitlab_mr' => GitlabMergeRequestReviewFormatter,
19
21
  'bitbucket' => BitbucketFormatter,
20
22
  'bitbucket_pr' => BitbucketPullRequestFormatter,
21
23
  'bitbucket_server_pr' => BitbucketServerPullRequestFormatter,
@@ -0,0 +1,24 @@
1
+ require_relative 'github_status_formatter/status_builder'
2
+
3
+ module Pronto
4
+ module Formatter
5
+ class GithubCombinedStatusFormatter
6
+ def format(messages, repo, _)
7
+ client = Github.new(repo)
8
+ head = repo.head_commit_sha
9
+
10
+ create_status(client, head, messages.uniq || [])
11
+ end
12
+
13
+ private
14
+
15
+ def create_status(client, sha, messages)
16
+ builder = GithubStatusFormatter::StatusBuilder.new(nil, messages)
17
+ status = Status.new(sha, builder.state,
18
+ 'pronto', builder.description)
19
+
20
+ client.create_commit_status(status)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -10,7 +10,7 @@ module Pronto
10
10
  end
11
11
 
12
12
  def submit_comments(client, comments)
13
- client.create_pull_request_review(comments)
13
+ client.publish_pull_request_comments(comments)
14
14
  rescue Octokit::UnprocessableEntity, HTTParty::Error => e
15
15
  $stderr.puts "Failed to post: #{e.message}"
16
16
  end
@@ -0,0 +1,29 @@
1
+ module Pronto
2
+ module Formatter
3
+ class GitlabMergeRequestReviewFormatter < PullRequestFormatter
4
+ def client_module
5
+ Gitlab
6
+ end
7
+
8
+ def pretty_name
9
+ 'Gitlab'
10
+ end
11
+
12
+ def existing_comments(_, client, repo)
13
+ sha = repo.head_commit_sha
14
+ comments = client.pull_comments(sha)
15
+ grouped_comments(comments)
16
+ end
17
+
18
+ def submit_comments(client, comments)
19
+ client.create_pull_request_review(comments)
20
+ rescue => e
21
+ $stderr.puts "Failed to post: #{e.message}"
22
+ end
23
+
24
+ def line_number(message, _)
25
+ message.line.line.new_lineno if message.line
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,7 +3,7 @@ require 'json'
3
3
  module Pronto
4
4
  module Formatter
5
5
  class JsonFormatter < Base
6
- def format(messages, _, _)
6
+ def format(messages, _repo, _patches)
7
7
  messages.map do |message|
8
8
  lineno = message.line.new_lineno if message.line
9
9
 
@@ -1,7 +1,7 @@
1
1
  module Pronto
2
2
  module Formatter
3
3
  class NullFormatter < Base
4
- def format(_, _, _); end
4
+ def format(_messages, _repo, _patches); end
5
5
  end
6
6
  end
7
7
  end
@@ -3,7 +3,7 @@ require 'pronto/formatter/text_message_decorator'
3
3
  module Pronto
4
4
  module Formatter
5
5
  class TextFormatter < Base
6
- def format(messages, _, _)
6
+ def format(messages, _repo, _patches)
7
7
  messages.map do |message|
8
8
  message_format = config.message_format(self.class.name)
9
9
  message_data = TextMessageDecorator.new(message).to_h
@@ -37,8 +37,6 @@ module Pronto
37
37
  repo.path.join(new_file_path)
38
38
  end
39
39
 
40
- private
41
-
42
40
  def new_file_path
43
41
  delta.new_file[:path]
44
42
  end
@@ -38,7 +38,7 @@ module Pronto
38
38
 
39
39
  def commits_until(sha)
40
40
  result = []
41
- @repo.walk(head, Rugged::SORT_TOPO).take_while do |commit|
41
+ @repo.walk(head_commit_sha, Rugged::SORT_TOPO).take_while do |commit|
42
42
  result << commit.oid
43
43
  !commit.oid.start_with?(sha)
44
44
  end
@@ -46,7 +46,7 @@ module Pronto
46
46
  end
47
47
 
48
48
  def path
49
- Pathname.new(@repo.path).parent
49
+ Pathname.new(@repo.workdir).cleanpath
50
50
  end
51
51
 
52
52
  def blame(path, lineno)
@@ -45,17 +45,12 @@ module Pronto
45
45
  end
46
46
  end
47
47
 
48
- def create_pull_request_review(comments)
49
- return if comments.empty?
50
-
51
- options = {
52
- event: 'COMMENT',
53
- accept: 'application/vnd.github.v3.diff+json', # https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
54
- comments: comments.map do |c|
55
- { path: c.path, position: c.position, body: c.body }
56
- end
57
- }
58
- client.create_pull_request_review(slug, pull_id, options)
48
+ def publish_pull_request_comments(comments)
49
+ comments_left = comments.clone
50
+ while comments_left.any?
51
+ comments_to_publish = comments_left.slice!(0, warnings_per_review)
52
+ create_pull_request_review(comments_to_publish)
53
+ end
59
54
  end
60
55
 
61
56
  def create_commit_status(status)
@@ -68,6 +63,21 @@ module Pronto
68
63
 
69
64
  private
70
65
 
66
+ def create_pull_request_review(comments)
67
+ options = {
68
+ event: @config.github_review_type,
69
+ accept: 'application/vnd.github.v3.diff+json', # https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
70
+ comments: comments.map do |comment|
71
+ {
72
+ path: comment.path,
73
+ position: comment.position,
74
+ body: comment.body
75
+ }
76
+ end
77
+ }
78
+ client.create_pull_request_review(slug, pull_id, options)
79
+ end
80
+
71
81
  def slug
72
82
  return @config.github_slug if @config.github_slug
73
83
  @slug ||= begin
@@ -103,5 +113,9 @@ module Pronto
103
113
  @github_pull.pull_by_commit(@repo.head_commit_sha)
104
114
  end
105
115
  end
116
+
117
+ def warnings_per_review
118
+ @warnings_per_review ||= @config.warnings_per_review
119
+ end
106
120
  end
107
121
  end
@@ -2,12 +2,49 @@ module Pronto
2
2
  class Gitlab < Client
3
3
  def commit_comments(sha)
4
4
  @comment_cache[sha.to_s] ||= begin
5
- client.commit_comments(slug, sha, per_page: 500).map do |comment|
5
+ client.commit_comments(slug, sha).auto_paginate.map do |comment|
6
6
  Comment.new(sha, comment.note, comment.path, comment.line)
7
7
  end
8
8
  end
9
9
  end
10
10
 
11
+ def pull_comments(sha)
12
+ @comment_cache["#{slug}/#{pull_id}"] ||= begin
13
+ arr = []
14
+ client.merge_request_discussions(slug, pull_id).auto_paginate.each do |comment|
15
+ comment.notes.each do |note|
16
+ next unless note['position']
17
+
18
+ arr << Comment.new(
19
+ sha,
20
+ note['body'],
21
+ note['position']['new_path'],
22
+ note['position']['new_line']
23
+ )
24
+ end
25
+ end
26
+ arr
27
+ end
28
+ end
29
+
30
+ def create_pull_request_review(comments)
31
+ return if comments.empty?
32
+
33
+ comments.each do |comment|
34
+ options = {
35
+ body: comment.body,
36
+ position: position_sha.dup.merge(
37
+ new_path: comment.path,
38
+ position_type: 'text',
39
+ new_line: comment.position,
40
+ old_line: nil,
41
+ )
42
+ }
43
+
44
+ client.create_merge_request_discussion(slug, pull_id, options)
45
+ end
46
+ end
47
+
11
48
  def create_commit_comment(comment)
12
49
  @config.logger.log("Creating commit comment on #{comment.sha}")
13
50
  client.create_commit_comment(slug, comment.sha, comment.body,
@@ -17,6 +54,15 @@ module Pronto
17
54
 
18
55
  private
19
56
 
57
+ def position_sha
58
+ # Better to get those informations from Gitlab API directly than trying to look for them here.
59
+ # (FYI you can't use `pull` method because index api does not contains those informations)
60
+ @position_sha ||= begin
61
+ data = client.merge_request(slug, pull_id)
62
+ data.diff_refs.to_h
63
+ end
64
+ end
65
+
20
66
  def slug
21
67
  return @config.gitlab_slug if @config.gitlab_slug
22
68
  @slug ||= begin
@@ -27,6 +73,17 @@ module Pronto
27
73
  end
28
74
  end
29
75
 
76
+ def pull_id
77
+ env_pull_id || raise(Pronto::Error, "Unable to determine merge request id. Specify either `PRONTO_PULL_REQUEST_ID` or `CI_MERGE_REQUEST_IID`.")
78
+ end
79
+
80
+ def env_pull_id
81
+ pull_request = super
82
+
83
+ pull_request ||= ENV['CI_MERGE_REQUEST_IID']
84
+ pull_request.to_i if pull_request
85
+ end
86
+
30
87
  def slug_regex(url)
31
88
  if url =~ %r{^ssh:\/\/}
32
89
  %r{.*#{host}(:[0-9]+)?(:|\/)(?<slug>.*).git}
@@ -28,7 +28,10 @@ module Pronto
28
28
  end
29
29
 
30
30
  def ruby_file?(path)
31
- rb_file?(path) || rake_file?(path) || ruby_executable?(path)
31
+ rb_file?(path) ||
32
+ rake_file?(path) ||
33
+ gem_file?(path) ||
34
+ ruby_executable?(path)
32
35
  end
33
36
 
34
37
  def repo_path
@@ -45,6 +48,10 @@ module Pronto
45
48
  File.extname(path) == '.rake'
46
49
  end
47
50
 
51
+ def gem_file?(path)
52
+ File.basename(path) == 'Gemfile' || File.extname(path) == '.gemspec'
53
+ end
54
+
48
55
  def ruby_executable?(path)
49
56
  return false if File.directory?(path)
50
57
  line = File.open(path, &:readline)
@@ -1,6 +1,6 @@
1
1
  module Pronto
2
2
  module Version
3
- STRING = '0.10.0'.freeze
3
+ STRING = '0.11.0'.freeze
4
4
 
5
5
  MSG = '%s (running on %s %s %s)'.freeze
6
6
 
@@ -40,14 +40,15 @@ Gem::Specification.new do |s|
40
40
  s.require_paths = ['lib']
41
41
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
42
42
 
43
- s.add_runtime_dependency('gitlab', '~> 4.0', '>= 4.0.0')
43
+ s.add_runtime_dependency('gitlab', '~> 4.4', '>= 4.4.0')
44
44
  s.add_runtime_dependency('httparty', '>= 0.13.7')
45
45
  s.add_runtime_dependency('octokit', '~> 4.7', '>= 4.7.0')
46
46
  s.add_runtime_dependency('rainbow', '>= 2.2', '< 4.0')
47
- s.add_runtime_dependency('rugged', '~> 0.24', '>= 0.23.0')
48
- s.add_runtime_dependency('thor', '~> 0.20.0')
47
+ s.add_runtime_dependency('rexml', '~> 3.2')
48
+ s.add_runtime_dependency('rugged', '>= 0.23.0', '< 1.1.0')
49
+ s.add_runtime_dependency('thor', '>= 0.20.3', '< 2.0')
49
50
  s.add_development_dependency('bundler', '>= 1.15')
50
- s.add_development_dependency('pronto-rubocop', '~> 0.9.0')
51
+ s.add_development_dependency('pronto-rubocop', '~> 0.10.0')
51
52
  s.add_development_dependency('rake', '~> 12.0')
52
53
  s.add_development_dependency('rspec', '~> 3.4')
53
54
  s.add_development_dependency('rspec-its', '~> 1.2')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pronto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mindaugas Mozūras
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-03 00:00:00.000000000 Z
11
+ date: 2021-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gitlab
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0
19
+ version: 4.4.0
20
20
  - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: '4.0'
22
+ version: '4.4'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 4.0.0
29
+ version: 4.4.0
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '4.0'
32
+ version: '4.4'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: httparty
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -84,6 +84,20 @@ dependencies:
84
84
  - - "<"
85
85
  - !ruby/object:Gem::Version
86
86
  version: '4.0'
87
+ - !ruby/object:Gem::Dependency
88
+ name: rexml
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - "~>"
92
+ - !ruby/object:Gem::Version
93
+ version: '3.2'
94
+ type: :runtime
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - "~>"
99
+ - !ruby/object:Gem::Version
100
+ version: '3.2'
87
101
  - !ruby/object:Gem::Dependency
88
102
  name: rugged
89
103
  requirement: !ruby/object:Gem::Requirement
@@ -91,9 +105,9 @@ dependencies:
91
105
  - - ">="
92
106
  - !ruby/object:Gem::Version
93
107
  version: 0.23.0
94
- - - "~>"
108
+ - - "<"
95
109
  - !ruby/object:Gem::Version
96
- version: '0.24'
110
+ version: 1.1.0
97
111
  type: :runtime
98
112
  prerelease: false
99
113
  version_requirements: !ruby/object:Gem::Requirement
@@ -101,23 +115,29 @@ dependencies:
101
115
  - - ">="
102
116
  - !ruby/object:Gem::Version
103
117
  version: 0.23.0
104
- - - "~>"
118
+ - - "<"
105
119
  - !ruby/object:Gem::Version
106
- version: '0.24'
120
+ version: 1.1.0
107
121
  - !ruby/object:Gem::Dependency
108
122
  name: thor
109
123
  requirement: !ruby/object:Gem::Requirement
110
124
  requirements:
111
- - - "~>"
125
+ - - ">="
112
126
  - !ruby/object:Gem::Version
113
- version: 0.20.0
127
+ version: 0.20.3
128
+ - - "<"
129
+ - !ruby/object:Gem::Version
130
+ version: '2.0'
114
131
  type: :runtime
115
132
  prerelease: false
116
133
  version_requirements: !ruby/object:Gem::Requirement
117
134
  requirements:
118
- - - "~>"
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 0.20.3
138
+ - - "<"
119
139
  - !ruby/object:Gem::Version
120
- version: 0.20.0
140
+ version: '2.0'
121
141
  - !ruby/object:Gem::Dependency
122
142
  name: bundler
123
143
  requirement: !ruby/object:Gem::Requirement
@@ -138,14 +158,14 @@ dependencies:
138
158
  requirements:
139
159
  - - "~>"
140
160
  - !ruby/object:Gem::Version
141
- version: 0.9.0
161
+ version: 0.10.0
142
162
  type: :development
143
163
  prerelease: false
144
164
  version_requirements: !ruby/object:Gem::Requirement
145
165
  requirements:
146
166
  - - "~>"
147
167
  - !ruby/object:Gem::Version
148
- version: 0.9.0
168
+ version: 0.10.0
149
169
  - !ruby/object:Gem::Dependency
150
170
  name: rake
151
171
  requirement: !ruby/object:Gem::Requirement
@@ -243,6 +263,7 @@ extra_rdoc_files:
243
263
  - LICENSE
244
264
  - README.md
245
265
  files:
266
+ - ".github/CODEOWNERS"
246
267
  - CHANGELOG.md
247
268
  - CONTRIBUTING.md
248
269
  - LICENSE
@@ -268,6 +289,7 @@ files:
268
289
  - lib/pronto/formatter/commit_formatter.rb
269
290
  - lib/pronto/formatter/formatter.rb
270
291
  - lib/pronto/formatter/git_formatter.rb
292
+ - lib/pronto/formatter/github_combined_status_formatter.rb
271
293
  - lib/pronto/formatter/github_formatter.rb
272
294
  - lib/pronto/formatter/github_pull_request_formatter.rb
273
295
  - lib/pronto/formatter/github_pull_request_review_formatter.rb
@@ -275,6 +297,7 @@ files:
275
297
  - lib/pronto/formatter/github_status_formatter/sentence.rb
276
298
  - lib/pronto/formatter/github_status_formatter/status_builder.rb
277
299
  - lib/pronto/formatter/gitlab_formatter.rb
300
+ - lib/pronto/formatter/gitlab_merge_request_review_formatter.rb
278
301
  - lib/pronto/formatter/json_formatter.rb
279
302
  - lib/pronto/formatter/null_formatter.rb
280
303
  - lib/pronto/formatter/pull_request_formatter.rb
@@ -316,7 +339,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
316
339
  - !ruby/object:Gem::Version
317
340
  version: '0'
318
341
  requirements: []
319
- rubygems_version: 3.0.1
342
+ rubygems_version: 3.0.3
320
343
  signing_key:
321
344
  specification_version: 4
322
345
  summary: Pronto runs analysis by checking only the introduced changes