multi_repo 0.1.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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +16 -0
  3. data/.github/workflows/ci.yaml +32 -0
  4. data/.gitignore +6 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +4 -0
  7. data/.rubocop_cc.yml +4 -0
  8. data/.rubocop_local.yml +0 -0
  9. data/.whitesource +3 -0
  10. data/Gemfile +6 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +90 -0
  13. data/Rakefile +6 -0
  14. data/bin/console +8 -0
  15. data/exe/multi_repo +29 -0
  16. data/lib/multi_repo/cli.rb +92 -0
  17. data/lib/multi_repo/helpers/git_mirror.rb +198 -0
  18. data/lib/multi_repo/helpers/license.rb +106 -0
  19. data/lib/multi_repo/helpers/pull_request_blaster_outer.rb +129 -0
  20. data/lib/multi_repo/helpers/readme_badges.rb +84 -0
  21. data/lib/multi_repo/helpers/rename_labels.rb +26 -0
  22. data/lib/multi_repo/helpers/update_branch_protection.rb +24 -0
  23. data/lib/multi_repo/helpers/update_labels.rb +34 -0
  24. data/lib/multi_repo/helpers/update_milestone.rb +33 -0
  25. data/lib/multi_repo/helpers/update_repo_settings.rb +23 -0
  26. data/lib/multi_repo/labels.rb +31 -0
  27. data/lib/multi_repo/repo.rb +56 -0
  28. data/lib/multi_repo/repo_set.rb +27 -0
  29. data/lib/multi_repo/service/artifactory.rb +122 -0
  30. data/lib/multi_repo/service/code_climate.rb +119 -0
  31. data/lib/multi_repo/service/docker.rb +178 -0
  32. data/lib/multi_repo/service/git/minigit_capturing_patch.rb +12 -0
  33. data/lib/multi_repo/service/git.rb +90 -0
  34. data/lib/multi_repo/service/github.rb +238 -0
  35. data/lib/multi_repo/service/rubygems_stub.rb +103 -0
  36. data/lib/multi_repo/service/travis.rb +68 -0
  37. data/lib/multi_repo/version.rb +3 -0
  38. data/lib/multi_repo.rb +44 -0
  39. data/multi_repo.gemspec +44 -0
  40. data/repos/.gitkeep +0 -0
  41. data/scripts/delete_labels +23 -0
  42. data/scripts/destroy_branch +23 -0
  43. data/scripts/destroy_remote +26 -0
  44. data/scripts/destroy_tag +31 -0
  45. data/scripts/each_repo +23 -0
  46. data/scripts/fetch_repos +18 -0
  47. data/scripts/git_mirror +9 -0
  48. data/scripts/github_rate_limit +10 -0
  49. data/scripts/hacktoberfest +138 -0
  50. data/scripts/make_alumni +50 -0
  51. data/scripts/new_rubygems_stub +17 -0
  52. data/scripts/pull_request_blaster_outer +24 -0
  53. data/scripts/pull_request_labeler +59 -0
  54. data/scripts/pull_request_merger +63 -0
  55. data/scripts/reenable_repo_workflows +33 -0
  56. data/scripts/rename_labels +22 -0
  57. data/scripts/restart_travis_builds +31 -0
  58. data/scripts/show_commit_history +86 -0
  59. data/scripts/show_org_members +19 -0
  60. data/scripts/show_org_repos +13 -0
  61. data/scripts/show_org_stats +82 -0
  62. data/scripts/show_project_cards +35 -0
  63. data/scripts/show_repo_set +13 -0
  64. data/scripts/show_tag +33 -0
  65. data/scripts/show_travis_status +63 -0
  66. data/scripts/update_branch_protection +22 -0
  67. data/scripts/update_labels +16 -0
  68. data/scripts/update_milestone +21 -0
  69. data/scripts/update_repo_settings +15 -0
  70. metadata +366 -0
