multi_repo 0.4.0 → 0.5.1

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: bfc3d56275cbe25e40cecabf411913805b1a83f59395ac0bf721b52130bc1795
4
+ data.tar.gz: b10b82500c86b84030488e687e86bfed2283b83de8911092211dae510c8eb22b
5
5
  SHA512:
6
- metadata.gz: 4828418ee29894ce72fd5d2ab2e705b99854f1aa5ba26f321a0235bfa7c7eadf45a5aada881897aa5df16fb6f83cdd1968113af80e0163d2a13a9e4dd354ee2d
7
- data.tar.gz: b4b2ed2d3c9677e658ad4c60ec615779882dee381bc5ed4b771602d56ca0a5b72ade124e140d50568a359c5e838d99ce3c51a8a475925a096d0582b7adc0cf9e
6
+ metadata.gz: 551aad598181333a741eeb5ab881642f8e455645acb9eea1870494c3f5ce83d5d7a2e7fcbfaf1fa797e652ac8a4c3513907b211db4c5d37560e229bb62c40064
7
+ data.tar.gz: 352099fa70f24b0bd5ecd5493fc7d62dd9ec3c2eb6cdad3b7dde9bef8803b69d1532e303dfe8e37b27a007f9b298a61b515437413e492b21e70eb0bf3eb25c83
@@ -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,28 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.5.1] - 2025-02-20
8
+ ### Added
9
+ - Add debugging of octokit request/response if DEBUG env var set [[#38](https://github.com/ManageIQ/multi_repo/pull/38)]
10
+
11
+ ### Fixed
12
+ - Pin json gem to 2.9.1 since 2.10.0+ is broken [[#41](https://github.com/ManageIQ/multi_repo/pull/41)]
13
+
14
+ ## [0.5.0] - 2024-11-12
15
+ ### Added
16
+ - [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)]
17
+ - [pull_request_labeler] Add normalization of PR formats to org/repo#pr format [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
18
+ - [pull_request_merger] Add URL support to pull_request_merger [[#37](https://github.com/ManageIQ/multi_repo/pull/37)]
19
+ - [Git Service, GitHub service] Move helper methods into services [[#31](https://github.com/ManageIQ/multi_repo/pull/31)]
20
+ - Add testing with ruby 3.2, 3.3 [[#35](https://github.com/ManageIQ/multi_repo/pull/35)]
21
+
22
+ ### Changed
23
+ - [pull_request_labeler] Make add and remove optional [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
24
+
25
+ ### Fixed
26
+ - [pull_request_labeler] Fix cli description of --prs [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
27
+ - [show_commit_history] Handle issue where PR may not be found [[#36](https://github.com/ManageIQ/multi_repo/pull/30)]
28
+
7
29
  ## [0.4.0] - 2024-03-29
8
30
  ### Changed
9
31
  - Allow overriding the path for a repo [[#28](https://github.com/ManageIQ/multi_repo/pull/28)]
@@ -18,6 +40,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
18
40
  - [show_commit_history] Prevent missing ranges from failing the entire run [[#20](https://github.com/ManageIQ/multi_repo/pull/20)]
19
41
  - [pull_request_merger] Fixing issue passing kwargs on Ruby 3 [[#23](https://github.com/ManageIQ/multi_repo/pull/23)]
20
42
 
21
- [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.4.0...HEAD
43
+ [Unreleased]: https://github.com/ManageIQ/more_core_extensions/compare/v0.5.1...HEAD
44
+ [0.5.1]: https://github.com/ManageIQ/more_core_extensions/compare/v0.5.0...v0.5.1
45
+ [0.5.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.4.0...v0.5.0
22
46
  [0.4.0]: https://github.com/ManageIQ/more_core_extensions/compare/v0.3.1...v0.4.0
23
47
  [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
@@ -29,6 +29,13 @@ module MultiRepo::Service
29
29
  }.compact
30
30
 
31
31
  require 'octokit'
32
+
33
+ if ENV["DEBUG"]
34
+ middleware = Octokit.middleware.dup
35
+ middleware.response :logger
36
+ Octokit.middleware = middleware
37
+ end
38
+
32
39
  Octokit::Client.new(params)
33
40
  end
34
41
  end
@@ -83,6 +90,24 @@ module MultiRepo::Service
83
90
  client.workflows(repo_name)[:workflows].select { |w| w.state == "disabled_inactivity" }
84
91
  end
85
92
 
93
+ PR_REGEX = %r{^([^/#]+/[^/#]+)#(\d+)$}
94
+
95
+ # Parse a list of PRs that are in URL or org/repo#pr format into a Array of
96
+ # [repo_name, pr_number] entries.
97
+ def self.parse_prs(*prs)
98
+ prs.flatten.map do |pr|
99
+ # Normalize to org/repo#pr
100
+ normalized_pr = pr.sub("https://github.com/", "").sub("/pull/", "#")
101
+
102
+ if (match = PR_REGEX.match(normalized_pr))
103
+ repo_name, pr_number = match.captures
104
+ [repo_name, pr_number.to_i]
105
+ else
106
+ raise ArgumentError, "Invalid PR '#{pr}'. PR must be a GitHub URL or in org/repo#pr format."
107
+ end
108
+ end
109
+ end
110
+
86
111
  attr_reader :dry_run
87
112
 
88
113
  def initialize(dry_run: false)
@@ -138,6 +163,44 @@ module MultiRepo::Service
138
163
  end
139
164
  end
140
165
 
166
+ def add_labels_to_an_issue(repo_name, issue_number, labels)
167
+ labels = Array(labels)
168
+ if dry_run
169
+ puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{issue_number.inspect}, #{labels.inspect})".light_black
170
+ else
171
+ client.add_labels_to_an_issue(repo_name, issue_number, labels)
172
+ end
173
+ end
174
+
175
+ def remove_labels_from_an_issue(repo_name, issue_number, labels)
176
+ Array(labels).each do |label|
177
+ if dry_run
178
+ puts "** dry-run: github.remove_label(#{repo_name.inspect}, #{issue_number.inspect}, #{label.inspect})".light_black
179
+ else
180
+ client.remove_label(repo_name, issue_number, label)
181
+ end
182
+ rescue Octokit::NotFound
183
+ # Ignore labels that are not found, because we want them removed anyway
184
+ end
185
+ end
186
+
187
+ def add_comment(repo_name, issue_number, body)
188
+ if dry_run
189
+ puts "** dry-run: github.add_comment(#{repo_name.inspect}, #{issue_number.inspect}, #{body.pretty_inspect.chomp})".light_black
190
+ else
191
+ client.add_comment(repo_name, issue_number, body)
192
+ end
193
+ end
194
+
195
+ def assign_user(repo_name, issue_number, assignee)
196
+ assignee = assignee[1..] if assignee.start_with?("@")
197
+ if dry_run
198
+ puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{issue_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
199
+ else
200
+ client.update_issue(repo_name, issue_number, "assignee" => assignee)
201
+ end
202
+ end
203
+
141
204
  def create_milestone(repo_name, title, due_on)
142
205
  if dry_run
143
206
  puts "** dry-run: github.create_milestone(#{repo_name.inspect}, #{title.inspect}, :due_on => #{due_on.strftime("%Y-%m-%d").inspect})".light_black
@@ -208,6 +271,14 @@ module MultiRepo::Service
208
271
  end
209
272
  end
210
273
 
274
+ def merge_pull_request(repo_name, pr_number)
275
+ if dry_run
276
+ puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
277
+ else
278
+ client.merge_pull_request(repo_name, pr_number)
279
+ end
280
+ end
281
+
211
282
  def create_or_update_repository_secret(repo_name, key, value)
212
283
  payload = encode_secret(repo_name, value)
213
284
 
@@ -1,3 +1,3 @@
1
1
  module MultiRepo
2
- VERSION = "0.4.0".freeze
2
+ VERSION = "0.5.1".freeze
3
3
  end
data/multi_repo.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency "activesupport"
26
26
  spec.add_runtime_dependency "colorize"
27
27
  spec.add_runtime_dependency "config"
28
+ spec.add_runtime_dependency "json", "~> 2.9.1" # Pin json due to https://github.com/ruby/json/issues/752
28
29
  spec.add_runtime_dependency "licensee"
29
30
  spec.add_runtime_dependency "minigit"
30
31
  spec.add_runtime_dependency "more_core_extensions"
data/renovate.json CHANGED
@@ -1,6 +1,5 @@
1
1
  {
2
2
  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3
- "extends": [
4
- "config:recommended"
5
- ]
3
+ "inheritConfig": true,
4
+ "inheritConfigRepoName": "manageiq/renovate-config"
6
5
  }
@@ -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,13 @@
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.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Authors
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-03-29 00:00:00.000000000 Z
10
+ date: 2025-02-20 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -52,6 +51,20 @@ dependencies:
52
51
  - - ">="
53
52
  - !ruby/object:Gem::Version
54
53
  version: '0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: json
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 2.9.1
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 2.9.1
55
68
  - !ruby/object:Gem::Dependency
56
69
  name: licensee
57
70
  requirement: !ruby/object:Gem::Requirement
@@ -345,7 +358,6 @@ homepage: http://github.com/ManageIQ/multi_repo
345
358
  licenses:
346
359
  - MIT
347
360
  metadata: {}
348
- post_install_message:
349
361
  rdoc_options: []
350
362
  require_paths:
351
363
  - lib
@@ -360,8 +372,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
360
372
  - !ruby/object:Gem::Version
361
373
  version: '0'
362
374
  requirements: []
363
- rubygems_version: 3.3.26
364
- signing_key:
375
+ rubygems_version: 3.6.5
365
376
  specification_version: 4
366
377
  summary: MultiRepo is a library for managing multiple repositiories and running scripts
367
378
  against them.