neetob 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 (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