neetob 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +10 -0
  3. data/.env +1 -0
  4. data/.rubocop.yml +596 -0
  5. data/.ruby-version +1 -0
  6. data/.semaphore/semaphore.yml +31 -0
  7. data/CHANGELOG.md +5 -0
  8. data/CODE_OF_CONDUCT.md +84 -0
  9. data/Gemfile +26 -0
  10. data/Gemfile.lock +249 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +381 -0
  13. data/Rakefile +16 -0
  14. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/github_access.rb +29 -0
  15. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/neeto_apps.rb +35 -0
  16. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/neeto_commons.rb +16 -0
  17. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/runner.rb +35 -0
  18. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/skippable.rb +19 -0
  19. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_bin.rb +32 -0
  20. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_formatters.rb +35 -0
  21. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_husky.rb +33 -0
  22. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_misc.rb +36 -0
  23. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_test_support.rb +38 -0
  24. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons.rb +36 -0
  25. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/auto_update_prs_with_latest_master_verifier.rb +25 -0
  26. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/base.rb +72 -0
  27. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/bundler_version_verifier.rb +53 -0
  28. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/circleci_config_verifier.rb +25 -0
  29. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/common_gemfile_verifier.rb +25 -0
  30. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/common_initializers_verifier.rb +25 -0
  31. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/cypress_config_verifier.rb +46 -0
  32. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/cypress_plugins_index_verifier.rb +25 -0
  33. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/docker_file_dev_verifier.rb +25 -0
  34. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/environment_config_verifier.rb +38 -0
  35. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gem_version_verifier.rb +38 -0
  36. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gems_verifier_base.rb +34 -0
  37. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gitignore_file_verifier.rb +39 -0
  38. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/jsconfig_verifier.rb +100 -0
  39. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_auth_gems_verifier.rb +20 -0
  40. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_commons_sync_verifier.rb +42 -0
  41. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_gems_version_verifier.rb +24 -0
  42. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/newrelic_verifier.rb +25 -0
  43. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/node_version_verifier.rb +63 -0
  44. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/package_dependencies_version_verifier.rb +62 -0
  45. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/package_json_verifier.rb +39 -0
  46. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/roles_verifier.rb +22 -0
  47. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/ruby_version_verifier.rb +25 -0
  48. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/semaphoreci_config_verifier.rb +162 -0
  49. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sidekiq_queues_verifier.rb +34 -0
  50. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/simplecov_config_verifier.rb +28 -0
  51. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sitemap_config_verifier.rb +29 -0
  52. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/slugignore_file_verifier.rb +25 -0
  53. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/bin_files_verifier.rb +29 -0
  54. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/formatter_files_verifier.rb +29 -0
  55. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/husky_files_verifier.rb +29 -0
  56. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/misc_files_verifier.rb +29 -0
  57. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/test_support_files_verifier.rb +28 -0
  58. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier.rb +31 -0
  59. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/webpack_configuration_verifier.rb +44 -0
  60. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/webpacker_config_verifier.rb +29 -0
  61. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers_list.rb +61 -0
  62. data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/version.rb +5 -0
  63. data/data/branch-protection-rules.json +25 -0
  64. data/data/config-vars-audit.json +18 -0
  65. data/data/config-vars-list.json +1 -0
  66. data/data/config-vars-upsert.json +3 -0
  67. data/data/github-labels.json +192 -0
  68. data/env.sample +1 -0
  69. data/exe/neetob +25 -0
  70. data/install.sh +21 -0
  71. data/lib/neetob/cli/base.rb +85 -0
  72. data/lib/neetob/cli/fetchorupdate_repos/execute.rb +53 -0
  73. data/lib/neetob/cli/github/auth.rb +134 -0
  74. data/lib/neetob/cli/github/base.rb +35 -0
  75. data/lib/neetob/cli/github/commands.rb +50 -0
  76. data/lib/neetob/cli/github/issues/commands.rb +51 -0
  77. data/lib/neetob/cli/github/issues/create.rb +42 -0
  78. data/lib/neetob/cli/github/issues/list.rb +94 -0
  79. data/lib/neetob/cli/github/labels/commands.rb +62 -0
  80. data/lib/neetob/cli/github/labels/delete.rb +44 -0
  81. data/lib/neetob/cli/github/labels/delete_all.rb +48 -0
  82. data/lib/neetob/cli/github/labels/list.rb +36 -0
  83. data/lib/neetob/cli/github/labels/show.rb +37 -0
  84. data/lib/neetob/cli/github/labels/update.rb +40 -0
  85. data/lib/neetob/cli/github/labels/upsert.rb +62 -0
  86. data/lib/neetob/cli/github/login.rb +16 -0
  87. data/lib/neetob/cli/github/make_pr/base.rb +72 -0
  88. data/lib/neetob/cli/github/make_pr/commands.rb +37 -0
  89. data/lib/neetob/cli/github/make_pr/compliance_fix.rb +49 -0
  90. data/lib/neetob/cli/github/make_pr/script.rb +55 -0
  91. data/lib/neetob/cli/github/protect_branch.rb +46 -0
  92. data/lib/neetob/cli/github/search.rb +38 -0
  93. data/lib/neetob/cli/heroku/access/add.rb +38 -0
  94. data/lib/neetob/cli/heroku/access/commands.rb +41 -0
  95. data/lib/neetob/cli/heroku/access/list.rb +36 -0
  96. data/lib/neetob/cli/heroku/access/remove.rb +38 -0
  97. data/lib/neetob/cli/heroku/commands.rb +28 -0
  98. data/lib/neetob/cli/heroku/config_vars/audit.rb +64 -0
  99. data/lib/neetob/cli/heroku/config_vars/base.rb +19 -0
  100. data/lib/neetob/cli/heroku/config_vars/commands.rb +49 -0
  101. data/lib/neetob/cli/heroku/config_vars/list.rb +56 -0
  102. data/lib/neetob/cli/heroku/config_vars/remove.rb +39 -0
  103. data/lib/neetob/cli/heroku/config_vars/upsert.rb +80 -0
  104. data/lib/neetob/cli/heroku/execute.rb +37 -0
  105. data/lib/neetob/cli/local/commands.rb +19 -0
  106. data/lib/neetob/cli/local/ls.rb +29 -0
  107. data/lib/neetob/cli/sub_command_base.rb +17 -0
  108. data/lib/neetob/cli/ui.rb +41 -0
  109. data/lib/neetob/cli/users/audit.rb +121 -0
  110. data/lib/neetob/cli/users/commands.rb +28 -0
  111. data/lib/neetob/cli/users/commits.rb +125 -0
  112. data/lib/neetob/cli.rb +40 -0
  113. data/lib/neetob/exception_handler.rb +58 -0
  114. data/lib/neetob/utils.rb +16 -0
  115. data/lib/neetob/version.rb +5 -0
  116. data/lib/neetob.rb +10 -0
  117. data/overcommit.yml +43 -0
  118. data/scripts/delete_unused_assets.rb +67 -0
  119. metadata +235 -0
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../ui"
4
+ require "net/http"
5
+ require "uri"
6
+ require "json"
7
+ require "launchy"
8
+ require "fileutils"
9
+
10
+ module Neetob
11
+ class CLI
12
+ module Github
13
+ class Auth
14
+ attr_accessor :client_id, :grant_type, :uris, :provider, :scope, :access_token, :ui
15
+
16
+ def initialize(client_id:, grant_type:, auth_uris:, provider:, scope:)
17
+ @client_id = client_id
18
+ @grant_type = grant_type
19
+ @uris = auth_uris
20
+ @provider = provider
21
+ @scope = scope
22
+ @access_token = retrieve_persisted_token
23
+ @ui = CLI::UI.new
24
+ end
25
+
26
+ def token_persisted?
27
+ access_token_present?
28
+ end
29
+
30
+ def open_url_in_browser!(url)
31
+ Launchy.open(url) do |exception|
32
+ raise(StandardError, "Attempted to open #{url} in browser and failed because #{exception}.")
33
+ end
34
+ end
35
+
36
+ def start_oauth2_device_flow
37
+ auth_data = request_authorization
38
+ show_user_code(auth_data[:user_code])
39
+ open_url_in_browser!(auth_data[:verification_uri])
40
+ poll_for_token(auth_data)
41
+ end
42
+
43
+ def request_authorization
44
+ post(uris["auth_req"], params: { client_id: client_id, scope: scope })
45
+ end
46
+
47
+ private
48
+
49
+ def show_user_code(code)
50
+ ui.say("You'll be redirected to the browser in 5 secs. Enter the following code in the browser:")
51
+ ui.success(code)
52
+ sleep 5
53
+ end
54
+
55
+ def tmp_token_path(provider)
56
+ "/tmp/neetob_#{provider}_token"
57
+ end
58
+
59
+ def provider_local_token_path
60
+ @_provider_local_token_path ||= tmp_token_path(provider)
61
+ end
62
+
63
+ def retrieve_persisted_token
64
+ File.read(provider_local_token_path) if File.file?(provider_local_token_path)
65
+ end
66
+
67
+ def parse_response(http_result)
68
+ case http_result
69
+ when Net::HTTPOK
70
+ JSON.parse(http_result.body, { symbolize_names: true })
71
+ else
72
+ raise(StandardError, "Request failed with status code #{http_result.code}. #{http_result.body}")
73
+ nil
74
+ end
75
+ end
76
+
77
+ def post(url, params:, headers: { "Accept" => "application/json" })
78
+ base_uri = URI(url)
79
+ enc_params = URI.encode_www_form(params)
80
+ http_result = Net::HTTP.post(base_uri, enc_params, headers)
81
+ parse_response(http_result)
82
+ end
83
+
84
+ def poll_for_token(auth_data)
85
+ interval = auth_data[:interval]
86
+ loop do
87
+ res = post(
88
+ uris["token_req"],
89
+ params: {
90
+ client_id: client_id,
91
+ device_code: auth_data[:device_code],
92
+ grant_type: grant_type
93
+ }
94
+ )
95
+
96
+ if res.key?(:error)
97
+ case res[:error]
98
+ when "authorization_pending"
99
+ # dont hit the endpoint too fast such that we get rate limited
100
+ sleep interval
101
+ next
102
+ when "slow_down"
103
+ # increase polling interval incase rate limited
104
+ interval = res["interval"]
105
+ sleep interval
106
+ next
107
+ when "access_denied"
108
+ # user clicks cancel button
109
+ raise(StandardError, "Access denied while authorizing #{provider} access.")
110
+ break
111
+ else
112
+ raise(StandardError, res)
113
+ break
114
+ end
115
+ end
116
+
117
+ # We won't be running this script regularly. Thus storing in /tmp/
118
+ # for temporary reuse of token till machine is rebooted
119
+ File.write(provider_local_token_path, res[:access_token])
120
+ FileUtils.chmod(0600, provider_local_token_path)
121
+
122
+ self.access_token = res[:access_token]
123
+ ui.info("You've been authenticated!")
124
+ break
125
+ end
126
+ end
127
+
128
+ def access_token_present?
129
+ !(access_token.nil? || access_token.empty?)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "octokit"
4
+
5
+ require_relative "../base"
6
+ require_relative "../../exception_handler"
7
+ require_relative "auth"
8
+ require_relative "../../utils"
9
+
10
+ module Neetob
11
+ class CLI
12
+ module Github
13
+ class Base < CLI::Base
14
+ include Utils
15
+ attr_accessor :client
16
+
17
+ def initialize
18
+ super()
19
+ auth_client = Auth.new(**read_and_parse_auth_params_from_env)
20
+ unless auth_client.token_persisted?
21
+ auth_client.start_oauth2_device_flow
22
+ end
23
+ @client = Octokit::Client.new(access_token: auth_client.access_token)
24
+ end
25
+
26
+ private
27
+
28
+ def read_and_parse_auth_params_from_env
29
+ hash_with_keys_of_string_type = JSON.parse(ENV["AUTH_PARAMS"])
30
+ symbolize_keys(hash_with_keys_of_string_type)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "labels/commands"
5
+ require_relative "issues/commands"
6
+ require_relative "search"
7
+ require_relative "protect_branch"
8
+ require_relative "login"
9
+ require_relative "make_pr/commands"
10
+
11
+ module Neetob
12
+ class CLI
13
+ module Github
14
+ class Commands < Thor
15
+ desc "labels", "Interact with the labels of Github repos"
16
+ subcommand "labels", Labels::Commands
17
+
18
+ desc "issues", "Interact with the issues of Github repos"
19
+ subcommand "issues", Issues::Commands
20
+
21
+ desc "make-pr", "Create PRs across multiple Github repos"
22
+ subcommand "make_pr", MakePr::Commands
23
+
24
+ desc "search", "Find the lines matching the given keyword in the specified file across all the neeto apps"
25
+ option :apps, type: :array, aliases: "-a", required: true, desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
26
+ option :keyword, type: :string, aliases: "-k", desc: "Keyword which needs to be searched", required: true
27
+ option :path, type: :string, aliases: "-p",
28
+ desc: "Path of the file in which you want to search the given keyword.", required: true
29
+ def search
30
+ Search.new(options[:apps], options[:keyword], options[:path], options[:sandbox]).run
31
+ end
32
+
33
+ desc "login", "Update the Github access token by authenticating via browser"
34
+ def login
35
+ Login.new
36
+ end
37
+
38
+ desc "protect_branch", "Protect the specified branch with the given rules"
39
+ option :branch, type: :string, aliases: "-b",
40
+ desc: "Name of the branch whose protections rules needs to be updated", required: true
41
+ option :path, type: :string, aliases: "-p",
42
+ desc: "The JSON file path which specify all the required rules for branch protection"
43
+ option :apps, type: :array, aliases: "-a", required: true, desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
44
+ def protect_branch
45
+ ProtectBranch.new(options[:branch], options[:apps], options[:path], options[:sandbox]).run
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "list"
6
+ require_relative "create"
7
+ require_relative "../../sub_command_base"
8
+
9
+ module Neetob
10
+ class CLI
11
+ module Github
12
+ module Issues
13
+ class Commands < SubCommandBase
14
+ class_option :apps,
15
+ {
16
+ type: :array, aliases: "-a", required: true,
17
+ desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
18
+ }
19
+
20
+ desc "list", "List the issues in the Github repos"
21
+ option :state, type: :string, default: "open", aliases: "-s", desc: "State of the issues. Can be open or closed."
22
+ option :assignee, type: :string, desc: "Username of the current assignee. Can also use \"none\"."
23
+ option :label, type: :string, aliases: "-l", desc: "Label name to filter out the issues"
24
+ option :count, type: :boolean, aliases: "-c", desc: "Also shows the count of issues"
25
+ option :search, type: :string, desc: "Can provide custom query to filter or sort issues. Example: \"created:2022-11-07..2022-11-08 sort:comments-asc\""
26
+ def list
27
+ List.new(
28
+ options[:apps], options[:assignee], options[:state], options[:search], options[:count],
29
+ options[:label], options[:sandbox]).run
30
+ end
31
+
32
+ desc "create", "Create a issue in the Github repos"
33
+ option :title, type: :string, required: true, aliases: "-t", desc: "Title of the issue"
34
+ option :description, type: :string, aliases: "-d", desc: "Description of the issue"
35
+ option :assignee, type: :string, desc: "Username of the user you want to assign this issue."
36
+ option :labels, type: :string, desc: "List of comma separated labels you want to add in this issue. Example: \"--labels bug,ui\""
37
+ def create
38
+ Create.new(
39
+ options[:apps],
40
+ options[:title],
41
+ options[:description],
42
+ options[:assignee],
43
+ options[:labels],
44
+ options[:sandbox]
45
+ ).run
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Issues
11
+ class Create < Base
12
+ attr_accessor :apps, :issue_title, :issue_description, :issue_assignee, :issue_labels, :sandbox
13
+
14
+ def initialize(apps, issue_title, issue_description = "", issue_assignee = "", issue_labels = "",
15
+ sandbox = false)
16
+ super()
17
+ @apps = apps
18
+ @issue_title = issue_title
19
+ @issue_description = issue_description
20
+ @issue_assignee = issue_assignee
21
+ @issue_labels = issue_labels
22
+ @sandbox = sandbox
23
+ end
24
+
25
+ def run
26
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
27
+ matching_apps.each do |app|
28
+ ui.info("\n Creating issue in \"#{app}\" \n")
29
+ begin
30
+ issue_options = { assignee: issue_assignee, labels: issue_labels }
31
+ issue = client.create_issue(app, issue_title, issue_description, issue_options)
32
+ ui.success("Created the issue successfully \nLink: #{issue[:html_url]}")
33
+ rescue StandardError => e
34
+ ExceptionHandler.new(e).process
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require "action_view"
5
+
6
+ require_relative "../base"
7
+
8
+ module Neetob
9
+ class CLI
10
+ module Github
11
+ module Issues
12
+ class List < Base
13
+ include ActionView::Helpers::DateHelper
14
+
15
+ attr_accessor :apps, :issue_state, :issue_assignee, :issue_search_query, :show_issues_count, :issue_label,
16
+ :sandbox
17
+
18
+ def initialize(apps, issue_assignee = "", issue_state = "open",
19
+ issue_search_query = "", show_issues_count = false, issue_label = "",
20
+ sandbox = false)
21
+ super()
22
+ @apps = apps
23
+ @issue_state = issue_state
24
+ @issue_assignee = issue_assignee
25
+ @show_issues_count = show_issues_count
26
+ @issue_search_query = issue_search_query
27
+ @issue_label = issue_label
28
+ @sandbox = sandbox
29
+ end
30
+
31
+ def run
32
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
33
+ matching_apps.each do |app|
34
+ ui.info("\n Issues of #{app} \n")
35
+ begin
36
+ issues = client.search_issues(uri_with_query_options(app))
37
+ ui.info("There are #{issues[:total_count]} issues with matching query") if show_issues_count
38
+ table_rows = create_table(issues[:items])
39
+ table = Terminal::Table.new headings: table_columns, rows: table_rows
40
+ ui.success(table)
41
+ rescue StandardError => e
42
+ ExceptionHandler.new(e).process
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def table_columns
50
+ issue_label.nil? ?
51
+ ["Title", "Created at", "Assignee", "Link"] :
52
+ ["Title", "Created at", "Assignee", "Link", "Labels"]
53
+ end
54
+
55
+ def create_table(issues)
56
+ issues.map do |issue|
57
+ row_data = [
58
+ issue[:title],
59
+ "#{distance_of_time_in_words(issue[:created_at], Time.now)} ago",
60
+ issue.dig(:assignee, :login),
61
+ issue[:html_url]
62
+ ]
63
+ issue_label.nil? ? row_data : row_data.push(labels_names(issue[:labels]))
64
+ end
65
+ end
66
+
67
+ def uri_with_query_options(app)
68
+ uri = "repo:#{app} is:issue state:#{issue_state}"
69
+ unless issue_label.nil?
70
+ check_valid_labels(app)
71
+ uri.concat(" label:#{issue_label}")
72
+ end
73
+ uri.concat(issue_assignee == "none" ? " no:assignee" : " assignee:#{issue_assignee}") if issue_assignee
74
+ "#{uri} #{issue_search_query}"
75
+ end
76
+
77
+ def labels_names(labels)
78
+ labels.map { |label| label[:name] }.join(", ")
79
+ end
80
+
81
+ def check_valid_labels(app)
82
+ issue_label.split(",").each { |label| valid_label?(app, label) }
83
+ end
84
+
85
+ def valid_label?(app, label)
86
+ client.label(app, label)
87
+ rescue Octokit::NotFound => e
88
+ ui.error("There is no \"#{label}\" label in the \"#{app}\" repo.")
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "list"
6
+ require_relative "show"
7
+ require_relative "upsert"
8
+ require_relative "delete_all"
9
+ require_relative "delete"
10
+ require_relative "update"
11
+ require_relative "../../sub_command_base"
12
+
13
+ module Neetob
14
+ class CLI
15
+ module Github
16
+ module Labels
17
+ class Commands < SubCommandBase
18
+ class_option :apps,
19
+ {
20
+ type: :array, aliases: "-a", required: true,
21
+ desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
22
+ }
23
+
24
+ desc "list", "List all the labels in the Github repos"
25
+ def list
26
+ List.new(options[:apps], options[:sandbox]).run
27
+ end
28
+
29
+ desc "show", "Show details about the given label in the Github repos"
30
+ option :name, type: :string, aliases: "-n", required: true, desc: "Name of the label"
31
+ def show
32
+ Show.new(options[:apps], options[:name], options[:sandbox]).run
33
+ end
34
+
35
+ desc "upsert", "Create and update labels in the Github repos"
36
+ option :path, type: :string, aliases: "-p", desc: "The JSON file path which has a list of all the required labels. Each label should have name. The color and description are optional"
37
+ def upsert
38
+ Upsert.new(options[:apps], options[:path], options[:sandbox]).run
39
+ end
40
+
41
+ desc "delete_all", "Delete all the labels from the Github repos"
42
+ def delete_all
43
+ DeleteAll.new(options[:apps], options[:sandbox]).run
44
+ end
45
+
46
+ desc "delete", "Delete some labels from the Github repos"
47
+ option :labels, type: :array, required: true, desc: "Labels you want to delete from the repos."
48
+ def delete
49
+ Delete.new(options[:apps], options[:labels], options[:sandbox]).run
50
+ end
51
+
52
+ desc "update", "Update a label name in Github repos"
53
+ option :old_name, type: :string, required: true, desc: "Current label name which needs to be updated"
54
+ option :new_name, type: :string, required: true, desc: "New name for the updated label"
55
+ def update
56
+ Update.new(options[:apps], options[:old_name], options[:new_name], options[:sandbox]).run
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Labels
11
+ class Delete < Base
12
+ attr_accessor :apps, :sandbox, :labels
13
+
14
+ def initialize(apps, labels, sandbox = false)
15
+ super()
16
+ @labels = labels
17
+ @apps = apps
18
+ @sandbox = sandbox
19
+ end
20
+
21
+ def run
22
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
23
+ matching_apps.each do |app|
24
+ ui.info("\n Deleting labels from #{app} repo \n")
25
+ labels.each do |label|
26
+ delete_label(app, label)
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def delete_label(app, label)
34
+ if client.delete_label!(app, label)
35
+ ui.success("The \"#{label}\" label deleted successfully")
36
+ else
37
+ ui.error("The \"#{label}\" label can't be deleted. Please check and try again")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Labels
11
+ class DeleteAll < Base
12
+ attr_accessor :apps, :sandbox
13
+
14
+ def initialize(apps, sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @sandbox = sandbox
18
+ end
19
+
20
+ def run
21
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
22
+ matching_apps.each do |app|
23
+ ui.info("\n Working on #{app} repo \n")
24
+ begin
25
+ labels = client.labels(app)
26
+ labels.each do |label|
27
+ delete_label(app, label)
28
+ end
29
+ rescue StandardError => e
30
+ ExceptionHandler.new(e).process
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def delete_label(app, label_details)
38
+ if client.delete_label!(app, label_details[:name])
39
+ ui.success("The \"#{label_details[:name]}\" label deleted successfully")
40
+ else
41
+ ui.error("The \"#{label_details[:name]}\" label can't be deleted. Please try again")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Labels
11
+ class List < Base
12
+ attr_accessor :apps, :sandbox
13
+
14
+ def initialize(apps, sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @sandbox = sandbox
18
+ end
19
+
20
+ def run
21
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
22
+ matching_apps.each do |app|
23
+ ui.info("\n Labels of #{app} \n")
24
+ begin
25
+ labels = client.labels(app)
26
+ ui.success(labels)
27
+ rescue StandardError => e
28
+ ExceptionHandler.new(e).process
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Labels
11
+ class Show < Base
12
+ attr_accessor :apps, :label_name, :sandbox
13
+
14
+ def initialize(apps, label_name, sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @label_name = label_name
18
+ @sandbox = sandbox
19
+ end
20
+
21
+ def run
22
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
23
+ matching_apps.each do |app|
24
+ ui.info("\n \"#{label_name}\" label details from #{app} \n")
25
+ begin
26
+ label_details = client.label(app, label_name)
27
+ ui.success(label_details.inspect)
28
+ rescue StandardError => e
29
+ ExceptionHandler.new(e).process
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "../base"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Github
10
+ module Labels
11
+ class Update < Base
12
+ attr_accessor :apps, :sandbox, :old_name, :new_name
13
+
14
+ def initialize(apps, old_name, new_name, sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @sandbox = sandbox
18
+ @old_name = old_name
19
+ @new_name = new_name
20
+ end
21
+
22
+ def run
23
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
24
+ matching_apps.each do |app|
25
+ ui.info("\n Updating label for #{app} repo \n")
26
+ update_label!(app, old_name, new_name)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def update_label!(app, old_name, new_name)
33
+ client.update_label(app, old_name, { name: new_name })
34
+ ui.success("Label \"#{old_name}\" updated to \"#{new_name}\" successfully")
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end