multi_repo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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