neetob 0.5.68 → 0.5.77
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.
- checksums.yaml +4 -4
- data/.env +2 -1
- data/.neetoci/default.yml +1 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +44 -21
- data/README.md +11 -0
- data/bookmarks.md +113 -113
- data/data/github-labels.json +80 -45
- data/data/repo-team-leads.json +82 -0
- data/exe/neetob +1 -1
- data/lib/neetob/cli/base.rb +67 -5
- data/lib/neetob/cli/cloudflare/automatic_https_rewrites.rb +34 -0
- data/lib/neetob/cli/cloudflare/base.rb +2 -2
- data/lib/neetob/cli/cloudflare/commands.rb +7 -0
- data/lib/neetob/cli/github/active_record_doctor.rb +1 -1
- data/lib/neetob/cli/github/brakeman.rb +1 -1
- data/lib/neetob/cli/github/bundle_audit.rb +1 -1
- data/lib/neetob/cli/github/issues/helpers.rb +40 -0
- data/lib/neetob/cli/github/make_pr/base.rb +1 -1
- data/lib/neetob/cli/github/repositories/pull_requests.rb +19 -0
- data/lib/neetob/cli/github/repositories/team_leads.rb +34 -0
- data/lib/neetob/cli/github/unused_assets_audit.rb +5 -1
- data/lib/neetob/cli/monthly_audit/commands.rb +2 -1
- data/lib/neetob/cli/monthly_audit/databases/users_unique_email_index.rb +6 -1
- data/lib/neetob/cli/monthly_audit/databases/uuid_primary_key.rb +8 -0
- data/lib/neetob/cli/monthly_audit/github_issue_creation.rb +75 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/always_use_https_is_enabled.rb +11 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/automatic_https_rewrites_is_enabled.rb +43 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/dns_entry_has_proxy_status.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/main.rb +2 -2
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/minimum_tls_version_is_one_point_two.rb +11 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/spf_records_are_valid.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/ssl_tls_encryption_mode_set_to_full.rb +9 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_apps.rb +10 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_help_center.rb +12 -0
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_landing_pages.rb +15 -2
- data/lib/neetob/cli/monthly_audit/instances_and_addons/honeybadger/setup_correctly_for_apps.rb +28 -29
- data/lib/neetob/cli/monthly_audit/instances_and_addons/main.rb +5 -5
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/cloudfront_cdn_enabled.rb +11 -17
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/essential_environment_variables_set.rb +7 -10
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/main.rb +0 -3
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/scheduled_exports_enabled.rb +8 -4
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/ssl_certificates_over_thirty_days_from_expiry.rb +69 -24
- data/lib/neetob/cli/monthly_audit/misc/main.rb +1 -1
- data/lib/neetob/cli/monthly_audit/misc/redirections_working_correctly.rb +14 -1
- data/lib/neetob/cli/monthly_audit/misc/sparkpost_sub_account_used_for_all_apps.rb +24 -18
- data/lib/neetob/cli/monthly_audit/perform.rb +7 -2
- data/lib/neetob/cli/monthly_audit/security/code/active_record_doctor.rb +10 -5
- data/lib/neetob/cli/monthly_audit/security/code/brakeman.rb +10 -2
- data/lib/neetob/cli/monthly_audit/security/code/bundle_audit.rb +19 -6
- data/lib/neetob/cli/monthly_audit/security/code/checks_for_unused_assets.rb +5 -0
- data/lib/neetob/cli/monthly_audit/security/code/fasterer.rb +10 -2
- data/lib/neetob/cli/monthly_audit/security/code/yarn_audit.rb +6 -1
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_prs_merged.rb +20 -0
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_turned_on.rb +25 -21
- data/lib/neetob/cli/neeto_deploy/autoscaling_config.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/certificates.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/commands.rb +7 -0
- data/lib/neetob/cli/neeto_deploy/config_vars/list.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/config_vars/remove.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/config_vars/upsert.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/scheduled_exports.rb +1 -1
- data/lib/neetob/cli/neeto_deploy/unique_email_domains.rb +165 -0
- data/lib/neetob/cli/sre/base.rb +13 -13
- data/lib/neetob/cli/sre/check_essential_env.rb +7 -2
- data/lib/neetob/cli/sre/checklist.rb +2 -2
- data/lib/neetob/version.rb +1 -1
- data/neetob.gemspec +1 -1
- data/package.json +30 -0
- data/playwright.config.ts +39 -0
- data/scripts/config/.env.local +17 -0
- data/scripts/constants/auditData.ts +402 -0
- data/scripts/constants/routes.ts +30 -0
- data/scripts/constants/selectors.ts +4 -0
- data/scripts/constants/table.ts +30 -0
- data/scripts/constants/texts.ts +46 -0
- data/scripts/constants/userAgents.ts +14 -0
- data/scripts/utils/markdown.ts +23 -0
- data/scripts/workflows/dependabot.ts +104 -0
- data/scripts/workflows/honeybadger.ts +169 -0
- data/scripts/workflows/sparkpost.ts +204 -0
- data/tsconfig.json +35 -0
- data/yarn.lock +2216 -0
- metadata +26 -6
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/bot_protection_enabled.rb +0 -32
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/auto_scaling_enabled.rb +0 -60
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "open3"
|
|
4
|
+
|
|
5
|
+
module Neetob
|
|
6
|
+
class CLI
|
|
7
|
+
module NeetoDeploy
|
|
8
|
+
class UniqueEmailDomains < CLI::Base
|
|
9
|
+
attr_accessor :app
|
|
10
|
+
|
|
11
|
+
def initialize(app)
|
|
12
|
+
super()
|
|
13
|
+
@app = app
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
ui.info("Executing for app: #{app}")
|
|
18
|
+
query = get_query_for_app(app)
|
|
19
|
+
|
|
20
|
+
return ui.error("No query defined for app: #{app}") unless query
|
|
21
|
+
|
|
22
|
+
Open3.popen3("neetodeploy exec -a #{app}") do |stdin, stdout, stderr, wait_thr|
|
|
23
|
+
return handle_forbidden_error(stderr) if forbidden?(stderr)
|
|
24
|
+
|
|
25
|
+
send_command(stdin, "bundle exec rails console")
|
|
26
|
+
sleep(2)
|
|
27
|
+
return handle_forbidden_error(stderr) if forbidden?(stderr)
|
|
28
|
+
|
|
29
|
+
stdin.puts query
|
|
30
|
+
sleep(1)
|
|
31
|
+
stdin.puts "exit" if wait_thr.alive?
|
|
32
|
+
sleep(1)
|
|
33
|
+
stdin.puts "exit" if wait_thr.alive?
|
|
34
|
+
stdin.close
|
|
35
|
+
|
|
36
|
+
output = safely_read(stdout, "stdout")
|
|
37
|
+
errors = safely_read(stderr, "stderr")
|
|
38
|
+
|
|
39
|
+
if (exit_status = wait_thr.value.exitstatus) == 0
|
|
40
|
+
email_domains = extract_email_domains(output)
|
|
41
|
+
ui.success("Unique email domains for #{app}:")
|
|
42
|
+
|
|
43
|
+
if email_domains.empty?
|
|
44
|
+
ui.info("No email domains found")
|
|
45
|
+
ui.info("Debug: Raw output length: #{output.length}")
|
|
46
|
+
ui.info("Debug: Output preview: #{output[0..200]}...")
|
|
47
|
+
else
|
|
48
|
+
|
|
49
|
+
email_domains.each { |domain| puts domain }
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
ui.error("Command failed with exit status: #{exit_status}")
|
|
53
|
+
ui.error("Error output: #{errors}") unless errors.empty?
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
exit_status == 0
|
|
57
|
+
end
|
|
58
|
+
rescue Errno::EPIPE
|
|
59
|
+
handle_forbidden_error
|
|
60
|
+
rescue => e
|
|
61
|
+
ui.error("Exception: #{e.message}")
|
|
62
|
+
ui.error("Exception class: #{e.class}")
|
|
63
|
+
false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def forbidden?(stderr)
|
|
69
|
+
error_output = stderr.read_nonblock(1024) rescue ""
|
|
70
|
+
error_output.include?('{"error":"Forbidden"}')
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def handle_forbidden_error(stderr = nil)
|
|
74
|
+
ui.error("Access denied: You don't have permission to access this app or your session is not authenticated")
|
|
75
|
+
ui.error("Please run `neetodeploy login` and ensure you have access to the app: #{app}")
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def send_command(stdin, command)
|
|
80
|
+
stdin.puts command
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def safely_read(io, label)
|
|
84
|
+
io.read
|
|
85
|
+
rescue => e
|
|
86
|
+
ui.error("Error reading #{label}: #{e.message}")
|
|
87
|
+
""
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def get_query_for_app(app_name)
|
|
91
|
+
six_months_ago = (Time.now.utc - 6 * 30 * 24 * 60 * 60).strftime("%Y-%m-%d %H:%M:%S")
|
|
92
|
+
|
|
93
|
+
{
|
|
94
|
+
"neeto-form-web-production" =>
|
|
95
|
+
"User.joins(:forms).where('forms.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
96
|
+
|
|
97
|
+
"neeto-record-web-production" =>
|
|
98
|
+
"User.joins(:recordings).where('recordings.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
99
|
+
|
|
100
|
+
"neeto-kb-web-production" =>
|
|
101
|
+
"User.joins(:articles).where.not(articles: { slug: ['welcome', 'getting-started', 'getting-help', 'feedback'] }).pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
102
|
+
|
|
103
|
+
"neeto-code-web-production" =>
|
|
104
|
+
"User.joins(:projects).where('projects.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
105
|
+
|
|
106
|
+
"neeto-playdash-web-production" =>
|
|
107
|
+
"Organization.joins(:users, projects: :runs).where('runs.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
108
|
+
|
|
109
|
+
"neeto-desk-web-production" =>
|
|
110
|
+
"User.joins(:tickets).where.not(tickets: { number: [1,2,3,4,5] }).where('tickets.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
111
|
+
|
|
112
|
+
"neeto-invoice-web-production" =>
|
|
113
|
+
"User.joins(:time_entries).where('time_entries.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
114
|
+
|
|
115
|
+
"neeto-chat-web-production" =>
|
|
116
|
+
"User.joins(:conversations).where('conversations.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
117
|
+
|
|
118
|
+
"neeto-quiz-web-production" =>
|
|
119
|
+
"User.joins(quizzes: :attempts).where('attempts.updated_at >= ?', '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
120
|
+
|
|
121
|
+
"neeto-site-web-production" =>
|
|
122
|
+
"User.joins(sites: :pages).where('sites.updated_at >= :date OR pages.updated_at >= :date', date: '#{six_months_ago}').pluck(Arel.sql('DISTINCT SPLIT_PART(users.email, \\'@\\', 2)'))",
|
|
123
|
+
|
|
124
|
+
"neeto-cal-web-production" => <<~RUBY
|
|
125
|
+
result = ActiveRecord::Base.connection.execute("WITH active_users AS (
|
|
126
|
+
SELECT users.email AS email FROM users
|
|
127
|
+
WHERE (
|
|
128
|
+
EXISTS (
|
|
129
|
+
SELECT 1 FROM bookings_users
|
|
130
|
+
JOIN bookings ON bookings.id = bookings_users.booking_id
|
|
131
|
+
WHERE bookings.user_id = users.id AND bookings.updated_at >= '#{six_months_ago}'
|
|
132
|
+
)
|
|
133
|
+
OR EXISTS (
|
|
134
|
+
SELECT 1 FROM meetings_users
|
|
135
|
+
JOIN meetings ON meetings.id = meetings_users.meeting_id
|
|
136
|
+
WHERE meetings_users.user_id = users.id AND meetings.updated_at >= '#{six_months_ago}'
|
|
137
|
+
)
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
SELECT array_agg(DISTINCT SPLIT_PART(email, '@', 2)) AS unique_domains FROM active_users;");
|
|
141
|
+
unique_domains = result.first['unique_domains']
|
|
142
|
+
unique_domains = unique_domains[1...-1].split(',') if unique_domains.is_a?(String)
|
|
143
|
+
unique_domains
|
|
144
|
+
RUBY
|
|
145
|
+
}[app_name] || "User.pluck(:email).map { |e| e.split('@').last }.uniq"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def extract_email_domains(output)
|
|
149
|
+
domains = []
|
|
150
|
+
|
|
151
|
+
array_match = output.match(/=>\s*\n(\[.*?\])/m)
|
|
152
|
+
return [] unless array_match
|
|
153
|
+
|
|
154
|
+
array_content = array_match[1]
|
|
155
|
+
|
|
156
|
+
array_content.scan(/"([^"]+)"/).flatten.each do |domain|
|
|
157
|
+
domains << domain if domain.match?(/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
domains.uniq.sort
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
data/lib/neetob/cli/sre/base.rb
CHANGED
|
@@ -46,8 +46,6 @@ module Neetob
|
|
|
46
46
|
"neeto-replay-web-staging",
|
|
47
47
|
"neeto-site-web-production",
|
|
48
48
|
"neeto-site-web-staging",
|
|
49
|
-
"neeto-testify-web-production",
|
|
50
|
-
"neeto-testify-web-staging",
|
|
51
49
|
"neeto-tower-web-production",
|
|
52
50
|
"neeto-tower-web-staging",
|
|
53
51
|
"neeto-wireframe-web-production",
|
|
@@ -57,7 +55,9 @@ module Neetob
|
|
|
57
55
|
"neeto-playdash-web-staging",
|
|
58
56
|
"neeto-playdash-web-production",
|
|
59
57
|
"neeto-engage-web-staging",
|
|
60
|
-
"neeto-engage-web-production"
|
|
58
|
+
"neeto-engage-web-production",
|
|
59
|
+
"neeto-pay-web-production",
|
|
60
|
+
"neeto-pay-web-staging"
|
|
61
61
|
]
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -254,16 +254,6 @@ module Neetob
|
|
|
254
254
|
app: "neeto-site-web-production"
|
|
255
255
|
}
|
|
256
256
|
},
|
|
257
|
-
"NeetoTestify": {
|
|
258
|
-
"staging": {
|
|
259
|
-
dns: "neetotestify.net",
|
|
260
|
-
app: "neeto-testify-web-staging"
|
|
261
|
-
},
|
|
262
|
-
"production": {
|
|
263
|
-
dns: "neetotestify.com",
|
|
264
|
-
app: "neeto-testify-web-production"
|
|
265
|
-
}
|
|
266
|
-
},
|
|
267
257
|
"NeetoTower": {
|
|
268
258
|
"staging": {
|
|
269
259
|
dns: "neetotower.net",
|
|
@@ -303,6 +293,16 @@ module Neetob
|
|
|
303
293
|
dns: "neetoplaydash.com",
|
|
304
294
|
app: "neeto-playdash-web-production"
|
|
305
295
|
}
|
|
296
|
+
},
|
|
297
|
+
"NeetoPay": {
|
|
298
|
+
"staging": {
|
|
299
|
+
dns: "neetopay.net",
|
|
300
|
+
app: "neeto-pay-web-staging"
|
|
301
|
+
},
|
|
302
|
+
"production": {
|
|
303
|
+
dns: "neetopay.com",
|
|
304
|
+
app: "neeto-pay-web-production"
|
|
305
|
+
}
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
308
|
|
|
@@ -15,7 +15,11 @@ module Neetob
|
|
|
15
15
|
"HONEYBADGER_JS_API_KEY",
|
|
16
16
|
"NODE_MODULES_CACHE",
|
|
17
17
|
"YARN_CACHE",
|
|
18
|
-
"YARN_PRODUCTION"
|
|
18
|
+
"YARN_PRODUCTION",
|
|
19
|
+
"AUTH_APP_URL",
|
|
20
|
+
"DEFAULT_FROM_EMAIL",
|
|
21
|
+
"ORGANIZATION_SYNCING",
|
|
22
|
+
"SPARKPOST_DOMAIN"
|
|
19
23
|
]
|
|
20
24
|
REQUIRED_KEYS_HEROKU = [
|
|
21
25
|
"HEROKU_APP_NAME"
|
|
@@ -58,7 +62,7 @@ module Neetob
|
|
|
58
62
|
def check_envs_neetodeploy(app)
|
|
59
63
|
# TODO: Optimize once github.com/bigbinary/neeto-deploy-web/issues/3745 is done
|
|
60
64
|
begin
|
|
61
|
-
env_table = `neetodeploy env list -a #{app}`
|
|
65
|
+
env_table = `bundle exec neetodeploy env list -a #{app}`
|
|
62
66
|
json_parse_result = JSON.parse(env_table) rescue nil
|
|
63
67
|
if json_parse_result && json_parse_result["error"] == "Forbidden"
|
|
64
68
|
if Thread.current[:audit_mode]
|
|
@@ -73,6 +77,7 @@ module Neetob
|
|
|
73
77
|
match = line.match(/^\| (\w+) +\| (.+?) +\|$/)
|
|
74
78
|
envs[match[1]] = match[2] if match
|
|
75
79
|
end
|
|
80
|
+
REQUIRED_KEYS.filter! { |key| key != "AUTH_APP_URL" } if app == "neeto-auth-web-production"
|
|
76
81
|
required_keys = REQUIRED_KEYS + REQUIRED_KEYS_NEETODEPLOY
|
|
77
82
|
compare_envs(required_keys, envs, app)
|
|
78
83
|
rescue => exception
|
|
@@ -45,9 +45,9 @@ module Neetob
|
|
|
45
45
|
ui.info `neetob heroku autoscaling_config -a #{app_name} | sed 's/^/ /'`
|
|
46
46
|
else
|
|
47
47
|
ui.info "NeetoDeploy autoscaling status"
|
|
48
|
-
ui.info `neetodeploy autoscaling_config list -a #{app_name} | sed 's/^/ /'`
|
|
48
|
+
ui.info `bundle exec neetodeploy autoscaling_config list -a #{app_name} | sed 's/^/ /'`
|
|
49
49
|
ui.info "Scheduled exports status"
|
|
50
|
-
ui.info `neetodeploy addon scheduled_exports_enabled -a #{app_name} | sed 's/^/ /'`
|
|
50
|
+
ui.info `bundle exec neetodeploy addon scheduled_exports_enabled -a #{app_name} | sed 's/^/ /'`
|
|
51
51
|
end
|
|
52
52
|
ui.info "Validating essential envs"
|
|
53
53
|
ui.info `neetob sre check_essential_env -a #{app_name} | sed 's/^/ /'`
|
data/lib/neetob/version.rb
CHANGED
data/neetob.gemspec
CHANGED
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
|
|
|
30
30
|
spec.require_paths = ["lib"]
|
|
31
31
|
|
|
32
32
|
# Must have deps
|
|
33
|
-
spec.add_dependency "thor", "~> 1.
|
|
33
|
+
spec.add_dependency "thor", "~> 1.5.0" # for cli
|
|
34
34
|
spec.add_dependency "octokit", "~> 4.0" # for github client
|
|
35
35
|
spec.add_dependency "terminal-table", "~> 3.0.2" # for building cli table
|
|
36
36
|
spec.add_dependency "launchy", "~> 2.5.0" # for opening in browser
|
data/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "playwright-tests",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"audit:dependabot": "playwright test dependabot.ts",
|
|
8
|
+
"audit:honeybadger": "playwright test honeybadger.ts",
|
|
9
|
+
"audit:sparkpost": "playwright test sparkpost.ts"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@playwright/test": "1.56.1",
|
|
16
|
+
"@types/node": "22.10.7"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@bigbinary/neeto-cist": "1.0.17",
|
|
20
|
+
"@bigbinary/neeto-playwright-commons": "1.22.46",
|
|
21
|
+
"@bigbinary/neeto-playwright-reporter": "2.1.5",
|
|
22
|
+
"@faker-js/faker": "9.9.0",
|
|
23
|
+
"dayjs": "1.11.18",
|
|
24
|
+
"dotenv-expand": "^12.0.3",
|
|
25
|
+
"dotenv-webpack": "^8.1.1",
|
|
26
|
+
"lint-staged": "^16.2.6",
|
|
27
|
+
"puppeteer-extra-plugin-stealth": "2.11.2",
|
|
28
|
+
"ramda": "^0.32.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineConfig, devices } from "@playwright/test";
|
|
2
|
+
import dotenv from "dotenv";
|
|
3
|
+
import dotenvExpand from "dotenv-expand";
|
|
4
|
+
|
|
5
|
+
const env = dotenv.config({
|
|
6
|
+
path: `scripts/config/.env.local`,
|
|
7
|
+
});
|
|
8
|
+
dotenvExpand.expand(env);
|
|
9
|
+
|
|
10
|
+
const neetoPlaywrightReporterConfig = {
|
|
11
|
+
apiKey: process.env.PLAYDASH_API_KEY,
|
|
12
|
+
ciBuildId: new Date().toString(),
|
|
13
|
+
projectKey: "9gnVzoWsfAnbcsmZugMrVUMo",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default defineConfig({
|
|
17
|
+
testDir: "scripts",
|
|
18
|
+
fullyParallel: true,
|
|
19
|
+
forbidOnly: !!process.env.CI,
|
|
20
|
+
retries: process.env.CI ? 2 : 0,
|
|
21
|
+
workers: process.env.CI ? 1 : undefined,
|
|
22
|
+
reporter: [
|
|
23
|
+
["@bigbinary/neeto-playwright-reporter", neetoPlaywrightReporterConfig],
|
|
24
|
+
// ["line"],
|
|
25
|
+
],
|
|
26
|
+
use: {
|
|
27
|
+
trace: "on",
|
|
28
|
+
video: "on",
|
|
29
|
+
screenshot: "on",
|
|
30
|
+
},
|
|
31
|
+
timeout: 7 * 60_000,
|
|
32
|
+
projects: [
|
|
33
|
+
{
|
|
34
|
+
name: "chromium",
|
|
35
|
+
use: { ...devices["Desktop Chrome"] },
|
|
36
|
+
testMatch: "**/workflows/**/*.ts",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# GitHub credentials for Dependabot audit
|
|
2
|
+
GITHUB_USERNAME=github_username
|
|
3
|
+
GITHUB_PASSWORD=github_password
|
|
4
|
+
GITHUB_2FA_SECRET_KEY=2fa_secret_key
|
|
5
|
+
|
|
6
|
+
# Honeybadger credentials
|
|
7
|
+
HONEYBADGER_EMAIL=honeybadger@example.com
|
|
8
|
+
HONEYBADGER_PASSWORD=honeybadger_password
|
|
9
|
+
|
|
10
|
+
# Sparkpost credentials
|
|
11
|
+
SPARKPOST_EMAIL=sparkpost@example.com
|
|
12
|
+
SPARKPOST_PASSWORD=sparkpost_password
|
|
13
|
+
NEETO_DEPLOY_EMAIL=neeto_deploy@example.com
|
|
14
|
+
NEETO_AUTOMATION_FASTMAIL_API_KEY=neeto_deploy_fast_mail_api_key
|
|
15
|
+
|
|
16
|
+
# Playwright reporter
|
|
17
|
+
PLAYDASH_API_KEY=playdash_api_key
|