multi_repo 1.0.0 → 1.2.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: a65fcbfd465cabf43b5382db582a7516ad14d37ddaccb9dde5de7522879bf28a
4
- data.tar.gz: eebc43a34102d63149ec5ca32369576814ec9182b402c0e823178b7b4f4c90ea
3
+ metadata.gz: ff97c5d89d0a12946bcfeedc113427407e9858f72f687cad2c6c133db1bb41b4
4
+ data.tar.gz: 12f0b8884470a4dd1430cdc1b4bb131f3f93e5957bf66c5400ffa67d3fdbce78
5
5
  SHA512:
6
- metadata.gz: 51f252cfde3038b0cc51c8c254b45e9153d3e09ad535493b1a978e1dc7a3408d26aabbadf4f81fead3e7c93d2f9995c59f6d4eacd700736081a134e98e70ebdb
7
- data.tar.gz: 1bdcbab162f091ea83e96db96a81252e866f8aa87a50b9f96ec64239d54b8f9805c676d8c02544ba0f3f031ae11d472d03bf831c00fc8628b16a8292ea2439c3
6
+ metadata.gz: e562d3f593d9b5f3481cc8d1aafdc67aa0c938bd266f2ab939d07ebdd8fde31dbebf26026760451fcb0127613f0f356bf9f03ee7d264851f8b77d0747882f385
7
+ data.tar.gz: 03b147b28464d5179423794d5e96ee42feb3b8edc586d0407d9560769ba42ece76d498090692bebac3d339948defd498fe9e2820fc8e39dc24b8318fa512f6f8
@@ -1,11 +1,18 @@
1
1
  name: CI
2
-
3
2
  on:
4
- push:
5
3
  pull_request:
