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,62 @@
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 Upsert < Base
12
+ attr_accessor :apps, :required_labels_json_file_path, :sandbox
13
+
14
+ def initialize(apps, required_labels_json_file_path = "", sandbox = false)
15
+ super()
16
+ @apps = apps
17
+ @required_labels_json_file_path = required_labels_json_file_path
18
+ @sandbox = sandbox
19
+ end
20
+
21
+ def run
22
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
23
+ inform_about_default_labels_file
24
+ matching_apps.each do |app|
25
+ ui.info("\n Working on #{app} repo \n")
26
+ begin
27
+ required_labels = read_json_file(required_labels_json_file_path || default_labels_file_path)
28
+ required_labels.each do |label|
29
+ create_or_update_label(app, label)
30
+ end
31
+ rescue StandardError => e
32
+ ExceptionHandler.new(e).process
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def create_or_update_label(app, label_details)
40
+ begin
41
+ client.update_label(app, label_details["name"], label_details)
42
+ ui.success("Label \"#{label_details["name"]}\" updated successfully")
43
+ rescue Octokit::NotFound
44
+ client.add_label(app, label_details["name"], label_details["color"], label_details)
45
+ ui.success("Label \"#{label_details["name"]}\" created successfully")
46
+ end
47
+ end
48
+
49
+ def default_labels_file_path
50
+ File.expand_path("../../../../../data/github-labels.json", __dir__)
51
+ end
52
+
53
+ def inform_about_default_labels_file
54
+ if required_labels_json_file_path.nil?
55
+ ui.info("Upserting labels from the \"neetob/data/github-labels.json\" file")
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Github
8
+ class Login < Base
9
+ def initialize
10
+ super()
11
+ Auth.new(**read_and_parse_auth_params_from_env).start_oauth2_device_flow
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Github
8
+ module MakePr
9
+ class Base < Github::Base
10
+ BRANCH_NAME = "neeto_compliance"
11
+ PR_TITLE = "Neeto Compliance"
12
+ attr_accessor :branch_name, :pr_title
13
+
14
+ def initialize(pr_title = PR_TITLE, branch_name = BRANCH_NAME)
15
+ super()
16
+ @branch_name = branch_name || BRANCH_NAME
17
+ @pr_title = pr_title || PR_TITLE
18
+ end
19
+
20
+ private
21
+
22
+ def delete_and_create_temp_neetob_dir
23
+ `rm -rf /tmp/neetob`
24
+ `mkdir /tmp/neetob`
25
+ end
26
+
27
+ def app_name_without_org_suffix(app)
28
+ app.split("/").last
29
+ end
30
+
31
+ def clone_app_in_tmp_dir(app)
32
+ `git clone --quiet git@github.com:#{app}.git /tmp/neetob/#{app_name_without_org_suffix(app)}`
33
+ end
34
+
35
+ def add_commmit_and_push_changes(app)
36
+ `#{cd_to_app_in_tmp_dir(app)} && git add . && git commit -m "#{pr_title}" && git push -u origin #{branch_name} --force`
37
+ end
38
+
39
+ def delete_local_feature_branch(app)
40
+ `#{cd_to_app_in_tmp_dir(app)} && git checkout main && git branch -D #{branch_name}`
41
+ end
42
+
43
+ def checkout_to_new_branch(app)
44
+ `#{cd_to_app_in_tmp_dir(app)} && git checkout -b #{branch_name}`
45
+ end
46
+
47
+ def checkout_to_feature_branch(app)
48
+ `#{cd_to_app_in_tmp_dir(app)} && git checkout #{branch_name}`
49
+ end
50
+
51
+ def delete_remote_feature_branch(app)
52
+ `#{cd_to_app_in_tmp_dir(app)} && git push origin --delete #{branch_name}`
53
+ end
54
+
55
+ def check_and_delete_remote_branch(app)
56
+ checkout_to_feature_branch(app)
57
+ if $?.success?
58
+ ui.info("Remote branch found with the name \"#{branch_name}\"")
59
+ delete_remote_feature_branch(app)
60
+ delete_local_feature_branch(app)
61
+ end
62
+ checkout_to_new_branch(app)
63
+ end
64
+
65
+ def cd_to_app_in_tmp_dir(app)
66
+ "cd /tmp/neetob/#{app_name_without_org_suffix(app)}"
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "compliance_fix"
6
+ require_relative "script"
7
+ require_relative "../../sub_command_base"
8
+
9
+ module Neetob
10
+ class CLI
11
+ module Github
12
+ module MakePr
13
+ class Commands < SubCommandBase
14
+ class_option :apps,
15
+ {
16
+ type: :array, aliases: "-a", default: ["*"],
17
+ desc: "Github app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web\""
18
+ }
19
+
20
+ desc "compliance-fix", "Create PRs for fixing neeto compliance in all products"
21
+ def compliance_fix
22
+ ComplianceFix.new(options[:apps], options[:sandbox]).run
23
+ end
24
+
25
+ desc "script", "Create PRs after running the given script for each product."
26
+ option :path, type: :string, aliases: "-p",
27
+ desc: "Path to UNIX executable script which will be run for each product", required: true
28
+ option :title, type: :string, aliases: "-t", desc: "Title for the PR"
29
+ option :branch, type: :string, aliases: "-b", desc: "Feature branch name for the PR"
30
+ def script
31
+ Script.new(options[:apps], options[:path], options[:title], options[:branch], options[:sandbox]).run
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
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 MakePr
11
+ class ComplianceFix < 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
+ delete_and_create_temp_neetob_dir
23
+ matching_apps.each do |app|
24
+ ui.info("\n Working on #{app} \n")
25
+ begin
26
+ clone_app_in_tmp_dir(app)
27
+ check_and_delete_remote_branch(app)
28
+ bundle_install(app)
29
+ ui.info(add_commmit_and_push_changes(app))
30
+ delete_local_feature_branch(app)
31
+ res = client.create_pull_request(app, "main", BRANCH_NAME, PR_TITLE)
32
+ ui.success("PR created in \"#{app}\" project successfully.")
33
+ rescue StandardError => e
34
+ ExceptionHandler.new(e).process
35
+ end
36
+ end
37
+ `rm -rf /tmp/neetob`
38
+ end
39
+
40
+ private
41
+
42
+ def bundle_install(app)
43
+ `#{cd_to_app_in_tmp_dir(app)} && bundle`
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,55 @@
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 MakePr
11
+ class Script < Base
12
+ attr_accessor :apps, :sandbox, :path_to_the_script_file
13
+
14
+ def initialize(apps, path_to_the_script_file, pr_title, branch_name, sandbox = false)
15
+ super(pr_title, branch_name)
16
+ @apps = apps
17
+ @sandbox = sandbox
18
+ @path_to_the_script_file = path_to_the_script_file
19
+ end
20
+
21
+ def run
22
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
23
+ delete_and_create_temp_neetob_dir
24
+ matching_apps.each do |app|
25
+ ui.info("\n Working on #{app} \n")
26
+ begin
27
+ clone_app_in_tmp_dir(app)
28
+ check_and_delete_remote_branch(app)
29
+ update_script_file_permissions
30
+ execute_script(app)
31
+ ui.info(add_commmit_and_push_changes(app))
32
+ delete_local_feature_branch(app)
33
+ res = client.create_pull_request(app, "main", branch_name, pr_title)
34
+ ui.success("PR created in \"#{app}\" project successfully.")
35
+ rescue StandardError => e
36
+ ExceptionHandler.new(e).process
37
+ end
38
+ end
39
+ `rm -rf /tmp/neetob`
40
+ end
41
+
42
+ private
43
+
44
+ def update_script_file_permissions
45
+ `chmod +x #{path_to_the_script_file}`
46
+ end
47
+
48
+ def execute_script(app)
49
+ `#{cd_to_app_in_tmp_dir(app)} && #{path_to_the_script_file}`
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Github
8
+ class ProtectBranch < Base
9
+ attr_accessor :branch_name, :required_rules_json_file_path, :apps, :sandbox
10
+
11
+ def initialize(branch_name, apps, required_rules_json_file_path = "", sandbox = false)
12
+ super()
13
+ @branch_name = branch_name
14
+ @required_rules_json_file_path = required_rules_json_file_path
15
+ @apps = apps
16
+ @sandbox = sandbox
17
+ end
18
+
19
+ def run
20
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
21
+ inform_about_default_rules_file
22
+ matching_apps.each do |app|
23
+ ui.info("\n Working on \"#{app}\" repo")
24
+ ui.info(" Updating \"#{branch_name}\" branch protection rules")
25
+ rules = read_json_file(required_rules_json_file_path || default_rules_file_path)
26
+ rules_with_symbol_keys = rules.transform_keys(&:to_sym)
27
+ client.protect_branch(app, branch_name, rules_with_symbol_keys)
28
+ ui.success("Branch protection rules updated successfully")
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def default_rules_file_path
35
+ File.expand_path("../../../../data/branch-protection-rules.json", __dir__)
36
+ end
37
+
38
+ def inform_about_default_rules_file
39
+ if required_rules_json_file_path.nil?
40
+ ui.info("Updating protection rules from the \"neetob/data/branch-protection-rules.json\" file")
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module Neetob
6
+ class CLI
7
+ module Github
8
+ class Search < Base
9
+ attr_accessor :apps, :key_to_search, :search_file_path, :sandbox
10
+
11
+ def initialize(apps, key_to_search, search_file_path, sandbox = false)
12
+ super()
13
+ @apps = apps
14
+ @key_to_search = key_to_search
15
+ @search_file_path = search_file_path
16
+ @sandbox = sandbox
17
+ end
18
+
19
+ def run
20
+ matching_apps = find_all_matching_apps(apps, :github, sandbox)
21
+ matching_apps.each do |app|
22
+ begin
23
+ ui.info("\n Searching in \"#{app}/#{search_file_path}\" for \"#{key_to_search}\"\n")
24
+ content = Base64.decode64(client.contents(app, path: search_file_path).content)
25
+ ui.error("Keyword not found") and next unless content.include? key_to_search
26
+
27
+ content.each_line do |line|
28
+ ui.success(line) if line.include?(key_to_search)
29
+ end
30
+ rescue StandardError => e
31
+ ExceptionHandler.new(e).process
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ 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 Add < Base
10
+ attr_accessor :apps, :new_users, :sandbox
11
+
12
+ def initialize(apps, new_users = [], sandbox = false)
13
+ super()
14
+ @apps = apps
15
+ @new_users = new_users
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
+ new_users.each do |user|
30
+ ui.info(`heroku access:add #{user} -a #{app}`)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+
5
+ require_relative "list"
6
+ require_relative "add"
7
+ require_relative "remove"
8
+ require_relative "../../sub_command_base"
9
+
10
+ module Neetob
11
+ class CLI
12
+ module Heroku
13
+ module Access
14
+ class Commands < SubCommandBase
15
+ class_option :apps,
16
+ {
17
+ type: :array, aliases: "-a", required: true,
18
+ desc: "Heroku app names. Can be matched using the '*' wildcard. Example: \"neeto*\" \"neeto-cal-web-staging\""
19
+ }
20
+
21
+ desc "list", "List all the users of the Heroku apps"
22
+ def list
23
+ List.new(options[:apps], options[:sandbox]).run
24
+ end
25
+
26
+ desc "add", "Add new users to the Heroku apps"
27
+ option :users, type: :array, required: true, desc: "Users' emails that need to be added to Heroku apps"
28
+ def add
29
+ Add.new(options[:apps], options[:users], options[:sandbox]).run
30
+ end
31
+
32
+ desc "remove", "Remove the users from the Heroku apps"
33
+ option :users, type: :array, required: true, desc: "Users' emails that need to be removed from the Heroku apps"
34
+ def remove
35
+ Remove.new(options[:apps], options[:users], options[:sandbox]).run
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -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