multi_repo 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc809429c529e0f58d2274708e0785944edf7170ce7aa23858fc88031bb593e1
4
- data.tar.gz: 7d58ebc46fe2202b9e2e285e6a26fc4b4a40556181301a651994d41b9e4c1d5f
3
+ metadata.gz: 8505baba7399c81174faea1dcce56eb3d16687d1c08c88ac1fe18c2eeae6f26a
4
+ data.tar.gz: d513358adc717ca4582c6f29864926a0a23bfb01a88a0622b55ff358939f7d35
5
5
  SHA512:
6
- metadata.gz: 4828418ee29894ce72fd5d2ab2e705b99854f1aa5ba26f321a0235bfa7c7eadf45a5aada881897aa5df16fb6f83cdd1968113af80e0163d2a13a9e4dd354ee2d
7
- data.tar.gz: b4b2ed2d3c9677e658ad4c60ec615779882dee381bc5ed4b771602d56ca0a5b72ade124e140d50568a359c5e838d99ce3c51a8a475925a096d0582b7adc0cf9e
6
+ metadata.gz: 86f552f73954d01bbf06b31906170399eee68a60721538743dd5fdf2ce46832e918c89740d49e83c337a150f52dc9f8be3f73d0cb37f459fab3dcf317e244366
7
+ data.tar.gz: 86846ee0c472f5eb5b8ebade9bdafa87985db8ab114e210b6b0aa276e36466a56412260a6e503cc436dc874893f13baa140733542088816bae034c40ce7e3e5d
@@ -14,6 +14,8 @@ jobs:
14
14
  ruby-version:
15
15
  - '3.0'
16
16
  - '3.1'
17
+ - '3.2'
18
+ - '3.3'
17
19
  env:
18
20
  CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
19
21
  steps:
@@ -29,4 +31,4 @@ jobs:
29
31
  - name: Report code coverage
30
32
  if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '3.1' }}
31
33
  continue-on-error: true
