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,59 @@
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 :prs, "The list of PRs to merge", :type => :strings, :required => true
11
+ opt :add, "Labels to add", :type => :strings, :required => true
12
+ opt :remove, "Labels to remove", :type => :strings, :required => true
13
+
14
+ MultiRepo::CLI.common_options(self, :only => :dry_run)
15
+ end
16
+
17
+ # TODO: Normalize any PR format to `org/repo#pr`
18
+ PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
19
+ Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }
20
+
21
+ def github
22
+ MultiRepo::Service::Github.client
23
+ end
24
+
25
+ def add_labels(repo_name, pr_number, labels:, dry_run:, **_)
26
+ labels = Array(labels)
27
+ if dry_run
28
+ puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
29
+ else
30
+ github.add_labels_to_an_issue(repo_name, pr_number, labels)
31
+ end
32
+ end
33
+
34
+ def remove_labels(repo_name, pr_number, labels:, dry_run:, **_)
35
+ Array(labels).each do |label|
36
+ remove_label(repo_name, pr_number, label: label, dry_run: dry_run)
37
+ end
38
+ end
39
+
40
+ def remove_label(repo_name, pr_number, label:, dry_run:, **_)
41
+ if dry_run
42
+ puts "** dry-run: github.remove_label(#{repo_name.inspect}, #{pr_number.inspect}, #{label.inspect})".light_black
43
+ else
44
+ github.remove_label(repo_name, pr_number, label)
45
+ end
46
+ rescue Octokit::NotFound
47
+ # Ignore labels that are not found, because we want them removed anyway
48
+ end
49
+
50
+ opts[:prs].each do |pr|
51
+ puts MultiRepo::CLI.header(pr)
52
+
53
+ repo_name, pr_number = PR_REGEX.match(pr).captures
54
+
55
+ add_labels(repo_name, pr_number, labels: opts[:add], **opts)
56
+ remove_labels(repo_name, pr_number, labels: opts[:remove], **opts)
57
+
58
+ puts
59
+ end
@@ -0,0 +1,63 @@
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 :prs, "The list of PRs to merge", :type => :strings, :required => true
11
+ opt :assignee, "GitHub user to assign when merging", :type => :string, :required => true
12
+ opt :labels, "Labels to apply when merging", :type => :strings
13
+
14
+ MultiRepo::CLI.common_options(self)
15
+ end
16
+
17
+ # TODO: Normalize any PR format to `org/repo#pr`
18
+ PR_REGEX = %r{^([^/#]+/[^/#]+)#([^/#]+)$}
19
+ Optimist.die :prs, "must be in the form `org/repo#pr`" unless opts[:prs].all? { |pr| pr.match?(PR_REGEX) }
20
+
21
+ def merge_pull_request(repo_name, pr_number, dry_run:, **_)
22
+ if dry_run
23
+ puts "** dry-run: github.merge_pull_request(#{repo_name.inspect}, #{pr_number.inspect})".light_black
24
+ else
25
+ begin
26
+ MultiRepo::Service::Github.client.merge_pull_request(repo_name, pr_number)
27
+ rescue Octokit::MethodNotAllowed => err
28
+ raise unless err.to_s.include?("Pull Request is not mergeable")
29
+
30
+ puts "** WARN: Pull Request is not mergeable"
31
+ end
32
+ end
33
+ end
34
+
35
+ def add_labels(repo_name, pr_number, labels:, dry_run:, **_)
36
+ labels = Array(labels)
37
+ if dry_run
38
+ puts "** dry-run: github.add_labels_to_an_issue(#{repo_name.inspect}, #{pr_number.inspect}, #{labels.inspect})".light_black
39
+ else
40
+ MultiRepo::Service::Github.client.add_labels_to_an_issue(repo_name, pr_number, labels)
41
+ end
42
+ end
43
+
44
+ def assign_user(repo_name, pr_number, assignee:, dry_run:, **_)
45
+ assignee = assignee[1..] if assignee.start_with?("@")
46
+ if dry_run
47
+ puts "** dry-run: github.update_issue(#{repo_name.inspect}, #{pr_number.inspect}, \"assignee\" => #{assignee.inspect})".light_black
48
+ else
49
+ MultiRepo::Service::Github.client.update_issue(repo_name, pr_number, "assignee" => assignee)
50
+ end
51
+ end
52
+
53
+ opts[:prs].each do |pr|
54
+ puts MultiRepo::CLI.header(pr)
55
+
56
+ repo_name, pr_number = PR_REGEX.match(pr).captures
57
+
58
+ merge_pull_request(repo_name, pr_number, opts)
59
+ add_labels(repo_name, pr_number, opts) if opts[:labels].present?
60
+ assign_user(repo_name, pr_number, opts)
61
+
62
+ puts
63
+ end
@@ -0,0 +1,33 @@
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 reenable workflows in", :type => :string, :required => true
11
+ opt :extra_repos, "Extra repos to reenable workflows in", :type => :strings, :default => []
12
+
13
+ MultiRepo::CLI.common_options(self, :only => :dry_run)
14
+ ende
15
+
16
+ github = MultiRepo::Service::Github.new(**opts.slice(:dry_run))
17
+
18
+ repos = (github.org_repo_names(opts[:org]) + opts[:extra_repos]).sort
19
+ repos.each do |repo_name|
20
+ puts MultiRepo::CLI.header(repo_name)
21
+
22
+ disabled_workflows = github.disabled_workflows
23
+ if disabled_workflows.any?
24
+ disabled_workflows.each do |w|
25
+ puts "** Enabling #{w.html_url} (#{w.id})"
26
+ github.enable_workflow(github, repo_name, w.html_url, w.id)
27
+ end
28
+ else
29
+ puts "** No disabled workflows found"
30
+ end
31
+
32
+ puts
33
+ end
@@ -0,0 +1,22 @@
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 :old, "The old label names.", :type => :strings, :required => true
11
+ opt :new, "The new label names.", :type => :strings, :required => true
12
+
13
+ MultiRepo::CLI.common_options(self)
14
+ end
15
+
16
+ rename_hash = opts[:old].zip(opts[:new]).to_h
17
+ puts "Renaming: #{rename_hash.pretty_inspect}"
18
+ puts
19
+
20
+ MultiRepo::CLI.each_repo(**opts) do |repo|
21
+ MultiRepo::Helpers::RenameLabels.new(repo.name, rename_hash, **opts).run
22
+ 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
+ require 'travis'
9
+ require 'travis/pro/auto_login'
10
+
11
+ opts = Optimist.options do
12
+ opt :ref, "The branch or release tag to rebuild.", :type => :string, :required => true
13
+
14
+ MultiRepo::CLI.common_options(self, :except => :dry_run, :repo_set_default => nil)
15
+ end
16
+ opts[:repo_set] = opts[:ref].split("-").first unless opts[:repo] || opts[:repo_set]
17
+
18
+ puts "Restarting Travis builds for #{opts[:ref]}:"
19
+
20
+ MultiRepo::CLI.repos_for(**opts).collect do |repo|
21
+ repo = Travis::Pro::Repository.find(repo.name)
22
+ begin
23
+ last_build = repo.last_on_branch(opts[:ref])
24
+ rescue Travis::Client::NotFound
25
+ # Ignore repo which doesn't have Travis enabled for that branch
26
+ next
27
+ end
28
+
29
+ puts "- #{repo.name}..."
30
+ last_build.restart
31
+ end
@@ -0,0 +1,86 @@
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 "active_support/core_ext/object/blank"
9
+ require "active_support/core_ext/string/inflections"
10
+
11
+ DISPLAY_FORMATS = %w[commit pr-title pr-label]
12
+
13
+ opts = Optimist.options do
14
+ opt :from, "The commit log 'from' ref", :type => :string, :required => true
15
+ opt :to, "The commit log 'to' ref" , :type => :string, :required => true
16
+ opt :display, "How to display the history. Valid values are: #{DISPLAY_FORMATS.join(", ")}", :default => "commit"
17
+ opt :summary, "Display a summary of the repos.", :default => false
18
+
19
+ opt :skip, "The repos to skip", :type => :strings, :default => []
20
+
21
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
22
+ end
23
+ Optimist.die :display, "must be one of: #{DISPLAY_FORMATS.join(", ")}" unless DISPLAY_FORMATS.include?(opts[:display])
24
+
25
+ range = "#{opts[:from]}..#{opts[:to]}"
26
+
27
+ puts "Git commit log between #{opts[:from]} and #{opts[:to]}\n\n"
28
+
29
+ repos_with_changes = []
30
+
31
+ MultiRepo::CLI.repos_for(**opts).each do |repo|
32
+ next if opts[:skip].include?(repo.name)
33
+
34
+ puts MultiRepo::CLI.header(repo.name)
35
+ repo.git.fetch(output: false)
36
+
37
+ case opts[:display]
38
+ when "pr-label", "pr-title"
39
+ github ||= MultiRepo::Service::Github.client
40
+ pr_label_display = opts[:display] == "pr-label"
41
+
42
+ results = {}
43
+ if pr_label_display
44
+ results["bug"] = []
45
+ results["enhancement"] = []
46
+ end
47
+ results["other"] = []
48
+
49
+ log = repo.git.client.capturing.log({:oneline => true}, range)
50
+ log.lines.each do |line|
51
+ next unless (match = line.match(/Merge pull request #(\d+)\b/))
52
+
53
+ pr = github.pull_request(repo.name, match[1])
54
+ label = pr.labels.detect { |l| results.key?(l.name) }&.name || "other"
55
+ results[label] << pr
56
+ end
57
+
58
+ changes_found = false
59
+
60
+ results.each do |label, prs|
61
+ next if prs.blank?
62
+ changes_found = true
63
+
64
+ puts "\n## #{label.titleize}\n\n" if pr_label_display
65
+ prs.each do |pr|
66
+ puts "* #{pr.title} [[##{pr.number}]](#{pr.html_url})"
67
+ end
68
+ end
69
+
70
+ repos_with_changes << repo if changes_found
71
+ when "commit"
72
+ output = repo.git.client.capturing.log({:oneline => true, :decorate => true, :graph => true}, range)
73
+ puts output
74
+ repos_with_changes << repo if output.present?
75
+ end
76
+ puts
77
+ end
78
+
79
+ if opts[:summary] && repos_with_changes.any?
80
+ puts
81
+ puts "Here are the changes per affected repository in GitHub:"
82
+ repos_with_changes.each do |repo|
83
+ puts "* [#{repo.name}](https://github.com/#{repo.name}/compare/#{opts[:from]}...#{opts[:to]})"
84
+ end
85
+ puts
86
+ end
@@ -0,0 +1,19 @@
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 org to list the users for", :type => :string, :required => true
11
+ opt :team, "Show members of a specific team", :type => :string
12
+ opt :alumni, "Whether or not to include alumni", :default => false
13
+ end
14
+
15
+ github = MultiRepo::Service::Github.new
16
+ members = opts[:team] ? github.team_member_names(opts[:org], opts[:team]) : github.org_member_names(opts[:org])
17
+ members -= github.team_member_names(opts[:org], "alumni") unless opts[:alumni]
18
+
19
+ puts members
@@ -0,0 +1,13 @@
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 org to list the repos for", :type => :string, :required => true
11
+ end
12
+
13
+ puts MultiRepo::Service::Github.org_repo_names(opts[:org])
@@ -0,0 +1,82 @@
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 :since, "Since what date.", :type => :string, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self, :except => :dry_run)
13
+ end
14
+
15
+ class OrgStats
16
+ def initialize(since:, **opts)
17
+ @since = since
18
+ @opts = opts
19
+
20
+ @total_commits = Hash.new(0)
21
+ @total_merges = Hash.new(0)
22
+ @names = {}
23
+ end
24
+
25
+ def run
26
+ MultiRepo::CLI.each_repo(**@opts) { |repo| run_one(repo) }
27
+
28
+ puts
29
+ puts "Total Commits:"
30
+ print_totals(@total_commits)
31
+
32
+ puts
33
+ puts "Grand Total Commits: #{@total_commits.values.sum}"
34
+
35
+ puts
36
+ puts "Total Merges:"
37
+ print_totals(@total_merges)
38
+
39
+ puts
40
+ puts "Grand Total Merges: #{@total_merges.values.sum}"
41
+ end
42
+
43
+ private
44
+
45
+ def run_one(repo)
46
+ repo.git.fetch
47
+ repo.git.hard_checkout("master")
48
+
49
+ puts "Commits:"
50
+ commits = repo.git.client.capturing.shortlog("--summary", "--numbered", "--email", "--no-merges", "--since", @since)
51
+ puts commits
52
+
53
+ parse_data(commits).each do |number, name, email|
54
+ @total_commits[email] += number.to_i
55
+ @names[email] ||= name
56
+ end
57
+
58
+ puts "Merges:"
59
+ merges = repo.git.client.capturing.shortlog("--summary", "--numbered", "--email", "--merges", "--since", @since, "--grep", "Merge pull request #")
60
+ puts merges
61
+
62
+ parse_data(merges).each do |number, name, email|
63
+ @total_merges[email] += number.to_i
64
+ @names[email] ||= name
65
+ end
66
+ end
67
+
68
+ def parse_data(data)
69
+ data
70
+ .chomp
71
+ .lines(:chomp => true)
72
+ .map { |l| l.match(/^\s*(\d+)\s+([^<]+)<([^>]+)>/).captures }
73
+ end
74
+
75
+ def print_totals(totals)
76
+ totals.sort_by { |_email, number| -number }.each do |email, number|
77
+ puts "#{number.to_s.rjust(8)} #{@names[email]} <#{email}>"
78
+ end
79
+ end
80
+ end
81
+
82
+ OrgStats.new(**opts).run
@@ -0,0 +1,35 @@
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 :project_id, "The project ID", :type => :integer, :required => true
11
+ opt :column, "The column within the project", :type => :string, :required => true
12
+
13
+ MultiRepo::CLI.common_options(self, :only => :repo)
14
+ end
15
+
16
+ github = MultiRepo::Service::Github.client
17
+ repo = opts[:repo].first
18
+ projects_headers = {:accept => "application/vnd.github.inertia-preview+json"}
19
+
20
+ projects = github.send(repo.include?("/") ? :projects : :org_projects, repo, projects_headers)
21
+ project = projects.detect { |p| p.number == opts[:project_id] }
22
+ Optimist.die :project_id, "not found" if project.nil?
23
+
24
+ column = github.project_columns(project.id, projects_headers).detect { |c| c.name == opts[:column] }
25
+ Optimist.die :column, "not found" if column.nil?
26
+
27
+ cards = github.column_cards(column.id, projects_headers)
28
+ issues = cards.map do |card|
29
+ org, repo, _issues, id = URI.parse(card.content_url).path.split("/").last(4)
30
+ github.issue("#{org}/#{repo}", id)
31
+ end
32
+
33
+ issues.each do |issue|
34
+ puts "* #{issue.title} [[##{issue.number}]](#{issue.html_url})"
35
+ end
@@ -0,0 +1,13 @@
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
+ MultiRepo::CLI.common_options(self, :only => :repo_set)
11
+ end
12
+
13
+ puts MultiRepo::CLI.repos_for(**opts).collect(&:name)
data/scripts/show_tag ADDED
@@ -0,0 +1,33 @@
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
+ opts = Optimist.options do
11
+ opt :tag, "The tag name.", :type => :string, :required => true
12
+
13
+ MultiRepo::CLI.common_options(self, :except => :dry_run, :repo_set_default => nil)
14
+ end
15
+ opts[:repo_set] = opts[:tag].split("-").first unless opts[:repo] || opts[:repo_set]
16
+
17
+ HEADER = %w(Repo SHA Message).freeze
18
+
19
+ def show_tag(repo, tag)
20
+ line =
21
+ begin
22
+ repo.git.client.capturing.show({:summary => true, :oneline => true}, tag)
23
+ rescue MiniGit::GitError => err
24
+ ""
25
+ end
26
+
27
+ sha, message = line.split(" ", 2)
28
+ [repo.name, sha, message]
29
+ end
30
+
31
+ repos = MultiRepo::CLI.repos_for(**opts)
32
+ table = [HEADER] + repos.collect { |repo| show_tag(repo, opts[:tag]) }
33
+ puts table.tableize(:max_width => 75)
@@ -0,0 +1,63 @@
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
+ gem "action_view"
8
+ end
9
+
10
+ require 'more_core_extensions/core_ext/array/tableize'
11
+ require 'action_view' # For ActionView::Helpers::DateHelper
12
+ require 'travis'
13
+ require 'travis/pro/auto_login'
14
+
15
+ opts = Optimist.options do
16
+ opt :ref, "The branch or release tag to check status for.", :type => :string, :required => true
17
+
18
+ MultiRepo::CLI.common_options(self, :except => :dry_run, :repo_set_default => nil)
19
+ end
20
+ opts[:repo_set] = opts[:ref].split("-").first unless opts[:repo] || opts[:repo_set]
21
+
22
+ date_helper = Class.new { include ActionView::Helpers::DateHelper }.new
23
+
24
+ travis_repos = MultiRepo::CLI.repos_for(**opts).collect do |repo|
25
+ repo = Travis::Pro::Repository.find(repo.name)
26
+ begin
27
+ last_build = repo.last_on_branch(opts[:ref])
28
+ rescue Travis::Client::NotFound
29
+ # Ignore repo which doesn't have Travis enabled for that branch
30
+ next
31
+ end
32
+
33
+ status, status_sort =
34
+ case last_build.state
35
+ when "errored", "failed"
36
+ [last_build.state.red, 0]
37
+ when "created", "started"
38
+ [last_build.state.yellow, 1]
39
+ when "passed"
40
+ [last_build.state.green, 2]
41
+ else
42
+ [last_build.state, 3]
43
+ end
44
+
45
+ date_sort = last_build.finished_at
46
+ date = "#{date_helper.time_ago_in_words(date_sort)} ago" if date_sort
47
+
48
+ last_build_url = "https://travis-ci.com/github/#{last_build.repository.slug}/builds/#{last_build.id}"
49
+
50
+ {
51
+ "Repo" => repo.name,
52
+ "Status" => status,
53
+ "Status Sort" => status_sort,
54
+ "Date" => date,
55
+ "Date Sort" => date_sort,
56
+ "URL" => last_build_url
57
+ }
58
+ end.compact
59
+
60
+ # Reverse sort by date then stable sort by status
61
+ travis_repos = travis_repos.sort_by { |v| v["Date Sort"].to_s }.reverse.sort_by.with_index { |v, n| [v["Status Sort"], n] }
62
+
63
+ puts travis_repos.tableize(:columns => ["Repo", "Status", "Date", "URL"])
@@ -0,0 +1,22 @@
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 protect.", :type => :string, :required => true
11
+
12
+ MultiRepo::CLI.common_options(self, :repo_set_default => nil)
13
+ end
14
+ opts[:repo_set] = opts[:branch] unless opts[:repo] || opts[:repo_set]
15
+
16
+ MultiRepo::CLI.repos_for(**opts).each do |repo|
17
+ next if opts[:branch] != "master" && repo.config.has_real_releases
18
+
19
+ puts MultiRepo::CLI.header(repo.name)
20
+ MultiRepo::Helpers::UpdateBranchProtection.new(repo.name, **opts).run
21
+ puts
22
+ end
@@ -0,0 +1,16 @@
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
+ MultiRepo::CLI.common_options(self, :repo_set_default => nil)
11
+ end
12
+ opts[:repo] = MultiRepo::Labels.all.keys.sort unless opts[:repo] || opts[:repo_set]
13
+
14
+ MultiRepo::CLI.each_repo(**opts) do |repo|
15
+ MultiRepo::Helpers::UpdateLabels.new(repo.name, **opts).run
16
+ end
@@ -0,0 +1,21 @@
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 :title, "The milestone title.", :type => :string, :required => true
11
+ opt :due_on, "The due date.", :type => :string
12
+ opt :close, "Whether to close the milestone.", :default => false
13
+
14
+ MultiRepo::CLI.common_options(self)
15
+ end
16
+ Optimist.die(:due_on, "is required") if !opts[:close] && !opts[:due_on]
17
+ Optimist.die(:due_on, "must be a date format") if opts[:due_on] && !MultiRepo::Service::GitHub.valid_milestone_date?(opts[:due_on])
18
+
19
+ MultiRepo::CLI.each_repo(**opts) do |repo|
20
+ MultiRepo::Helpers::UpdateMilestone.new(repo.name, **opts).run
21
+ end
@@ -0,0 +1,15 @@
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
+ MultiRepo::CLI.common_options(self)
11
+ end
12
+
13
+ MultiRepo::CLI.each_repo(**opts) do |repo|
14
+ MultiRepo::Helpers::UpdateRepoSettings.new(repo.name, **opts).run
15
+ end