@@ -0,0 +1,103 @@
1
+ module MultiRepo::Service
2
+ class RubygemsStub
3
+ attr_reader :repo, :owners, :dry_run
4
+
5
+ def initialize(repo, owners: [], dry_run: false, **_)
6
+ @repo = repo
7
+ @owners = owners
8
+ @dry_run = dry_run
9
+ end
10
+
11
+ def run
12
+ if stub_exists?
13
+ puts "A stub gem for #{repo.inspect} already exists."
14
+ return
15
+ end
16
+
17
+ if gem_exists?
18
+ puts "A gem for #{repo.inspect} already exists with the following versions:"
19
+ puts " #{gem_versions}"
20
+ puts
21
+ loop do
22
+ print "Would you still like to create a stub? (y/N) "
23
+ answer = gets.chomp.downcase[0] || "n"
24
+ break if answer == "y"
25
+ return if answer == "n"
26
+ end
27
+ puts
28
+ end
29
+
30
+ Dir.mktmpdir do |dir|
31
+ package = create_gem(dir)
32
+ push_gem(package)
33
+
34
+ owners.each do |o|
35
+ set_gem_owner(o)
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def stub_exists?
43
+ gem_versions.include?("0.0.1")
44
+ end
45
+
46
+ def gem_exists?
47
+ gem_string.presence
48
+ end
49
+
50
+ # Returns a gem's versions as listed by gem list
51
+ #
52
+ # Example (where @repo is the "foo" gem):
53
+ # # => ["2.1.0", "2.0.0", "1.1.0", "1.0.0"]
54
+ def gem_versions
55
+ gem_string.split(" ", 2).last.to_s[1..-2].to_s.split(", ")
56
+ end
57
+
58
+ # Returns a gem string as listed by gem list
59
+ #
60
+ # Example (where @repo is the "foo" gem):
61
+ # # => "foo (2.1.0, 2.0.0, 1.1.0, 1.0.0)"
62
+ def gem_string
63
+ @gem_string ||= `gem list #{repo} --exact --remote --all`.chomp.split("\n").last.to_s
64
+ end
65
+
66
+ def create_gem(dir)
67
+ path = File.join(dir, "#{repo}.gemspec")
68
+ File.write(path , <<~RUBY)
69
+ Gem::Specification.new do |s|
70
+ s.name = "#{repo}"
71
+ s.version = "0.0.1"
72
+ s.licenses = ["Apache-2.0"]
73
+ s.summary = "#{repo}"
74
+ s.description = s.summary
75
+ s.authors = ["ManageIQ Authors"]
76
+ s.homepage = "https://github.com/ManageIQ/#{repo}"
77
+ s.metadata = { "source_code_uri" => s.homepage }
78
+ end
79
+ RUBY
80
+
81
+ system("gem build #{path}", :chdir => dir)
82
+
83
+ File.join(dir, "#{repo}-0.0.1.gem")
84
+ end
85
+
86
+ def push_gem(package)
87
+ if dry_run
88
+ raise "#{package} not found" unless File.file?(package)
89
+ puts "** dry-run: gem push #{package}".light_black
90
+ else
91
+ system("gem push #{package}")
92
+ end
93
+ end
94
+
95
+ def set_gem_owner(owner)
96
+ if dry_run
97
+ puts "** dry-run: gem owner #{repo} --add #{owner}".light_black
98
+ else
99
+ system("gem owner #{repo} --add #{owner}")
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,68 @@
1
+ require 'yaml'
2
+
3
+ module MultiRepo::Service
4
+ class Travis
5
+ def self.api_token
6
+ @api_token ||= ENV["TRAVIS_API_TOKEN"]
7
+ end
8
+
9
+ def self.api_token=(token)
10
+ @api_token = token
11
+ end
12
+
13
+ def self.client
14
+ @client ||= begin
15
+ raise "Missing Travis API Token" if travis_api_token.nil?
16
+
17
+ require 'travis/client'
18
+ ::Travis::Client.new(
19
+ :uri => ::Travis::Client::COM_URI,
20
+ :access_token => api_token
21
+ )
22
+ end
23
+ end
24
+
25
+ def self.badge_name
26
+ "Build Status"
27
+ end
28
+
29
+ def self.badge_details(repo, branch)
30
+ {
31
+ "description" => badge_name,
32
+ "image" => "https://travis-ci.com/#{repo.name}.svg?branch=#{branch}",
33
+ "url" => "https://travis-ci.com/#{repo.name}"
34
+ }
35
+ end
36
+
37
+ attr_reader :repo, :dry_run
38
+
39
+ def initialize(repo, dry_run: false, **_)
40
+ @repo = repo
41
+ @dry_run = dry_run
42
+ end
43
+
44
+ def badge_details
45
+ self.class.badge_details(repo, "master")
46
+ end
47
+
48
+ def enable
49
+ if dry_run
50
+ puts "** dry-run: travis login --com --github-token $GITHUB_API_TOKEN".light_black
51
+ puts "** dry-run: travis enable --com".light_black
52
+ else
53
+ `travis login --com --github-token $GITHUB_API_TOKEN`
54
+ `travis enable --com`
55
+ end
56
+ end
57
+
58
+ def set_env(hash)
59
+ hash.each do |key, value|
60
+ if dry_run
61
+ puts "** dry-run: travis env set #{key} #{value}".light_black
62
+ else
63
+ `travis env set #{key} #{value}`
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,3 @@
1
+ module MultiRepo
2
+ VERSION = "0.1.0"
3
+ end
data/lib/multi_repo.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'pathname'
2
+ require 'pp'
3
+
4
+ require 'multi_repo/version'
5
+
6
+ require 'multi_repo/labels'
7
+ require 'multi_repo/repo'
8
+ require 'multi_repo/repo_set'
9
+
10
+ require 'multi_repo/service/artifactory'
11
+ require 'multi_repo/service/code_climate'
12
+ require 'multi_repo/service/docker'
13
+ require 'multi_repo/service/git'
14
+ require 'multi_repo/service/github'
15
+ require 'multi_repo/service/rubygems_stub'
16
+ require 'multi_repo/service/travis'
17
+
18
+ require 'multi_repo/helpers/git_mirror'
19
+ require 'multi_repo/helpers/license'
20
+ require 'multi_repo/helpers/pull_request_blaster_outer'
21
+ require 'multi_repo/helpers/readme_badges'
22
+ require 'multi_repo/helpers/rename_labels'
23
+ require 'multi_repo/helpers/update_branch_protection'
24
+ require 'multi_repo/helpers/update_labels'
25
+ require 'multi_repo/helpers/update_milestone'
26
+ require 'multi_repo/helpers/update_repo_settings'
27
+
28
+ module MultiRepo
29
+ def self.root_dir
30
+ @root_dir ||= Pathname.new(Dir.pwd).expand_path
31
+ end
32
+
33
+ def self.root_dir=(dir)
34
+ @root_dir = Pathname.new(dir).expand_path
35
+ end
36
+
37
+ def self.config_dir
38
+ @config_dir ||= root_dir.join("config")
39
+ end
40
+
41
+ def self.repos_dir
42
+ @repos_dir ||= root_dir.join("repos")
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multi_repo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "multi_repo"
8
+ spec.version = MultiRepo::VERSION
9
+ spec.authors = ["ManageIQ Authors"]
10
+ spec.email = ["contact@manageiq.org"]
11
+ spec.description = %q{MultiRepo is a library for managing multiple repositiories and running scripts against them.}
12
+ spec.summary = spec.description
13
+ spec.homepage = "http://github.com/ManageIQ/multi_repo"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.required_ruby_version = ">= 2.7.0"
24
+
25
+ spec.add_runtime_dependency "activesupport"
26
+ spec.add_runtime_dependency "colorize"
27
+ spec.add_runtime_dependency "config"
28
+ spec.add_runtime_dependency "licensee"
29
+ spec.add_runtime_dependency "minigit"
30
+ spec.add_runtime_dependency "more_core_extensions"
31
+ spec.add_runtime_dependency "octokit", ">=4.23.0"
32
+ spec.add_runtime_dependency "optimist"
33
+ spec.add_runtime_dependency "progressbar"
34
+ spec.add_runtime_dependency "psych", ">=3"
35
+ spec.add_runtime_dependency "rbnacl"
36
+ spec.add_runtime_dependency "rest-client"
37
+ spec.add_runtime_dependency "travis"
38
+
39
+ spec.add_development_dependency "bundler"
40
+ spec.add_development_dependency "manageiq-style"
41
+ spec.add_development_dependency "rake"
42
+ spec.add_development_dependency "rspec", ">= 3.0"
43
+ spec.add_development_dependency "simplecov", ">= 0.21.2"
44
+ end
data/repos/.gitkeep ADDED
File without changes
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :labels, "The labels to delete.", :type => :strings, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self, :repo_set_default => nil)
13
+ end
14
+ opts[:repo] = MultiRepo::Helpers::Labels.all.keys.sort unless opts[:repo] || opts[:repo_set]
15
+
16
+ github = MultiRepo::Service::Github.new(dry_run: opts[:dry_run])
17
+
18
+ MultiRepo::CLI.each_repo(**opts) do |repo|
19
+ opts[:labels].each do |label|
20
+ puts "Deleting #{label.inspect}"
21
+ github.delete_label!(repo.name, label)
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :branch, "The branch to destroy.", :type => :string, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
13
+ end
14
+
15
+ MultiRepo::CLI.each_repo(**opts) do |repo|
16
+ unless repo.git.branch?(opts[:branch])
17
+ puts "!! Skipping because #{opts[:branch]} branch doesn't exist".yellow
18
+ next
19
+ end
20
+
21
+ repo.git.client.checkout("master")
22
+ repo.git.client.branch("-D", opts[:branch])
23
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :remote, "The remote to destroy", :type => :string, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self)
13
+ end
14
+
15
+ MultiRepo::CLI.each_repo(**opts) do |repo|
16
+ unless repo.git.remote?(opts[:remote])
17
+ puts "!! Skipping because #{opts[:remote]} remote doesn't exist".yellow
18
+ next
19
+ end
20
+
21
+ if opts[:dry_run]
22
+ puts "** dry-run: git remote rm #{opts[:remote]}".light_black
23
+ else
24
+ repo.git.client.remote("rm", opts[:remote])
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :tag, "The tag to destroy", :type => :string, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
13
+ end
14
+
15
+ require "stringio"
16
+ post_review = StringIO.new
17
+
18
+ MultiRepo::CLI.each_repo(**opts) do |repo|
19
+ unless repo.git.tag?(opts[:tag])
20
+ puts "!! Skipping because #{opts[:tag]} tag doesn't exist".yellow
21
+ next
22
+ end
23
+
24
+ repo.git.client.tag("-d", opts[:tag])
25
+ post_review.puts("pushd #{repo.path} && git push origin :#{opts[:tag]} && popd")
26
+ end
27
+
28
+ puts
29
+ puts "Run the following script to delete '#{opts[:tag]}' tag from all remote repos"
30
+ puts
31
+ puts post_review.string
data/scripts/each_repo ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :command, "A command to run in each repo", :type => :string, :required => true
11
+ opt :ref, "Ref to checkout before running the command", :type => :string, :default => "master"
12
+
13
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
14
+ end
15
+
16
+ MultiRepo::CLI.each_repo(**opts) do |repo|
17
+ repo.git.fetch
18
+ repo.git.hard_checkout(opts[:ref])
19
+ repo.chdir do
20
+ puts "+ #{opts[:command]}".light_black
21
+ system(opts[:command])
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :checkout, "Branch to checkout after fetching.", :type => :string
11
+
12
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
13
+ end
14
+
15
+ MultiRepo::CLI.each_repo(**opts) do |repo|
16
+ repo.git.fetch
17
+ repo.git.hard_checkout(opts[:checkout]) if opts[:checkout]
18
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ exit 1 unless MultiRepo::Helpers::GitMirror.new.mirror_all
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+ require "more_core_extensions/core_ext/array/tableize"
9
+
10
+ puts [MultiRepo::Service::Github.client.rate_limit.to_h].tableize
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :org, "The organization to apply the `hacktoberfest` label to", :type => :string, :required => true
11
+ opt :apply, "Apply the `hacktoberfest` label to `good first issue` labels. "\
12
+ "Pass --no-apply to remove the `hacktoberfest` label",
13
+ :type => :boolean, :default => true
14
+
15
+ MultiRepo::CLI.common_options(self, :only => :dry_run)
16
+ end
17
+
18
+ class MultiRepo::Hacktoberfest
19
+ attr_reader :org, :apply, :dry_run
20
+
21
+ def initialize(org:, apply:, dry_run: false, **_)
22
+ @org = org
23
+ @apply = apply
24
+ @dry_run = dry_run
25
+ end
26
+
27
+ def run
28
+ if apply
29
+ add_hacktoberfest_topics
30
+ good_first_issues.each { |issue| add_hacktoberfest_label(issue) }
31
+ else
32
+ remove_hacktoberfest_topics
33
+ hacktoberfest_issues.each { |issue| remove_hacktoberfest_label(issue) }
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def good_first_issues
40
+ sorted_issues("org:#{org} archived:false is:open label:\"good first issue\" -label:hacktoberfest")
41
+ end
42
+
43
+ def hacktoberfest_issues
44
+ sorted_issues("org:#{org} archived:false is:open label:hacktoberfest")
45
+ end
46
+
47
+ def sorted_issues(query)
48
+ github.client.search_issues(query).items.sort_by { |issue| issue_id(issue) }
49
+ end
50
+
51
+ def add_hacktoberfest_label(issue)
52
+ labels = ["hacktoberfest"]
53
+ repo, number = issue_id(issue)
54
+ puts "Adding #{labels.first.inspect} label to issue #{repo}##{number}"
55
+
56
+ if dry_run
57
+ puts "** dry-run: github.add_labels_to_an_issue(#{repo.inspect}, #{number.inspect}, #{labels.inspect})".light_black
58
+ else
59
+ github.client.add_labels_to_an_issue(repo, number, labels)
60
+ end
61
+ end
62
+
63
+ def remove_hacktoberfest_label(issue)
64
+ label = "hacktoberfest"
65
+ repo, number = issue_id(issue)
66
+ puts "Removing #{label.inspect} label from issue #{repo}##{number}"
67
+
68
+ if dry_run
69
+ puts "** dry-run: github.remove_label(#{repo.inspect}, #{number.inspect}, #{label.inspect})".light_black
70
+ else
71
+ github.client.remove_label(repo, number, label)
72
+ end
73
+ end
74
+
75
+ def add_hacktoberfest_topics
76
+ org_repos.each do |repo|
77
+ add_hacktoberfest_topic(repo)
78
+ end
79
+ end
80
+
81
+ def remove_hacktoberfest_topics
82
+ org_repos.each do |repo|
83
+ remove_hacktoberfest_topic(repo)
84
+ end
85
+ end
86
+
87
+ def add_hacktoberfest_topic(repo)
88
+ topic = "hacktoberfest"
89
+ topics = topic_names(repo)
90
+ return if topics.include?(topic)
91
+
92
+ puts "Adding #{topic.inspect} topic to repo #{repo}"
93
+
94
+ topics << topic
95
+ if dry_run
96
+ puts "** dry-run: github.replace_all_topics(#{repo.inspect}, #{topics.inspect})".light_black
97
+ else
98
+ github.client.replace_all_topics(repo, topics, :accept => "application/vnd.github.mercy-preview+json")
99
+ end
100
+ end
101
+
102
+ def remove_hacktoberfest_topic(repo)
103
+ topic = "hacktoberfest"
104
+ topics = topic_names(repo)
105
+ return unless topics.include?(topic)
106
+
107
+ puts "Removing #{topic.inspect} topic from repo #{repo}"
108
+
109
+ topics.delete(topic)
110
+ if dry_run
111
+ puts "** dry-run: github.replace_all_topics(#{repo.inspect}, #{topics.inspect})".light_black
112
+ else
113
+ github.client.replace_all_topics(repo, topics, :accept => "application/vnd.github.mercy-preview+json")
114
+ end
115
+ end
116
+
117
+ def issue_id(issue)
118
+ [issue_repo(issue), issue.number]
119
+ end
120
+
121
+ def issue_repo(issue)
122
+ issue.repository_url.split("/").last(2).join("/")
123
+ end
124
+
125
+ def topic_names(repo)
126
+ github.client.topics(repo, :accept => "application/vnd.github.mercy-preview+json")[:names]
127
+ end
128
+
129
+ def org_repos
130
+ github.org_repo_names(org)
131
+ end
132
+
133
+ def github
134
+ @github ||= MultiRepo::Service::Github.new(dry_run: dry_run)
135
+ end
136
+ end
137
+
138
+ MultiRepo::Hacktoberfest.new(**opts).run
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :users, "The users to make alumni.", :type => :strings, :required => true
11
+ opt :org, "The org in which user belongs", :type => :string, :required => true
12
+
13
+ MultiRepo::CLI.common_options(self, :only => :dry_run)
14
+ end
15
+
16
+ class MultiRepo::MakeAlumni
17
+ attr_reader :org, :dry_run
18
+
19
+ def initialize(org:, dry_run:, **_)
20
+ @org = org
21
+ @dry_run = dry_run
22
+ @github = MultiRepo::Service::Github.new(dry_run: dry_run)
23
+ end
24
+
25
+ def run(user)
26
+ progress = MultiRepo.progress_bar(teams.size + repos.size)
27
+
28
+ github.add_team_membership(org, "alumni", user)
29
+ progress.increment
30
+
31
+ non_alumni_teams = github.team_names(org) - ["alumni"]
32
+ non_alumni_teams.each do |team|
33
+ github.remove_team_membership(org, team, user)
34
+ progress.increment
35
+ end
36
+
37
+ repos.each do |repo|
38
+ github.remove_collaborator(repo, user)
39
+ progress.increment
40
+ end
41
+
42
+ progress.finish
43
+ end
44
+ end
45
+
46
+ make_alumni = MultiRepo::MakeAlumni.new(**opts)
47
+ opts[:users].each do |user|
48
+ puts MultiRepo::CLI.header(user)
49
+ make_alumni.run(user)
50
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :owners, "Owners to add to the gem stub", :type => :strings, :default => []
11
+
12
+ MultiRepo::CLI.common_options(self, :except => :repo_set)
13
+ end
14
+
15
+ MultiRepo::CLI.each_repo(**opts) do |repo|
16
+ MultiRepo::Service::RubygemsStub.new(repo.name, **opts).run
17
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/inline"
4
+ gemfile do
5
+ source "https://rubygems.org"
6
+ gem "multi_repo", require: "multi_repo/cli", path: File.expand_path("..", __dir__)
7
+ end
8
+
9
+ opts = Optimist.options do
10
+ opt :base, "The target branch for the changes.", :type => :string, :required => true
11
+ opt :head, "The name of the branch to create on your fork.", :type => :string, :required => true
12
+ opt :script, "The path to the script that will update the desired files.", :type => :string, :required => true
13
+ opt :message, "The commit message for this change.", :type => :string, :required => true
14
+ opt :title, "The PR title for this change. (default is --message)", :type => :string
15
+
16
+ MultiRepo::CLI.common_options(self)
17
+ end
18
+
19
+ results = {}
20
+ MultiRepo::CLI.each_repo(**opts) do |repo|
21
+ results[repo.name] = MultiRepo::Helpers::PullRequestBlasterOuter.new(repo, **opts).blast
22
+ end
23
+
24
+ pp results