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.
- 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
|