neetob 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +10 -0
- data/.env +1 -0
- data/.rubocop.yml +596 -0
- data/.ruby-version +1 -0
- data/.semaphore/semaphore.yml +31 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +249 -0
- data/LICENSE.txt +21 -0
- data/README.md +381 -0
- data/Rakefile +16 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/github_access.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/neeto_apps.rb +35 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/neeto_commons.rb +16 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/runner.rb +35 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/skippable.rb +19 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_bin.rb +32 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_formatters.rb +35 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_husky.rb +33 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_misc.rb +36 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons/sync_test_support.rb +38 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/sync_neeto_commons.rb +36 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/auto_update_prs_with_latest_master_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/base.rb +72 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/bundler_version_verifier.rb +53 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/circleci_config_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/common_gemfile_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/common_initializers_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/cypress_config_verifier.rb +46 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/cypress_plugins_index_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/docker_file_dev_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/environment_config_verifier.rb +38 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gem_version_verifier.rb +38 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gems_verifier_base.rb +34 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/gitignore_file_verifier.rb +39 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/jsconfig_verifier.rb +100 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_auth_gems_verifier.rb +20 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_commons_sync_verifier.rb +42 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/neeto_gems_version_verifier.rb +24 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/newrelic_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/node_version_verifier.rb +63 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/package_dependencies_version_verifier.rb +62 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/package_json_verifier.rb +39 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/roles_verifier.rb +22 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/ruby_version_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/semaphoreci_config_verifier.rb +162 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sidekiq_queues_verifier.rb +34 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/simplecov_config_verifier.rb +28 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sitemap_config_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/slugignore_file_verifier.rb +25 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/bin_files_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/formatter_files_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/husky_files_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/misc_files_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier/test_support_files_verifier.rb +28 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/sync_neeto_commons_verifier.rb +31 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/webpack_configuration_verifier.rb +44 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers/webpacker_config_verifier.rb +29 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/verifiers_list.rb +61 -0
- data/Users/chiragshah/Workspace/bigbinary/neeto/neetob/neeto_compliance/lib/neeto_compliance/version.rb +5 -0
- data/data/branch-protection-rules.json +25 -0
- data/data/config-vars-audit.json +18 -0
- data/data/config-vars-list.json +1 -0
- data/data/config-vars-upsert.json +3 -0
- data/data/github-labels.json +192 -0
- data/env.sample +1 -0
- data/exe/neetob +25 -0
- data/install.sh +21 -0
- data/lib/neetob/cli/base.rb +85 -0
- data/lib/neetob/cli/fetchorupdate_repos/execute.rb +53 -0
- data/lib/neetob/cli/github/auth.rb +134 -0
- data/lib/neetob/cli/github/base.rb +35 -0
- data/lib/neetob/cli/github/commands.rb +50 -0
- data/lib/neetob/cli/github/issues/commands.rb +51 -0
- data/lib/neetob/cli/github/issues/create.rb +42 -0
- data/lib/neetob/cli/github/issues/list.rb +94 -0
- data/lib/neetob/cli/github/labels/commands.rb +62 -0
- data/lib/neetob/cli/github/labels/delete.rb +44 -0
- data/lib/neetob/cli/github/labels/delete_all.rb +48 -0
- data/lib/neetob/cli/github/labels/list.rb +36 -0
- data/lib/neetob/cli/github/labels/show.rb +37 -0
- data/lib/neetob/cli/github/labels/update.rb +40 -0
- data/lib/neetob/cli/github/labels/upsert.rb +62 -0
- data/lib/neetob/cli/github/login.rb +16 -0
- data/lib/neetob/cli/github/make_pr/base.rb +72 -0
- data/lib/neetob/cli/github/make_pr/commands.rb +37 -0
- data/lib/neetob/cli/github/make_pr/compliance_fix.rb +49 -0
- data/lib/neetob/cli/github/make_pr/script.rb +55 -0
- data/lib/neetob/cli/github/protect_branch.rb +46 -0
- data/lib/neetob/cli/github/search.rb +38 -0
- data/lib/neetob/cli/heroku/access/add.rb +38 -0
- data/lib/neetob/cli/heroku/access/commands.rb +41 -0
- data/lib/neetob/cli/heroku/access/list.rb +36 -0
- data/lib/neetob/cli/heroku/access/remove.rb +38 -0
- data/lib/neetob/cli/heroku/commands.rb +28 -0
- data/lib/neetob/cli/heroku/config_vars/audit.rb +64 -0
- data/lib/neetob/cli/heroku/config_vars/base.rb +19 -0
- data/lib/neetob/cli/heroku/config_vars/commands.rb +49 -0
- data/lib/neetob/cli/heroku/config_vars/list.rb +56 -0
- data/lib/neetob/cli/heroku/config_vars/remove.rb +39 -0
- data/lib/neetob/cli/heroku/config_vars/upsert.rb +80 -0
- data/lib/neetob/cli/heroku/execute.rb +37 -0
- data/lib/neetob/cli/local/commands.rb +19 -0
- data/lib/neetob/cli/local/ls.rb +29 -0
- data/lib/neetob/cli/sub_command_base.rb +17 -0
- data/lib/neetob/cli/ui.rb +41 -0
- data/lib/neetob/cli/users/audit.rb +121 -0
- data/lib/neetob/cli/users/commands.rb +28 -0
- data/lib/neetob/cli/users/commits.rb +125 -0
- data/lib/neetob/cli.rb +40 -0
- data/lib/neetob/exception_handler.rb +58 -0
- data/lib/neetob/utils.rb +16 -0
- data/lib/neetob/version.rb +5 -0
- data/lib/neetob.rb +10 -0
- data/overcommit.yml +43 -0
- data/scripts/delete_unused_assets.rb +67 -0
- 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
|