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,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "list"
6
+ require_relative "audit"
7
+ require_relative "upsert"
8
+ require_relative "remove"
9
+ require_relative "../../sub_command_base"
10
+
11
+ module Neetob
12
+ class CLI
13
+ module Heroku
14
+ module ConfigVars
15
+ class Commands < SubCommandBase
16
+ desc "list", "List all the config variables in the Heroku apps"
17
+ option :apps, type: :array, aliases: :a, required: true, desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
18
+ option :keys, type: :array, desc: "Array of config vars that needs to be listed."
19
+ option :path, type: :string, desc: "The JSON file path which has config vars that needs to be listed"
20
+ def list
21
+ List.new(options[:apps], options[:keys], options[:path], options[:sandbox]).run
22
+ end
23
+
24
+ desc "audit", "Verify whether config vars set in Heroku apps matches against the conditions specified in JSON file."
25
+ option :apps, type: :array, aliases: :a, required: true, desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
26
+ option :path, type: :string, desc: "The JSON file path from which config vars will be compared"
27
+ def audit
28
+ Audit.new(options[:apps], options[:path], options[:sandbox]).run
29
+ end
30
+
31
+ desc "upsert", "Update and insert the config vars in Heroku apps"
32
+ option :apps, type: :array, aliases: :a, desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
33
+ option :path, type: :string, aliases: :p, desc: "The JSON file path from which config vars will be upserted"
34
+ option :path_with_project_keys, type: :string, desc: "The JSON file path with the project names as the key containing required config vars for each project."
35
+ def upsert
36
+ Upsert.new(options[:apps], options[:path], options[:path_with_project_keys], options[:sandbox]).run
37
+ end
38
+
39
+ desc "remove", "Remove the config vars from Heroku apps"
40
+ option :apps, type: :array, aliases: :a, required: true, desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
41
+ option :keys, type: :array, required: true, desc: "Array of config vars to be removed."
42
+ def remove
43
+ Remove.new(options[:apps], options[:keys], options[:sandbox]).run
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Heroku
8
+ module ConfigVars
9
+ class List < Base
10
+ attr_accessor :apps, :sandbox, :keys, :required_config_vars_file_path
11
+
12
+ def initialize(apps, keys = [], required_config_vars_file_path = "", sandbox = false)
13
+ super()
14
+ @apps = apps
15
+ @sandbox = sandbox
16
+ @keys = keys
17
+ @required_config_vars_file_path = required_config_vars_file_path
18
+ end
19
+
20
+ def run
21
+ matching_apps = find_all_matching_apps(apps, :heroku, sandbox)
22
+ matching_apps.each do |app|
23
+ ui.info("\n Config of #{app}\n")
24
+ config = `heroku config -a #{app} --json`
25
+ unless $?.success?
26
+ ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
27
+ ui.error("Please check the specified app name and ensure you're authorized to view that app.")
28
+ next
29
+ end
30
+ table = Terminal::Table.new headings: table_columns, rows: filter_config(config)
31
+ ui.success(table)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def table_columns
38
+ ["Key", "Value"]
39
+ end
40
+
41
+ def filter_config(config)
42
+ parsed_config = JSON.parse(config)
43
+ if keys.nil? && required_config_vars_file_path.nil?
44
+ return parsed_config
45
+ end
46
+
47
+ required_config = keys || read_json_file(required_config_vars_file_path)
48
+ required_config.map do |key|
49
+ [key, parsed_config[key]]
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Heroku
8
+ module ConfigVars
9
+ class Remove < Base
10
+ attr_accessor :apps, :keys, :sandbox
11
+
12
+ def initialize(apps, keys = [], sandbox = false)
13
+ super()
14
+ @apps = apps
15
+ @keys = keys
16
+ @sandbox = sandbox
17
+ end
18
+
19
+ def run
20
+ matching_apps = find_all_matching_apps(apps, :heroku, sandbox)
21
+ matching_apps.each do |app|
22
+ `heroku access -a #{app}`
23
+
24
+ unless $?.success?
25
+ ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
26
+ ui.error("Please check the specified app name and ensure you're authorized to view that app.")
27
+ next
28
+ end
29
+
30
+ keys.each do |key|
31
+ `heroku config:unset #{key} -a #{app}`
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Heroku
8
+ module ConfigVars
9
+ class Upsert < Base
10
+ attr_accessor :apps, :required_config_vars_json_file_path,
11
+ :required_config_vars_with_project_keys_json_file_path, :sandbox
12
+
13
+ def initialize(apps, required_config_vars_json_file_path,
14
+ required_config_vars_with_project_keys_json_file_path, sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @required_config_vars_json_file_path = required_config_vars_json_file_path
18
+ @required_config_vars_with_project_keys_json_file_path =
19
+ required_config_vars_with_project_keys_json_file_path
20
+ @sandbox = sandbox
21
+ end
22
+
23
+ def run
24
+ check_the_given_arguments
25
+ inform_about_current_working_mode(sandbox) if apps.nil?
26
+ apps_to_be_updated = apps.nil? ?
27
+ read_json_file(required_config_vars_with_project_keys_json_file_path) :
28
+ find_all_matching_apps(apps, :heroku, sandbox)
29
+ inform_about_default_config_vars_file
30
+
31
+ apps_to_be_updated.each do |app|
32
+ required_config = apps.nil? ? app[1] : read_json_file(required_config_vars_json_file_path || default_config_vars_upsert_file_path)
33
+ app = app[0] if apps.nil?
34
+
35
+ if apps.nil? && sandbox && app != "neeto-dummy"
36
+ ui.error("The \"#{app}\" app is not available in sandbox mode.")
37
+ next
38
+ end
39
+
40
+ upsert_config_variables(app, required_config)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def upsert_config_variables(app, vars)
47
+ `heroku access -a #{app}`
48
+ unless $?.success?
49
+ ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
50
+ ui.error("Please check the specified app name and ensure you're authorized to view that app.")
51
+ return
52
+ end
53
+
54
+ vars.each do |key, val|
55
+ `heroku config:set #{key}='#{val}' -a #{app}`
56
+ end
57
+ end
58
+
59
+ def check_the_given_arguments
60
+ if (!apps.nil? && !required_config_vars_with_project_keys_json_file_path.nil?) ||
61
+ (apps.nil? && required_config_vars_with_project_keys_json_file_path.nil?)
62
+ ui.error("Please provide either apps or path to the config file with project keys")
63
+ exit
64
+ end
65
+ end
66
+
67
+ def default_config_vars_upsert_file_path
68
+ File.expand_path("../../../../../data/config-vars-upsert.json", __dir__)
69
+ end
70
+
71
+ def inform_about_default_config_vars_file
72
+ if !apps.nil? && required_config_vars_with_project_keys_json_file_path.nil? && required_config_vars_json_file_path.nil?
73
+ ui.info("Upserting config vars from the \"neetob/data/config-vars-upsert.json\" file")
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Heroku
8
+ class Execute < Base
9
+ attr_accessor :apps, :command_to_execute, :should_run_in_rails_console, :sandbox
10
+
11
+ def initialize(apps, command_to_execute, should_run_in_rails_console = false, sandbox = false)
12
+ super()
13
+ @apps = apps
14
+ @command_to_execute = command_to_execute
15
+ @should_run_in_rails_console = should_run_in_rails_console
16
+ @sandbox = sandbox
17
+ end
18
+
19
+ def run
20
+ matching_apps = find_all_matching_apps(apps, :heroku, sandbox)
21
+ rails_runner_command = "heroku run rails runner '#{command_to_execute}'"
22
+ heroku_command = should_run_in_rails_console ? rails_runner_command : command_to_execute
23
+ matching_apps.each do |app|
24
+ ui.info("\n Working on #{app}\n")
25
+ output = `#{heroku_command} -a #{app}`
26
+ unless $?.success?
27
+ ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
28
+ ui.error("Please check the specified app name and ensure you're authorized to view that app.")
29
+ next
30
+ end
31
+ ui.success(output)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "ls"
5
+
6
+ module Neetob
7
+ class CLI
8
+ module Local
9
+ class Commands < Thor
10
+ desc "ls", "List the files in local neeto repos"
11
+ option :apps, type: :array, aliases: "-a", required: true, desc: "Neeto app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
12
+ option :dir, type: :string, aliases: "-d", desc: "Mention the directory you want to list"
13
+ def ls
14
+ Ls.new(options[:apps], options[:dir], options[:sandbox]).run
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Local
8
+ class Ls < Base
9
+ attr_accessor :sandbox, :apps, :dir
10
+
11
+ def initialize(apps, dir, sandbox = false)
12
+ super()
13
+ @apps = apps
14
+ @dir = dir
15
+ @sandbox = sandbox
16
+ end
17
+
18
+ def run
19
+ matching_apps = find_all_matching_apps(apps, :github, sandbox, true)
20
+ matching_apps.each do |app|
21
+ app_name = app.split("/")[1]
22
+ ui.info("\nListing files from #{app_name}/#{dir}\n")
23
+ ui.info(`cd ./#{app_name} && ls #{dir}`)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ class SubCommandBase < Thor
6
+ def self.banner(command, namespace = nil, subcommand = false)
7
+ "#{basename} #{subcommand_prefix} #{command.usage}"
8
+ end
9
+
10
+ def self.subcommand_prefix
11
+ self.name
12
+ .split("::")[2..-2]
13
+ .map { |name| name.gsub(%r{^[A-Z]}) { |match| match[0].downcase } }
14
+ .map { |name| name.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" } }
15
+ .join(" ")
16
+ end
17
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ 4# frozen_string_literal: true
4
+
5
+ require "thor"
6
+
7
+ module Neetob
8
+ class CLI
9
+ class UI
10
+ attr_accessor :shell
11
+
12
+ def initialize
13
+ @shell = Thor::Base.shell.new
14
+ end
15
+
16
+ def say(statement, color = Thor::Shell::Color::YELLOW)
17
+ shell.say(statement, color)
18
+ end
19
+
20
+ def ask(question, echo = true)
21
+ shell.ask(question, echo: echo)
22
+ end
23
+
24
+ def yes?(question)
25
+ shell.yes?(question)
26
+ end
27
+
28
+ def error(statement)
29
+ shell.say(statement, Thor::Shell::Color::RED)
30
+ end
31
+
32
+ def success(statement)
33
+ shell.say(statement, Thor::Shell::Color::GREEN)
34
+ end
35
+
36
+ def info(statement)
37
+ shell.say(statement)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Users
8
+ class Audit < Base
9
+ attr_accessor :sandbox
10
+
11
+ def initialize(sandbox = false)
12
+ super()
13
+ @sandbox = sandbox
14
+ end
15
+
16
+ def run
17
+ users_data = users_for_all_available_apps
18
+ users = extract_values_from_user_data(users_data)
19
+ email_repos_map = create_email_repos_map(users)
20
+ unique_users = users.uniq { |user| [user[0], user[1]] }.sort
21
+ ui.info("\nUsers with multiple emails:")
22
+ find_users_with_multiple_emails(unique_users.transpose, email_repos_map)
23
+ ui.info("Users with emails having 3rd party domains:")
24
+ find_users_with_invalid_emails(unique_users.transpose, email_repos_map)
25
+ end
26
+
27
+ private
28
+
29
+ def users_for_all_available_apps
30
+ find_all_matching_apps(["*"], :github, sandbox, true).map do |app|
31
+ clone_repo_and_get_users(app).split("\n").map { |user| "#{user} #{app}" }
32
+ end
33
+ end
34
+
35
+ def extract_values_from_user_data(users)
36
+ users.flatten.map do |user|
37
+ values = user.strip.split(" ")[1..-1]
38
+ [values[0..-3].join(" "), clean_email(values[-2]), clean_repo_name(values[-1])]
39
+ end
40
+ end
41
+
42
+ def clone_repo_and_get_users(app)
43
+ app_name_without_org_suffix = app.split("/")[1]
44
+ `git -C ./#{app_name_without_org_suffix} shortlog -sne`
45
+ end
46
+
47
+ def create_email_repos_map(users)
48
+ map = {}
49
+ users.each do |user|
50
+ email = user[1]
51
+ repo = user[2]
52
+ map[email] = [] unless map.key?(email)
53
+ map[email].push(repo)
54
+ end
55
+ map
56
+ end
57
+
58
+ def find_users_with_multiple_emails(users, email_repos_map)
59
+ user_emails = {}
60
+ users[0].each_with_index do |name, index|
61
+ email = users[1][index]
62
+ user_emails[name] = [] unless user_emails.key?(name)
63
+ user_emails[name].push(email)
64
+ end
65
+ user_with_multiple_emails = user_emails.filter { |_, val| val.length > 1 }
66
+ table_rows = create_rows_and_add_repos(user_with_multiple_emails, email_repos_map)
67
+ create_and_show_table(table_rows, table_columns)
68
+ end
69
+
70
+ def find_users_with_invalid_emails(users, email_repos_map)
71
+ user_with_invalid_emails = {}
72
+ users[1].each_with_index do |email, index|
73
+ name = users[0][index]
74
+ if invalid_email?(email)
75
+ user_with_invalid_emails[name] = [] unless user_with_invalid_emails.key?(name)
76
+ user_with_invalid_emails[name].push(email)
77
+ end
78
+ end
79
+ table_rows = create_rows_and_add_repos(user_with_invalid_emails, email_repos_map)
80
+ create_and_show_table(table_rows, table_columns)
81
+ end
82
+
83
+ def table_columns
84
+ [:Name, :Email, :Repo]
85
+ end
86
+
87
+ def create_rows_and_add_repos(users, email_repos_map)
88
+ users.map do |name, emails|
89
+ repos = emails.map { |email| email_repos_map[email] }
90
+ [name, emails.join(", "), join_and_truncate_repos(repos)]
91
+ end
92
+ end
93
+
94
+ def create_and_show_table(data, column_names)
95
+ table = Terminal::Table.new headings: column_names, rows: data
96
+ ui.error(table)
97
+ end
98
+
99
+ def join_and_truncate_repos(repos)
100
+ repos.flatten.uniq.join(",").truncate(35)
101
+ end
102
+
103
+ def clean_email(email)
104
+ email.gsub(/<|>/, "")
105
+ end
106
+
107
+ def clean_repo_name(repo)
108
+ repo.gsub("bigbinary/", "")
109
+ end
110
+
111
+ def invalid_email?(email)
112
+ !allowed_email_domains.any? { |domain| email.downcase.include?(domain) }
113
+ end
114
+
115
+ def allowed_email_domains
116
+ ["github", "gmail", "bigbinary"]
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "audit"
5
+ require_relative "commits"
6
+
7
+ module Neetob
8
+ class CLI
9
+ module Users
10
+ class Commands < Thor
11
+ desc "audit", "Audit the users of all the neeto apps"
12
+ def audit
13
+ Audit.new(options[:sandbox]).run
14
+ end
15
+
16
+ desc "commits", "List the commits of a user across the neeto apps"
17
+ option :apps, type: :array, aliases: "-a", default: ["*"], desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
18
+ option :author, type: :string, required: true, desc: "Github username of the person whose commits you want to list"
19
+ option :duration, type: :string, required: true, desc: "Duration for which you want to list the commits. Example: \"6.months\" \"10.days\""
20
+ def commits
21
+ Commits.new(
22
+ options[:author], options[:duration], options[:apps],
23
+ options[:sandbox]).run
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Users
8
+ class Commits < Base
9
+ attr_accessor :sandbox, :apps, :author, :duration
10
+
11
+ def initialize(author, duration, apps = ["*"], sandbox = false)
12
+ super()
13
+ @sandbox = sandbox
14
+ @apps = apps
15
+ @author = author
16
+ @duration = duration
17
+ end
18
+
19
+ def run
20
+ table_rows = build_commit_rows
21
+ html_content = build_html_content(table_rows)
22
+ create_html_file(html_content)
23
+ open_html_file_in_default_system_application
24
+ end
25
+
26
+ private
27
+
28
+ def build_commit_rows
29
+ find_all_matching_apps(apps, :github, sandbox, true).map do |app|
30
+ commits = commits_within_range(app)
31
+ if commits.empty?
32
+ ui.error("No commits found in \"#{app}\" for the given author and duration.")
33
+ next
34
+ end
35
+
36
+ build_table_rows(app, commits)
37
+ end
38
+ end
39
+
40
+ def commits_within_range(app)
41
+ `git -C ./#{app_name_without_org_suffix(app)} log --pretty=format:"%H:::%ae:::%ar:::%s" --author=#{author} --since=#{duration} --no-merges`
42
+ end
43
+
44
+ def build_table_rows(app, commits)
45
+ commits.split("\n").map { |commit| html_table_row(app, *commit.split(":::")) }
46
+ end
47
+
48
+ def app_name_without_org_suffix(app)
49
+ app.split("/")[1]
50
+ end
51
+
52
+ def html_table_row(app, commit, email, time, title)
53
+ starting_7_characters_of_commit = commit[0..6]
54
+ "<tr>
55
+ <td class='commit'><a href='https://github.com/#{app}/commit/#{commit}'
56
+ target='_blank'>#{starting_7_characters_of_commit}</a></td>
57
+ <td class='project'>#{app_name_without_org_suffix(app)}</td>
58
+ <td class='email'>#{email}</td>
59
+ <td class='time'>#{time}</td>
60
+ <td class='title'>#{title}</td>
61
+ </tr>"
62
+ end
63
+
64
+ def build_html_content(table_rows)
65
+ "<!DOCTYPE html>
66
+ <html>
67
+ <body>
68
+ <style>
69
+ table {
70
+ font-family: arial, sans-serif;
71
+ border-collapse: collapse;
72
+ width: 100%;
73
+ }
74
+ td, th {
75
+ border: 1px solid #dddddd;
76
+ text-align: left;
77
+ padding: 8px;
78
+ }
79
+ tr:nth-child(even) {
80
+ background-color: #dddddd;
81
+ }
82
+ .project {
83
+ color: blue;
84
+ }
85
+ .commit {
86
+ color: blueviolet;
87
+ }
88
+ .email {
89
+ color: green;
90
+ width: 50px;
91
+ }
92
+ .time {
93
+ color: darkorange;
94
+ }
95
+ .title {
96
+ color: lightcoral
97
+ }
98
+ </style>
99
+ <table>
100
+ <tr>
101
+ <th>Commit</th>
102
+ <th>Product</th>
103
+ <th>Email</th>
104
+ <th>Created at</th>
105
+ <th>Title</th>
106
+ </tr>
107
+ #{table_rows.empty? ? "<tr><td>No commits found in the given duration</td></tr>" : table_rows.join}
108
+ </table>
109
+ </body>
110
+ </html>"
111
+ end
112
+
113
+ def create_html_file(html_content)
114
+ commits_file = File.new("commits.html", "w")
115
+ commits_file.puts(html_content)
116
+ commits_file.close
117
+ end
118
+
119
+ def open_html_file_in_default_system_application
120
+ `open ./commits.html`
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
data/lib/neetob/cli.rb ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ module Neetob
6
+ class CLI < Thor
7
+ require_relative "cli/heroku/commands"
8
+ require_relative "cli/github/commands"
9
+ require_relative "cli/users/commands"
10
+ require_relative "cli/fetchorupdate_repos/execute"
11
+ require_relative "cli/local/commands"
12
+
13
+ class_option :sandbox,
14
+ {
15
+ type: :boolean, default: false,
16
+ desc: "All the commands in sandbox mode will run only on the \"neeto-dummy\" app."
17
+ }
18
+
19
+ def self.start(*)
20
+ super
21
+ end
22
+
23
+ desc "heroku", "Interact with any resource in Heroku"
24
+ subcommand "heroku", Heroku::Commands
25
+
26
+ desc "github", "Interact with any resource in Github"
27
+ subcommand "github", Github::Commands
28
+
29
+ desc "users", "Interact with the contributors of neeto apps"
30
+ subcommand "users", Users::Commands
31
+
32
+ desc "local", "Interact with the local neeto repos"
33
+ subcommand "local", Local::Commands
34
+
35
+ desc "make_repos_uptodate", "Uptodate all neeto repos"
36
+ def make_repos_uptodate
37
+ FetchorupdateRepos::Execute.new(options[:sandbox]).run
38
+ end
39
+ end
40
+ end