multi_repo 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +16 -0
- data/.github/workflows/ci.yaml +32 -0
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_cc.yml +4 -0
- data/.rubocop_local.yml +0 -0
- data/.whitesource +3 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +90 -0
- data/Rakefile +6 -0
- data/bin/console +8 -0
- data/exe/multi_repo +29 -0
- data/lib/multi_repo/cli.rb +92 -0
- data/lib/multi_repo/helpers/git_mirror.rb +198 -0
- data/lib/multi_repo/helpers/license.rb +106 -0
- data/lib/multi_repo/helpers/pull_request_blaster_outer.rb +129 -0
- data/lib/multi_repo/helpers/readme_badges.rb +84 -0
- data/lib/multi_repo/helpers/rename_labels.rb +26 -0
- data/lib/multi_repo/helpers/update_branch_protection.rb +24 -0
- data/lib/multi_repo/helpers/update_labels.rb +34 -0
- data/lib/multi_repo/helpers/update_milestone.rb +33 -0
- data/lib/multi_repo/helpers/update_repo_settings.rb +23 -0
- data/lib/multi_repo/labels.rb +31 -0
- data/lib/multi_repo/repo.rb +56 -0
- data/lib/multi_repo/repo_set.rb +27 -0
- data/lib/multi_repo/service/artifactory.rb +122 -0
- data/lib/multi_repo/service/code_climate.rb +119 -0
- data/lib/multi_repo/service/docker.rb +178 -0
- data/lib/multi_repo/service/git/minigit_capturing_patch.rb +12 -0
- data/lib/multi_repo/service/git.rb +90 -0
- data/lib/multi_repo/service/github.rb +238 -0
- data/lib/multi_repo/service/rubygems_stub.rb +103 -0
- data/lib/multi_repo/service/travis.rb +68 -0
- data/lib/multi_repo/version.rb +3 -0
- data/lib/multi_repo.rb +44 -0
- data/multi_repo.gemspec +44 -0
- data/repos/.gitkeep +0 -0
- data/scripts/delete_labels +23 -0
- data/scripts/destroy_branch +23 -0
- data/scripts/destroy_remote +26 -0
- data/scripts/destroy_tag +31 -0
- data/scripts/each_repo +23 -0
- data/scripts/fetch_repos +18 -0
- data/scripts/git_mirror +9 -0
- data/scripts/github_rate_limit +10 -0
- data/scripts/hacktoberfest +138 -0
- data/scripts/make_alumni +50 -0
- data/scripts/new_rubygems_stub +17 -0
- data/scripts/pull_request_blaster_outer +24 -0
- data/scripts/pull_request_labeler +59 -0
- data/scripts/pull_request_merger +63 -0
- data/scripts/reenable_repo_workflows +33 -0
- data/scripts/rename_labels +22 -0
- data/scripts/restart_travis_builds +31 -0
- data/scripts/show_commit_history +86 -0
- data/scripts/show_org_members +19 -0
- data/scripts/show_org_repos +13 -0
- data/scripts/show_org_stats +82 -0
- data/scripts/show_project_cards +35 -0
- data/scripts/show_repo_set +13 -0
- data/scripts/show_tag +33 -0
- data/scripts/show_travis_status +63 -0
- data/scripts/update_branch_protection +22 -0
- data/scripts/update_labels +16 -0
- data/scripts/update_milestone +21 -0
- data/scripts/update_repo_settings +15 -0
- 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
|
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
|
data/multi_repo.gemspec
ADDED
@@ -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
|
data/scripts/destroy_tag
ADDED
@@ -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
|
data/scripts/fetch_repos
ADDED
@@ -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
|
data/scripts/git_mirror
ADDED
@@ -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
|
data/scripts/make_alumni
ADDED
@@ -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
|