neetob-ud 0.2.5
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 +30 -0
- data/CHANGELOG.md +40 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +28 -0
- data/Gemfile.lock +250 -0
- data/LICENSE.txt +21 -0
- data/README.md +396 -0
- data/Rakefile +16 -0
- data/config/secrets.yml +0 -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/github-labels.json +197 -0
- data/env.sample +1 -0
- data/exe/neetob +25 -0
- data/install.sh +21 -0
- data/lib/neetob/cli/base.rb +96 -0
- data/lib/neetob/cli/fetchorupdate_repos/execute.rb +55 -0
- data/lib/neetob/cli/github/auth.rb +134 -0
- data/lib/neetob/cli/github/base.rb +42 -0
- data/lib/neetob/cli/github/commands.rb +54 -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 +65 -0
- data/lib/neetob/cli/github/labels/delete.rb +46 -0
- data/lib/neetob/cli/github/labels/delete_all.rb +50 -0
- data/lib/neetob/cli/github/labels/list.rb +38 -0
- data/lib/neetob/cli/github/labels/show.rb +39 -0
- data/lib/neetob/cli/github/labels/update.rb +42 -0
- data/lib/neetob/cli/github/labels/upsert.rb +64 -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 +48 -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 +30 -0
- data/lib/neetob/cli/users/commits.rb +171 -0
- data/lib/neetob/cli.rb +42 -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 +186 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Heroku
|
8
|
+
module Access
|
9
|
+
class List < Base
|
10
|
+
attr_accessor :apps, :sandbox
|
11
|
+
|
12
|
+
def initialize(apps, sandbox = false)
|
13
|
+
super()
|
14
|
+
@apps = apps
|
15
|
+
@sandbox = sandbox
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
matching_apps = find_all_matching_apps(apps, :heroku, sandbox)
|
20
|
+
matching_apps.each do |app|
|
21
|
+
ui.info("\n Users for \"#{app}\" app\n")
|
22
|
+
users = `heroku access -a #{app}`
|
23
|
+
unless $?.success?
|
24
|
+
ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
|
25
|
+
ui.error("Please check the specified app name and ensure you're authorized to view that app.")
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
ui.success(users)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../base"
|
4
|
+
|
5
|
+
module Neetob
|
6
|
+
class CLI
|
7
|
+
module Heroku
|
8
|
+
module Access
|
9
|
+
class Remove < Base
|
10
|
+
attr_accessor :apps, :users_to_be_removed, :sandbox
|
11
|
+
|
12
|
+
def initialize(apps, users_to_be_removed = [], sandbox = false)
|
13
|
+
super()
|
14
|
+
@apps = apps
|
15
|
+
@users_to_be_removed = users_to_be_removed
|
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
|
+
unless $?.success?
|
24
|
+
ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
|
25
|
+
ui.error("Please check the specified app name and ensure you're authorized to view that app.")
|
26
|
+
next
|
27
|
+
end
|
28
|
+
|
29
|
+
users_to_be_removed.each do |user|
|
30
|
+
ui.info(`heroku access:remove #{user} -a #{app}`)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require_relative "config_vars/commands"
|
5
|
+
require_relative "access/commands"
|
6
|
+
require_relative "execute"
|
7
|
+
|
8
|
+
module Neetob
|
9
|
+
class CLI
|
10
|
+
module Heroku
|
11
|
+
class Commands < Thor
|
12
|
+
desc "execute", "Run the given Heroku CLI command or Rails console command on Heroku apps"
|
13
|
+
option :command, type: :string, aliases: "-c", required: true, desc: "Command to run on Heroku apps"
|
14
|
+
option :rails, type: :boolean, aliases: "-r", default: false, desc: "Use this flag to run the given command in the Rails console"
|
15
|
+
option :apps, type: :array, aliases: "-a", required: true, desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
|
16
|
+
def execute
|
17
|
+
Execute.new(options[:apps], options[:command], options[:rails], options[:sandbox]).run
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "config_vars", "Interact with the config(env) variables on Heroku apps"
|
21
|
+
subcommand "config_vars", ConfigVars::Commands
|
22
|
+
|
23
|
+
desc "access", "Interact with the users of the Heroku apps"
|
24
|
+
subcommand "access", Access::Commands
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "terminal-table"
|
5
|
+
|
6
|
+
require_relative "base"
|
7
|
+
|
8
|
+
module Neetob
|
9
|
+
class CLI
|
10
|
+
module Heroku
|
11
|
+
module ConfigVars
|
12
|
+
class Audit < Base
|
13
|
+
attr_accessor :apps, :expected_config_vars_json_file_path, :sandbox
|
14
|
+
|
15
|
+
def initialize(apps, expected_config_vars_json_file_path = "", sandbox = false)
|
16
|
+
super()
|
17
|
+
@apps = apps
|
18
|
+
@expected_config_vars_json_file_path = expected_config_vars_json_file_path
|
19
|
+
@sandbox = sandbox
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
matching_apps = find_all_matching_apps(apps, :heroku, sandbox)
|
24
|
+
table_rows = []
|
25
|
+
expected_config = read_json_file(expected_config_vars_json_file_path || default_config_vars_json_file_path)
|
26
|
+
return unless expected_config
|
27
|
+
|
28
|
+
matching_apps.each do |app|
|
29
|
+
actual_config = `heroku config -a #{app} --json`
|
30
|
+
unless $?.success?
|
31
|
+
ui.error("There is a problem in accessing the app with name \"#{app}\" in your account.")
|
32
|
+
ui.error("Please check the specified app name and ensure you're authorized to view that app.")
|
33
|
+
next
|
34
|
+
end
|
35
|
+
|
36
|
+
actual_config_json = JSON.parse(actual_config)
|
37
|
+
table_rows.concat(compare_config_and_build_rows(app, expected_config, actual_config_json))
|
38
|
+
end
|
39
|
+
table = Terminal::Table.new headings: ["App", "Config var", "Expected", "Result"], rows: table_rows
|
40
|
+
ui.success(table)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def compare_config_and_build_rows(app, expected_config, actual_config)
|
46
|
+
expected_config.map do |key, val|
|
47
|
+
row = [app, key.to_s]
|
48
|
+
row << (value_set_dynamically_by_heroku?(val) ? "Heroku has dynamically set the value" : val.to_s)
|
49
|
+
row << (actual_config[key] == val ? "✅" : (actual_config[key] || "No such key"))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def value_set_dynamically_by_heroku?(value)
|
54
|
+
value == { "isDynamic" => true }
|
55
|
+
end
|
56
|
+
|
57
|
+
def default_config_vars_json_file_path
|
58
|
+
File.expand_path("../../../../../data/config-vars-audit.json", __dir__)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,19 @@
|
|
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 Base < CLI::Base
|
10
|
+
attr_accessor :client
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -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
|