32
- uses: paambaati/codeclimate-action@v5
34
+ uses: paambaati/codeclimate-action@v9
data/CHANGELOG.md CHANGED
@@ -4,6 +4,21 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.5.0] - 2024-11-12
8
+ ### Added
9
+ - [pull_request_labeler] Add ability to also add a comment about why the labels are changing [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
10
+ - [pull_request_labeler] Add normalization of PR formats to org/repo#pr format [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
11
+ - [pull_request_merger] Add URL support to pull_request_merger [[#37](https://github.com/ManageIQ/multi_repo/pull/37)]
12
+ - [Git Service, GitHub service] Move helper methods into services [[#31](https://github.com/ManageIQ/multi_repo/pull/31)]
13
+ - Add testing with ruby 3.2, 3.3 [[#35](https://github.com/ManageIQ/multi_repo/pull/35)]
14
+
15
+ ### Changed
16
+ - [pull_request_labeler] Make add and remove optional [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
17
+
18
+ ### Fixed
19
+ - [pull_request_labeler] Fix cli description of --prs [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
20
+ - [show_commit_history] Handle issue where PR may not be found [[#36](https://github.com/ManageIQ/multi_repo/pull/30)]
21
+
7
22
  ## [0.4.0] - 2024-03-29
8
23
  ### Changed
9
24
  - Allow overriding the path for a repo [[#28](https://github.com/ManageIQ/multi_repo/pull/28)]
@@ -18,6 +33,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
18
33
  - [show_commit_history] Prevent missing ranges from failing the entire run [[#20](https://github.com/ManageIQ/multi_repo/pull/20)]
19
34
  - [pull_request_merger] Fixing issue passing kwargs on Ruby 3 [[#23](https://github.com/ManageIQ/multi_repo/pull/23)]
20
35
 
21
- [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.4.0...HEAD
36
+ [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.5.0...HEAD
37
+ [0.5.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.4.0...v0.5.0
22
38
  [0.4.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.3.1...v0.4.0
23
39
  [0.3.1]: https://github.com/ManageIQ/more_core_extensions/compare/v0.3.0...v0.3.1
@@ -83,6 +83,17 @@ module MultiRepo::Service
83
83
  true
84
84
  end
85
85
 
86
+ def destroy_remote(remote)
87
+ if dry_run
88
+ puts "** dry-run: git remote rm #{remote}".light_black
89
+ else
90
+ client.remote("rm", remote)
91
+ end
92
+ rescue MiniGit::GitError
93
+ # Ignore missing remotes because we want them destroyed anyway
94
+ nil
95
+ end
96
+
86
97
  def remote_branch?(remote, branch)
87
98
  client.capturing.ls_remote(remote, branch).present?
88
99
  end
@@ -83,6 +83,24 @@ module MultiRepo::Service
83
83
  client.workflows(repo_name)[:workflows].select { |w| w.state == "disabled_inactivity" }
84
84
  end
85
85
 
86
+ PR_REGEX = %r{^([^/#]+/[^/#]+)#(\d+)$}
87
+
88
+ # Parse a list of PRs that are in URL or org/repo#pr format into a Array of
89
+ # [repo_name, pr_number] entries.
90
+ def self.parse_prs(*prs)
91
+ prs.flatten.map do |pr|
92
+ # Normalize to org/repo#pr
93
+ normalized_pr = pr.sub("https://github.com/", "").sub("/pull/", "#")
94
+
95
+ if (match = PR_REGEX.match(normalized_pr))
96
+ repo_name, pr_number = match.captures
97
+ [repo_name, pr_number.to_i]
98
+ else
99
+ raise ArgumentError, "Invalid PR '#{pr}'. PR must be a GitHub URL or in org/repo#pr format."
100
+ end
101
+ end
102
+ end
103
+
86
104
  attr_reader :dry_run
87
105
 
88
106
  def initialize(dry_run: false)
@@ -138,6 +156,44 @@ module MultiRepo::Service
138
156
  end
139
157
  end
140
158
 
159
+ def add_labels_to_an_issue(repo_name, issue_number, labels)
160
+ labels = Array(labels)
161
+ if dry_run
162
+ puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{issue_number.inspect}, #{labels.inspect})".light_black
163
+ else
164
+ client.add_labels_to_an_issue(repo_name, issue_number, labels)
165
+ end
166
+ end
167
+
168
+ def remove_labels_from_an_issue(repo_name, issue_number, labels)
169
+ Array(labels).each do |label|
170
+ if dry_run
171
+ puts "** dry-run: github.remove_label(#{repo_name.inspect}, #{issue_number.inspect}, #{label.inspect})".light_black
172
+ else
173
+ client.remove_label(repo_name, issue_number, label)
174
+ end
175
+ rescue Octokit::NotFound
176
+ # Ignore labels that are not found, because we want them removed anyway
177
+ end
178
+ end
179
+
180
+ def add_comment(repo_name, issue_number, body)
181
+ if dry_run
182
+ puts "** dry-run: github.add_comment(#{repo_name.inspect}, #{issue_number.inspect}, #{body.pretty_inspect.chomp})".light_black
183
+ else
184
+ client.add_comment(repo_name, issue_number, body)
185
+ end
186
+ end
187
+
188
+ def assign_user(repo_name, issue_number, assignee)
189
+ assignee = assignee[1..] if assignee.start_with?("@")
190
+ if dry_run
191
+ puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{issue_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
192
+ else
193
+ client.update_issue(repo_name, issue_number, "assignee" => assignee)
194
+ end
195
+ end
196
+
141
197
  def create_milestone(repo_name, title, due_on)
142
198
  if dry_run
143
199
  puts "** dry-run: github.create_milestone(#{repo_name.inspect}, #{title.inspect}, :due_on => #{due_on.strftime("%Y-%m-%d").inspect})".light_black
@@ -208,6 +264,14 @@ module MultiRepo::Service
208
264
  end
209
265
  end
210
266
 
267
+ def merge_pull_request(repo_name, pr_number)
268
+ if dry_run
269
+ puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
270
+ else
271
+ client.merge_pull_request(repo_name, pr_number)
272
+ end
273
+ end
274
+
211
275
  def create_or_update_repository_secret(repo_name, key, value)
212
276
  payload = encode_secret(repo_name, value)
213
277
 
@@ -1,3 +1,3 @@
1
1
  module MultiRepo
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "0.5.0".freeze
3
3
  end
@@ -20,9 +20,5 @@ MultiRepo::CLI.each_repo(**opts) do |repo|
20
20
  next
21
21
  end
22
22
 
23
- if opts[:dry_run]
24
- puts "** dry-run: git remote rm #{opts[:remote]}".light_black
25
- else
26
- repo.git.client.remote("rm", opts[:remote])
27
- end
23
+ repo.git.destroy_remote(opts[:remote])
28
24
  end
@@ -9,53 +9,32 @@ end
9
9
  opts = Optimist.options do
10
10
  synopsis "Add or remove labels on a set of pull requests."
11
11
 
12
- opt :prs, "The list of PRs to merge", :type => :strings, :required => true
13
- opt :add, "Labels to add", :type => :strings, :required => true
14
- opt :remove, "Labels to remove", :type => :strings, :required => true
12
+ opt :prs, "The list of PRs to label", :type => :strings, :required => true
13
+ opt :add, "Labels to add", :type => :strings
14
+ opt :remove, "Labels to remove", :type => :strings
15
15
 
16
- MultiRepo::CLI.common_options(self, :only => :dry_run)
17
- end
18
-
19
- # TODO: Normalize any PR format to `org/repo#pr`
20
- PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
21
- Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }
22
-
23
- def github
24
- MultiRepo::Service::Github.client
25
- end
16
+ opt :comment, "Comment explaining the label change", :type => :string
26
17
 
27
- def add_labels(repo_name, pr_number, labels:, dry_run:, **_)
28
- labels = Array(labels)
29
- if dry_run
30
- puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
31
- else
32
- github.add_labels_to_an_issue(repo_name, pr_number, labels)
33
- end
18
+ MultiRepo::CLI.common_options(self, :only => :dry_run)
34
19
  end
35
20
 
36
- def remove_labels(repo_name, pr_number, labels:, dry_run:, **_)
37
- Array(labels).each do |label|
38
- remove_label(repo_name, pr_number, label: label, dry_run: dry_run)
39
- end
40
- end
21
+ Optimist.die "at least one of --add or --remove is required" unless opts[:add_given] || opts[:remove_given]
41
22
 
42
- def remove_label(repo_name, pr_number, label:, dry_run:, **_)
43
- if dry_run
44
- puts "** dry-run: github.remove_label(#{repo_name.inspect}, #{pr_number.inspect}, #{label.inspect})".light_black
45
- else
46
- github.remove_label(repo_name, pr_number, label)
23
+ prs =
24
+ begin
25
+ MultiRepo::Service::Github.parse_prs(opts[:prs])
26
+ rescue ArgumentError => err
27
+ Optimist.die :prs, err.message
47
28
  end
48
- rescue Octokit::NotFound
49
- # Ignore labels that are not found, because we want them removed anyway
50
- end
51
29
 
52
- opts[:prs].each do |pr|
53
- puts MultiRepo::CLI.header(pr)
30
+ github = MultiRepo::Service::Github.new(:dry_run => opts[:dry_run])
54
31
 
55
- repo_name, pr_number = PR_REGEX.match(pr).captures
32
+ prs.each do |repo_name, pr_number|
33
+ puts MultiRepo::CLI.header("#{repo_name}##{pr_number}")
56
34
 
57
- add_labels(repo_name, pr_number, labels: opts[:add], **opts)
58
- remove_labels(repo_name, pr_number, labels: opts[:remove], **opts)
35
+ github.add_labels_to_an_issue(repo_name, pr_number, opts[:add]) if opts[:add].present?
36
+ github.remove_labels_from_an_issue(repo_name, pr_number, opts[:remove]) if opts[:remove].present?
37
+ github.add_comment(repo_name, pr_number, opts[:comment]) if opts[:comment].present?
59
38
 
60
39
  puts
61
40
  end
@@ -16,50 +16,28 @@ opts = Optimist.options do
16
16
  MultiRepo::CLI.common_options(self)
17
17
  end
18
18
 
19
- # TODO: Normalize any PR format to `org/repo#pr`
20
- PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
21
- Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }
22
-
23
- def merge_pull_request(repo_name, pr_number, dry_run:, **_)
24
- if dry_run
25
- puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
26
- else
27
- begin
28
- MultiRepo::Service::Github.client.merge_pull_request(repo_name, pr_number)
29
- rescue Octokit::MethodNotAllowed => err
30
- raise unless err.to_s.include?("Pull Request is not mergeable")
31
-
32
- puts "** WARN: Pull Request is not mergeable"
33
- end
19
+ prs =
20
+ begin
21
+ MultiRepo::Service::Github.parse_prs(opts[:prs])
22
+ rescue ArgumentError => err
23
+ Optimist.die :prs, err.message
34
24
  end
35
- end
36
25
 
37
- def add_labels(repo_name, pr_number, labels:, dry_run:, **_)
38
- labels = Array(labels)
39
- if dry_run
40
- puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
41
- else
42
- MultiRepo::Service::Github.client.add_labels_to_an_issue(repo_name, pr_number, labels)
43
- end
44
- end
26
+ github = MultiRepo::Service::Github.new(:dry_run => opts[:dry_run])
45
27
 
46
- def assign_user(repo_name, pr_number, assignee:, dry_run:, **_)
47
- assignee = assignee[1..] if assignee.start_with?("@")
48
- if dry_run
49
- puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{pr_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
50
- else
51
- MultiRepo::Service::Github.client.update_issue(repo_name, pr_number, "assignee" => assignee)
52
- end
53
- end
28
+ prs.each do |repo_name, pr_number|
29
+ puts MultiRepo::CLI.header("#{repo_name}##{pr_number}")
54
30
 
55
- opts[:prs].each do |pr|
56
- puts MultiRepo::CLI.header(pr)
31
+ begin
32
+ github.merge_pull_request(repo_name, pr_number)
33
+ rescue Octokit::MethodNotAllowed => err
34
+ raise unless err.to_s.include?("Pull Request is not mergeable")
57
35
 
58
- repo_name, pr_number = PR_REGEX.match(pr).captures
36
+ puts "** WARN: Pull Request is not mergeable".light_yellow
37
+ end
59
38
 
60
- merge_pull_request(repo_name, pr_number, **opts)
61
- add_labels(repo_name, pr_number, **opts) if opts[:labels].present?
62
- assign_user(repo_name, pr_number, **opts)
39
+ github.add_labels_to_an_issue(repo_name, pr_number, opts[:labels]) if opts[:labels].present?
40
+ github.assign_user(repo_name, pr_number, opts[:assignee])
63
41
 
64
42
  puts
65
43
  end
@@ -60,7 +60,12 @@ MultiRepo::CLI.repos_for(**opts).each do |repo|
60
60
  log.lines.each do |line|
61
61
  next unless (match = line.match(/Merge pull request #(\d+)\b/))
62
62
 
63
- pr = github.pull_request(repo.name, match[1])
63
+ pr =
64
+ begin
65
+ github.pull_request(repo.name, match[1])
66
+ rescue Octokit::NotFound
67
+ next # PR not found could mean this was a cherry-pick from a different repo, so the PR doesn't exist.
68
+ end
64
69
  label = pr.labels.detect { |l| results.key?(l.name) }&.name || "other"
65
70
  results[label] << pr
66
71
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multi_repo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Authors
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-29 00:00:00.000000000 Z
11
+ date: 2024-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -360,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
360
360
  - !ruby/object:Gem::Version
361
361
  version: '0'
362
362
  requirements: []
363
- rubygems_version: 3.3.26
363
+ rubygems_version: 3.3.27
364
364
  signing_key:
365
365
  specification_version: 4
366
366
  summary: MultiRepo is a library for managing multiple repositiories and running scripts