4
+ push:
5
+ branches-ignore:
6
+ - dependabot/*
7
+ - renovate/*
6
8
  schedule:
7
- - cron: '0 0 * * 0'
8
-
9
+ - cron: 0 0 * * 0
10
+ workflow_dispatch:
11
+ concurrency:
12
+ group: "${{ github.workflow }}-${{ github.ref }}"
13
+ cancel-in-progress: true
14
+ permissions:
15
+ contents: read
9
16
  jobs:
10
17
  ci:
11
18
  runs-on: ubuntu-latest
@@ -16,19 +23,13 @@ jobs:
16
23
  - '3.1'
17
24
  - '3.2'
18
25
  - '3.3'
19
- env:
20
- CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
21
26
  steps:
22
- - uses: actions/checkout@v4
27
+ - uses: actions/checkout@v6
23
28
  - name: Set up Ruby
24
29
  uses: ruby/setup-ruby@v1
25
30
  with:
26
- ruby-version: ${{ matrix.ruby-version }}
31
+ ruby-version: "${{ matrix.ruby-version }}"
27
32
  bundler-cache: true
28
33
  timeout-minutes: 30
29
34
  - name: Run tests
30
35
  run: bundle exec rake
31
- - name: Report code coverage
32
- if: ${{ github.ref == 'refs/heads/master' && matrix.ruby-version == '3.1' }}
33
- continue-on-error: true
34
- uses: paambaati/codeclimate-action@v9
data/CHANGELOG.md CHANGED
@@ -4,6 +4,30 @@ This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.2.0] - 2026-04-14
8
+ ### Added
9
+ - [Artifactory service] Add head and exists? methods [[#97](https://github.com/ManageIQ/multi_repo/pull/97)]
10
+ - [pull_request_blaster_outer] Add ability to override message in the script [[#70](https://github.com/ManageIQ/multi_repo/pull/70)]
11
+ - [pull_request_blaster_outer] Add ability to specify a different fork name [[#71](https://github.com/ManageIQ/multi_repo/pull/71)]
12
+ - [show_org_repos] Add options include_forks and include_archived [[#73](https://github.com/ManageIQ/multi_repo/pull/73)]
13
+
14
+ ### Fixed
15
+ - [Git service] Handle when tags move during a git fetch which would otherwise fail [[#75](https://github.com/ManageIQ/multi_repo/pull/75)]
16
+ - [each_repo] Fix each_repo when the script needs to bundle [[#72](https://github.com/ManageIQ/multi_repo/pull/72)]
17
+ - [delete_labels] Fix a constant problem [[#67](https://github.com/ManageIQ/multi_repo/pull/67)]
18
+
19
+ ### Removed
20
+ - **BREAKING** Drop CodeClimate [[#74](https://github.com/ManageIQ/multi_repo/pull/74)]
21
+
22
+ ## [1.1.0] - 2025-10-01
23
+ ### Added
24
+ - [show_commit_history] Add pr-changelog display format [[#49](https://github.com/ManageIQ/multi_repo/pull/49)]
25
+ - [pull_request_blaster_outer] Prevent git show paging when using --force [[#53](https://github.com/ManageIQ/multi_repo/pull/53)]
26
+
27
+ ### Changed
28
+ - Update licensee to at least 9.7.0 [[#54](https://github.com/ManageIQ/multi_repo/pull/54)]
29
+ - Separate progress bar options from creation of the progress bar [[#55](https://github.com/ManageIQ/multi_repo/pull/55)]
30
+
7
31
  ## [1.0.0] - 2025-04-24
8
32
  ### Added
9
33
  - Allow blank overrides on the command line [[#46](https://github.com/ManageIQ/multi_repo/pull/46)]
@@ -35,7 +59,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
35
59
 
36
60
  ### Fixed
37
61
  - [pull_request_labeler] Fix cli description of --prs [[#30](https://github.com/ManageIQ/multi_repo/pull/30)]
38
- - [show_commit_history] Handle issue where PR may not be found [[#36](https://github.com/ManageIQ/multi_repo/pull/30)]
62
+ - [show_commit_history] Handle issue where PR may not be found [[#36](https://github.com/ManageIQ/multi_repo/pull/36)]
39
63
 
40
64
  ## [0.4.0] - 2024-03-29
41
65
  ### Changed
@@ -51,7 +75,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
51
75
  - [show_commit_history] Prevent missing ranges from failing the entire run [[#20](https://github.com/ManageIQ/multi_repo/pull/20)]
52
76
  - [pull_request_merger] Fixing issue passing kwargs on Ruby 3 [[#23](https://github.com/ManageIQ/multi_repo/pull/23)]
53
77
 
54
- [Unreleased]: https://github.com/ManageIQ/multi_repo/compare/v1.0.0...HEAD
78
+ [Unreleased]: https://github.com/ManageIQ/multi_repo/compare/v1.2.0...HEAD
79
+ [1.2.0]: https://github.com/ManageIQ/multi_repo/compare/v1.1.0...v1.2.0
80
+ [1.1.0]: https://github.com/ManageIQ/multi_repo/compare/v1.0.0...v1.1.0
55
81
  [1.0.0]: https://github.com/ManageIQ/multi_repo/compare/v0.6.0...v1.0.0
56
82
  [0.6.0]: https://github.com/ManageIQ/multi_repo/compare/v0.5.1...v0.6.0
57
83
  [0.5.1]: https://github.com/ManageIQ/multi_repo/compare/v0.5.0...v0.5.1
data/README.md CHANGED
@@ -4,7 +4,6 @@ MultiRepo is a tool for managing multiple git repositories.
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/multi_repo.svg)](http://badge.fury.io/rb/multi_repo)
6
6
  [![CI](https://github.com/ManageIQ/multi_repo/actions/workflows/ci.yaml/badge.svg)](https://github.com/ManageIQ/multi_repo/actions/workflows/ci.yaml)
7
- [![Code Climate](https://codeclimate.com/github/ManageIQ/multi_repo.svg)](https://codeclimate.com/github/ManageIQ/multi_repo)
8
7
 
9
8
  ## Installation
10
9
 
@@ -19,7 +18,7 @@ gem install multi_repo
19
18
  Typical usage will be from single scripts. In order to keep each script manageable, it can be preferable to use bundler/inline to define the gems needed by that script. To do this, add the following to the top of the script:
20
19
 
21
20
  ```ruby
22
- #/usr/bin/env ruby
21
+ #!/usr/bin/env ruby
23
22
 
24
23
  require "bundler/inline"
25
24
  gemfile do
@@ -69,7 +68,7 @@ purposes
69
68
  - Go to https://github.com/settings/tokens
70
69
  - Choose "Generate New Token"
71
70
  - Give the token a description
72
- - At a mimimum, choose "repo" for the permissions.
71
+ - At a minimum, choose "repo" for the permissions.
73
72
  - Click "Generate Token"
74
73
  - Copy the token given to you, and keep it in a safe location, as once you leave
75
74
  the page, the token is no longer accessible
@@ -84,11 +84,15 @@ module MultiRepo
84
84
 
85
85
  def self.progress_bar(total = 100)
86
86
  require "progressbar"
87
- ProgressBar.create(
87
+ ProgressBar.create(progress_bar_options(total))
88
+ end
89
+
90
+ def self.progress_bar_options(total = 100)
91
+ {
88
92
  :format => "%j%% |%B| %E",
89
93
  :length => HEADER_SIZE,
90
94
  :total => total
91
- )
95
+ }
92
96
  end
93
97
  end
94
98
  end
@@ -2,9 +2,9 @@ require 'pathname'
2
2
 
3
3
  module MultiRepo::Helpers
4
4
  class PullRequestBlasterOuter
5
- attr_reader :repo, :base, :head, :script, :dry_run, :message, :title, :force
5
+ attr_reader :repo, :base, :head, :script, :dry_run, :source_message, :source_title, :source_body, :force
6
6
 
7
- def initialize(repo, base:, head:, script:, dry_run:, message:, title: nil, force: false, **)
7
+ def initialize(repo, base:, head:, script:, dry_run:, message:, title: nil, body: nil, force: false, **)
8
8
  @repo = repo
9
9
  @base = base
10
10
  @head = head
@@ -14,9 +14,11 @@ module MultiRepo::Helpers
14
14
  s.to_s
15
15
  end
16
16
  @dry_run = dry_run
17
- @message = message
18
- @title = (title || message)[0, 72]
19
17
  @force = force
18
+
19
+ @source_message = message&.gsub("\\n", "\n")
20
+ @source_title = title
21
+ @source_body = body&.gsub("\\n", "\n")
20
22
  end
21
23
 
22
24
  def blast
@@ -41,7 +43,14 @@ module MultiRepo::Helpers
41
43
  puts
42
44
 
43
45
  if dry_run
44
- puts "** dry-run: Skipping opening pull request".light_black
46
+ puts "** dry-run: Skipping opening pull request. The pull request would look like:".light_black
47
+ puts
48
+ puts "Pull Request Title:".light_black
49
+ puts title.light_black
50
+ puts
51
+ puts "Pull Request Body:".light_black
52
+ puts body.light_black
53
+
45
54
  result = "dry run".light_black
46
55
  else
47
56
  answer =
@@ -67,19 +76,31 @@ module MultiRepo::Helpers
67
76
 
68
77
  private
69
78
 
79
+ attr_accessor :override_message
80
+
81
+ def message
82
+ override_message || source_message
83
+ end
84
+
85
+ def title
86
+ source_title || message.lines.first.chomp[0, 72]
87
+ end
88
+
89
+ def body
90
+ source_body || message.lines.drop(1).join.strip
91
+ end
92
+
70
93
  def github
71
94
  @github ||= MultiRepo::Service::Github.new(dry_run: dry_run)
72
95
  end
73
96
 
74
- def forked?
75
- # NOTE: There is an assumption here that the fork's name will match the source's name.
76
- # Ideally there would be a "forked from" field in the repo metadata, but there isn't.
77
- github.client.repos(github.client.login, :type => "forks").any? { |m| m.name == repo.short_name }
97
+ def forked?(cache: true)
98
+ github.forks(cache: cache).any? { |f| f.name == repo.fork_short_name }
78
99
  end
79
100
 
80
101
  def fork_repo
81
102
  github.client.fork(repo.name)
82
- until forked?
103
+ until forked?(cache: false)
83
104
  print "."
84
105
  sleep 3
85
106
  end
@@ -88,6 +109,10 @@ module MultiRepo::Helpers
88
109
  def run_script
89
110
  repo.chdir do
90
111
  Bundler.with_unbundled_env do
112
+ # Ensure any previous override commit message is removed
113
+ FileUtils.rm_f(".git/COMMIT_EDITMSG")
114
+ self.override_message = nil
115
+
91
116
  parts = []
92
117
  parts << "GITHUB_REPO=#{repo.name}"
93
118
  parts << "DRY_RUN=true" if dry_run
@@ -98,6 +123,10 @@ module MultiRepo::Helpers
98
123
  puts "!! Script execution failed.".light_red
99
124
  exit $?.exitstatus
100
125
  end
126
+
127
+ if File.exist?(".git/COMMIT_EDITMSG")
128
+ self.override_message = File.read(".git/COMMIT_EDITMSG")
129
+ end
101
130
  end
102
131
  end
103
132
  end
@@ -112,7 +141,11 @@ module MultiRepo::Helpers
112
141
  end
113
142
 
114
143
  def show_commit
115
- repo.git.client.show
144
+ if force
145
+ repo.git.raw("--no-pager", "show")
146
+ else
147
+ repo.git.client.show
148
+ end
116
149
  end
117
150
 
118
151
  def blast_remote
@@ -134,7 +167,7 @@ module MultiRepo::Helpers
134
167
  end
135
168
 
136
169
  def open_pull_request
137
- pr = github.client.create_pull_request(repo.name, base, pr_head, title, title)
170
+ pr = github.client.create_pull_request(repo.name, base, pr_head, title, body)
138
171
  pr.html_url
139
172
  rescue => err
140
173
  raise unless err.message.include?("A pull request already exists")
@@ -27,6 +27,14 @@ module MultiRepo
27
27
  name.split("/").last
28
28
  end
29
29
 
30
+ def fork_name
31
+ config.fork_name
32
+ end
33
+
34
+ def fork_short_name
35
+ fork_name&.split("/")&.last || short_name
36
+ end
37
+
30
38
  def write_file(file, content, **kwargs)
31
39
  if dry_run
32
40
  puts "** dry-run: Writing #{path.join(file).expand_path}".light_black
@@ -40,6 +40,18 @@ module MultiRepo::Service
40
40
  request(:get, path, **kwargs)
41
41
  end
42
42
 
43
+ def head(path, **kwargs)
44
+ path = path.to_s
45
+ request(:head, path, **kwargs)
46
+ end
47
+
48
+ def exists?(path, **kwargs)
49
+ head(path, **kwargs)
50
+ true
51
+ rescue RestClient::NotFound
52
+ false
53
+ end
54
+
43
55
  def list(folder, cache: @cache, **kwargs)
44
56
  folder = folder.to_s
45
57
  cache_file = "/tmp/artifactory-#{folder.tr("/", "_")}-#{Date.today}.txt"
@@ -94,6 +106,8 @@ module MultiRepo::Service
94
106
  "Accept" => "application/json",
95
107
  "Content-Type" => "application/json"
96
108
  )
109
+ headers = headers.except("Accept") if verb == :head
110
+
97
111
  path = File.join(self.class.api_endpoint, path)
98
112
 
99
113
  puts "+ #{verb.to_s.upcase} #{path}".light_black if verbose
@@ -18,18 +18,21 @@ module MultiRepo::Service
18
18
  retry
19
19
  end
20
20
 
21
- def self.clone(clone_source:, path:)
21
+ def self.raw(*args, quiet: false)
22
22
  require "minigit"
23
23
  require "shellwords"
24
24
 
25
- args = ["clone", clone_source, path]
26
25
  command = Shellwords.join(["git", *args])
27
- command << " &>/dev/null" unless ENV["GIT_DEBUG"]
26
+ command << " &>/dev/null" if quiet && !ENV["GIT_DEBUG"]
28
27
  puts "+ #{command}" if ENV["GIT_DEBUG"] # Matches the output of MiniGit
29
28
 
30
29
  raise MiniGit::GitError.new(args, $?) unless system(command)
31
30
  end
32
31
 
32
+ def self.clone(clone_source:, path:)
33
+ raw("clone", clone_source, path, quiet: true)
34
+ end
35
+
33
36
  attr_reader :dry_run, :client
34
37
 
35
38
  def initialize(path:, clone_source:, dry_run: false)
@@ -39,10 +42,14 @@ module MultiRepo::Service
39
42
  @client = self.class.client(path: path, clone_source: clone_source)
40
43
  end
41
44
 
45
+ def raw(*args)
46
+ Dir.chdir(client.git_dir) { self.class.raw(*args) }
47
+ end
48
+
42
49
  def fetch(output: false)
43
50
  client = output ? self.client : self.client.capturing
44
51
 
45
- client.fetch(:all => true, :tags => true)
52
+ client.fetch(:all => true, :tags => true, :force => true)
46
53
  end
47
54
 
48
55
  def hard_checkout(branch, source = "origin/#{branch}", output: false)
@@ -90,6 +90,11 @@ module MultiRepo::Service
90
90
  client.workflows(repo_name)[:workflows].select { |w| w.state == "disabled_inactivity" }
91
91
  end
92
92
 
93
+ def self.forks(cache: true)
94
+ @forks = nil unless cache
95
+ @forks ||= client.repos(client.login, :type => "forks")
96
+ end
97
+
93
98
  PR_REGEX = %r{^([^/#]+/[^/#]+)#(\d+)$}
94
99
 
95
100
  # Parse a list of PRs that are in URL or org/repo#pr format into a Array of
@@ -125,6 +130,7 @@ module MultiRepo::Service
125
130
  :team_member_names,
126
131
  :team_ids_by_name,
127
132
  :team_names,
133
+ :forks,
128
134
  :disabled_workflows,
129
135
  :to => :class
130
136
 
@@ -1,3 +1,3 @@
1
1
  module MultiRepo
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.2.0".freeze
3
3
  end
data/lib/multi_repo.rb CHANGED
@@ -11,7 +11,6 @@ require 'multi_repo/repo'
11
11
  require 'multi_repo/repo_set'
12
12
 
13
13
  require 'multi_repo/service/artifactory'
14
- require 'multi_repo/service/code_climate'
15
14
  require 'multi_repo/service/docker'
16
15
  require 'multi_repo/service/git'
17
16
  require 'multi_repo/service/github'
data/multi_repo.gemspec CHANGED
@@ -25,7 +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 "licensee"
28
+ spec.add_runtime_dependency "licensee", ">= 9.7.0"
29
29
  spec.add_runtime_dependency "minigit"
30
30
  spec.add_runtime_dependency "more_core_extensions"
31
31
  spec.add_runtime_dependency "octokit", ">= 7.0.0"
@@ -36,7 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency "rest-client"
37
37
 
38
38
  spec.add_development_dependency "bundler"
39
- spec.add_development_dependency "manageiq-style", ">= 1.5.4"
39
+ spec.add_development_dependency "manageiq-style"
40
40
  spec.add_development_dependency "rake"
41
41
  spec.add_development_dependency "rspec", ">= 3.0"
42
42
  spec.add_development_dependency "simplecov", ">= 0.21.2"
@@ -13,7 +13,7 @@ opts = Optimist.options do
13
13
 
14
14
  MultiRepo::CLI.common_options(self, :repo_set_default => nil)
15
15
  end
16
- opts[:repo] = MultiRepo::Helpers::Labels.all.keys.sort unless opts[:repo] || opts[:repo_set]
16
+ opts[:repo] = MultiRepo::Labels.all.keys.sort unless opts[:repo] || opts[:repo_set]
17
17
 
18
18
  github = MultiRepo::Service::Github.new(dry_run: opts[:dry_run])
19
19
 
data/scripts/each_repo CHANGED
@@ -19,7 +19,9 @@ MultiRepo::CLI.each_repo(**opts) do |repo|
19
19
  repo.git.fetch
20
20
  repo.git.hard_checkout(opts[:ref])
21
21
  repo.chdir do
22
- puts "+ #{opts[:command]}".light_black
23
- system(opts[:command])
22
+ Bundler.with_unbundled_env do
23
+ puts "+ #{opts[:command]}".light_black
24
+ system(opts[:command])
25
+ end
24
26
  end
25
27
  end
@@ -14,12 +14,25 @@ opts = Optimist.options do
14
14
  opt :base, "The target branch for the changes.", :type => :string, :required => true
15
15
  opt :head, "The name of the branch to create on your fork.", :type => :string, :required => true
16
16
  opt :script, "The path to the script that will update the desired files.", :type => :string, :required => true
17
- opt :message, "The commit message for this change.", :type => :string, :required => true
18
- opt :title, "The PR title for this change. (default is --message)", :type => :string
17
+ opt :force, "Force creation of the pull request without asking.", :default => false
19
18
 
20
- opt :force, "Force creation of the pull request without asking.", :default => false
19
+ see_below = "See \"Notes on commit messages\" section below."
20
+ opt :message, "The commit message for this change. #{see_below}", :type => :string, :required => true
21
+ opt :title, "The PR title for this change. #{see_below}", :type => :string
22
+ opt :body, "The PR body for this change. #{see_below}", :type => :string
21
23
 
22
24
  MultiRepo::CLI.common_options(self)
25
+ opt :help, "Show this message" # Ensure help appears above the notes sections
26
+
27
+ banner ""
28
+ banner <<~EOS
29
+ Notes on commit messages:
30
+ * The --message and --body options can accept '\\n' characters to support multiline messages.
31
+ * In a script, you can override --message by writing the commit message contents to .git/COMMIT_EDITMSG.
32
+ * The --title will default to the first line of the message.
33
+ * The --body will default to the rest of the message.
34
+ * If you want to override the title or body, you can do so with the --title and --body options, respectively.
35
+ EOS
23
36
  end
24
37
 
25
38
  results = {}
@@ -7,14 +7,15 @@ gemfile do
7
7
  end
8
8
  require "active_support/core_ext/object/blank"
9
9
  require "active_support/core_ext/string/inflections"
10
+ require "more_core_extensions/core_ext/hash/deletes"
10
11
 
11
- DISPLAY_FORMATS = %w[commit pr-title pr-label]
12
+ DISPLAY_FORMATS = %w[commit pr-title pr-label pr-changelog]
12
13
 
13
14
  opts = Optimist.options do
14
15
  synopsis "Show the git commit log between two refs for all git repos."
15
16
 
16
17
  opt :from, "The commit log 'from' ref", :type => :string, :required => true
17
- opt :to, "The commit log 'to' ref" , :type => :string, :required => true
18
+ opt :to, "The commit log 'to' ref", :type => :string, :required => true
18
19
  opt :display, "How to display the history. Valid values are: #{DISPLAY_FORMATS.join(", ")}", :default => "commit"
19
20
  opt :summary, "Display a summary of the repos.", :default => false
20
21
 
@@ -33,30 +34,32 @@ repos_with_changes = []
33
34
  MultiRepo::CLI.repos_for(**opts).each do |repo|
34
35
  next if opts[:skip].include?(repo.name)
35
36
 
36
- puts MultiRepo::CLI.header(repo.name)
37
+ puts MultiRepo::CLI.header(repo.name) unless opts[:display] == "pr-changelog"
37
38
  repo.git.fetch(output: false)
38
39
 
39
40
  case opts[:display]
40
- when "pr-label", "pr-title"
41
+ when "pr-label", "pr-title", "pr-changelog"
41
42
  github ||= MultiRepo::Service::Github.client
42
- pr_label_display = opts[:display] == "pr-label"
43
43
 
44
44
  results = {}
45
- if pr_label_display
46
- results["bug"] = []
47
- results["enhancement"] = []
45
+ if %w[pr-label pr-changelog].include?(opts[:display])
46
+ results["bug"] = Set.new
47
+ results["enhancement"] = Set.new
48
48
  end
49
- results["other"] = []
49
+ results["other"] = Set.new
50
50
 
51
51
  log =
52
52
  begin
53
53
  repo.git.client.capturing.log({:oneline => true}, range)
54
54
  rescue MiniGit::GitError
55
- puts "ERROR: commit range not found.".light_red
56
- puts
55
+ unless opts[:display] == "pr-changelog"
56
+ puts "ERROR: commit range not found.".light_red
57
+ puts
58
+ end
57
59
  next
58
60
  end
59
61
 
62
+ pr_index = {}
60
63
  log.lines.each do |line|
61
64
  next unless (match = line.match(/Merge pull request #(\d+)\b/))
62
65
 
@@ -66,23 +69,31 @@ MultiRepo::CLI.repos_for(**opts).each do |repo|
66
69
  rescue Octokit::NotFound
67
70
  next # PR not found could mean this was a cherry-pick from a different repo, so the PR doesn't exist.
68
71
  end
72
+
73
+ pr_index[pr.number] = pr
69
74
  label = pr.labels.detect { |l| results.key?(l.name) }&.name || "other"
70
- results[label] << pr
75
+ results[label] << pr.number
71
76
  end
77
+ results.delete_blanks
72
78
 
73
- changes_found = false
74
-
75
- results.each do |label, prs|
76
- next if prs.blank?
77
- changes_found = true
79
+ if results.present? && opts[:display] == "pr-changelog"
80
+ puts "\n## <i class=\"fa-brands fa-github\"></i> [#{repo.name}](https://github.com/#{repo.name}/compare/#{opts[:from]}...#{opts[:to]})"
81
+ end
78
82
 
79
- puts "\n## #{label.titleize}\n\n" if pr_label_display
80
- prs.each do |pr|
83
+ results.each do |label, pr_numbers|
84
+ case opts[:display]
85
+ when "pr-label"
86
+ puts "\n## #{label.titleize}\n\n"
87
+ when "pr-changelog"
88
+ puts "\n### #{label.titleize}\n\n"
89
+ end
90
+ pr_numbers.each do |pr_number|
91
+ pr = pr_index[pr_number]
81
92
  puts "* #{pr.title} [[##{pr.number}]](#{pr.html_url})"
82
93
  end
83
94
  end
84
95
 
85
- repos_with_changes << repo if changes_found
96
+ repos_with_changes << repo if results.present?
86
97
  when "commit"
87
98
  output =
88
99
  begin
@@ -10,6 +10,9 @@ opts = Optimist.options do
10
10
  synopsis "List all repos in an org."
11
11
 
12
12
  opt :org, "The org to list the repos for", :type => :string, :required => true
13
+
14
+ opt :include_forks, "Include forked repos", :default => false
15
+ opt :include_archived, "Include archived repos", :default => false
13
16
  end
14
17
 
15
- puts MultiRepo::Service::Github.org_repo_names(opts[:org])
18
+ puts MultiRepo::Service::Github.org_repo_names(opts[:org], **opts.slice(:include_forks, :include_archived))
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: 1.0.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ManageIQ Authors
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-04-24 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -58,14 +57,14 @@ dependencies:
58
57
  requirements:
59
58
  - - ">="
60
59
  - !ruby/object:Gem::Version
61
- version: '0'
60
+ version: 9.7.0
62
61
  type: :runtime
63
62
  prerelease: false
64
63
  version_requirements: !ruby/object:Gem::Requirement
65
64
  requirements:
66
65
  - - ">="
67
66
  - !ruby/object:Gem::Version
68
- version: '0'
67
+ version: 9.7.0
69
68
  - !ruby/object:Gem::Dependency
70
69
  name: minigit
71
70
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +197,14 @@ dependencies:
198
197
  requirements:
199
198
  - - ">="
200
199
  - !ruby/object:Gem::Version
201
- version: 1.5.4
200
+ version: '0'
202
201
  type: :development
203
202
  prerelease: false
204
203
  version_requirements: !ruby/object:Gem::Requirement
205
204
  requirements:
206
205
  - - ">="
207
206
  - !ruby/object:Gem::Version
208
- version: 1.5.4
207
+ version: '0'
209
208
  - !ruby/object:Gem::Dependency
210
209
  name: rake
211
210
  requirement: !ruby/object:Gem::Requirement
@@ -257,12 +256,10 @@ executables:
257
256
  extensions: []
258
257
  extra_rdoc_files: []
259
258
  files:
260
- - ".codeclimate.yml"
261
259
  - ".github/workflows/ci.yaml"
262
260
  - ".gitignore"
263
261
  - ".rspec"
264
262
  - ".rubocop.yml"
265
- - ".rubocop_cc.yml"
266
263
  - ".rubocop_local.yml"
267
264
  - ".whitesource"
268
265
  - CHANGELOG.md
@@ -287,7 +284,6 @@ files:
287
284
  - lib/multi_repo/repo.rb
288
285
  - lib/multi_repo/repo_set.rb
289
286
  - lib/multi_repo/service/artifactory.rb
290
- - lib/multi_repo/service/code_climate.rb
291
287
  - lib/multi_repo/service/docker.rb
292
288
  - lib/multi_repo/service/git.rb
293
289
  - lib/multi_repo/service/git/minigit_capturing_patch.rb
@@ -330,7 +326,6 @@ homepage: http://github.com/ManageIQ/multi_repo
330
326
  licenses:
331
327
  - MIT
332
328
  metadata: {}
333
- post_install_message:
334
329
  rdoc_options: []
335
330
  require_paths:
336
331
  - lib
@@ -345,8 +340,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
345
340
  - !ruby/object:Gem::Version
346
341
  version: '0'
347
342
  requirements: []
348
- rubygems_version: 3.5.22
349
- signing_key:
343
+ rubygems_version: 4.0.7
350
344
  specification_version: 4
351
345
  summary: MultiRepo is a library for managing multiple repositiories and running scripts
352
346
  against them.
data/.codeclimate.yml DELETED
@@ -1,16 +0,0 @@
1
- prepare:
2
- fetch:
3
- - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_base.yml
4
- path: ".rubocop_base.yml"
5
- - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/.rubocop_cc_base.yml
6
- path: ".rubocop_cc_base.yml"
7
- - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/base.yml
8
- path: styles/base.yml
9
- - url: https://raw.githubusercontent.com/ManageIQ/manageiq-style/master/styles/cc_base.yml
10
- path: styles/cc_base.yml
11
- plugins:
12
- rubocop:
13
- enabled: true
14
- config: ".rubocop_cc.yml"
15
- channel: rubocop-1-56-3
16
- version: '2'
data/.rubocop_cc.yml DELETED
@@ -1,4 +0,0 @@
1
- inherit_from:
2
- - ".rubocop_base.yml"
3
- - ".rubocop_cc_base.yml"
4
- - ".rubocop_local.yml"
@@ -1,119 +0,0 @@
1
- module MultiRepo::Service
2
- class CodeClimate
3
- def self.api_token
4
- @api_token ||= ENV["CODECLIMATE_API_TOKEN"]
5
- end
6
-
7
- def self.api_token=(token)
8
- @api_token = token
9
- end
10
-
11
- def self.badge_name
12
- "Code Climate"
13
- end
14
-
15
- def self.badge_details(repo)
16
- {
17
- "description" => badge_name,
18
- "image" => "https://codeclimate.com/github/#{repo.name}.svg",
19
- "url" => "https://codeclimate.com/github/#{repo.name}"
20
- }
21
- end
22
-
23
- def self.coverage_badge_name
24
- "Test Coverage"
25
- end
26
-
27
- def self.coverage_badge_details(repo)
28
- {
29
- "description" => coverage_badge_name,
30
- "image" => "https://codeclimate.com/github/#{repo.name}/badges/coverage.svg",
31
- "url" => "https://codeclimate.com/github/#{repo.name}/coverage"
32
- }
33
- end
34
-
35
- attr_reader :repo, :dry_run
36
-
37
- def initialize(repo, dry_run: false, **_)
38
- @repo = repo
39
- @dry_run = dry_run
40
- end
41
-
42
- def save!
43
- write_codeclimate_yaml
44
- write_rubocop_yamls
45
- end
46
-
47
- def enable
48
- ensure_enabled
49
- end
50
-
51
- def badge_details
52
- self.class.badge_details(repo)
53
- end
54
-
55
- def coverage_badge_details
56
- self.class.coverage_badge_details(repo)
57
- end
58
-
59
- def test_reporter_id
60
- ensure_enabled
61
- @response.dig("data", 0, "attributes", "test_reporter_id")
62
- end
63
-
64
- def create_repo_secret
65
- Github.new(dry_run: dry_run).create_or_update_repository_secret(repo.name, "CC_TEST_REPORTER_ID", test_reporter_id)
66
- end
67
-
68
- private
69
-
70
- def ensure_enabled
71
- return if @enabled
72
-
73
- require 'rest-client'
74
- require 'json'
75
-
76
- @response =
77
- if dry_run
78
- puts "** dry-run: RestClient.get(\"https://api.codeclimate.com/v1/repos?github_slug=#{repo.name}\", #{headers})".light_black
79
- {"data" => [{"attributes" => {"badge_token" => "0123456789abdef01234", "test_reporter_id" => "0123456789abcedef0123456789abcedef0123456789abcedef0123456789abc"}}]}
80
- else
81
- JSON.parse(RestClient.get("https://api.codeclimate.com/v1/repos?github_slug=#{repo.name}", headers))
82
- end
83
-
84
- if @response["data"].empty?
85
- payload = {"data" => {"type" => "repos", "attributes" => {"url" => "https://github.com/#{repo.name}"}}}.to_json
86
- @response = JSON.parse(RestClient.post("https://api.codeclimate.com/v1/github/repos", payload, headers))
87
- @response["data"] = [@response["data"]]
88
- end
89
-
90
- @enabled = true
91
- end
92
-
93
- def headers
94
- token = self.class.api_token
95
- raise "Missing CodeClimate API Token" if token.nil?
96
-
97
- {
98
- :accept => "application/vnd.api+json",
99
- :content_type => "application/vnd.api+json",
100
- :authorization => "Token token=#{token}"
101
- }
102
- end
103
-
104
- def write_codeclimate_yaml
105
- write_generator_file(".codeclimate.yml")
106
- end
107
-
108
- def write_rubocop_yamls
109
- %w[.rubocop.yml .rubocop_cc.yml .rubocop_local.yml].each do |file|
110
- write_generator_file(file)
111
- end
112
- end
113
-
114
- def write_generator_file(file)
115
- content = RestClient.get("https://raw.githubusercontent.com/ManageIQ/manageiq/master/lib/generators/manageiq/plugin/templates/#{file}").body
116
- repo.write_file(file, content, dry_run: dry_run)
117
- end
118
- end
119
- end