neetob 0.5.69 → 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 +35 -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 +17 -4
- 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/github_issue_creation.rb +57 -17
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/{bot_protection_enabled.rb → automatic_https_rewrites_is_enabled.rb} +11 -9
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cloudflare/main.rb +2 -2
- data/lib/neetob/cli/monthly_audit/instances_and_addons/cronitor/setup_correctly_for_landing_pages.rb +3 -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 +0 -17
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/essential_environment_variables_set.rb +0 -15
- 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 +2 -4
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/ssl_certificates_over_thirty_days_from_expiry.rb +67 -34
- data/lib/neetob/cli/monthly_audit/misc/main.rb +1 -1
- data/lib/neetob/cli/monthly_audit/misc/sparkpost_sub_account_used_for_all_apps.rb +24 -18
- data/lib/neetob/cli/monthly_audit/security/code/active_record_doctor.rb +2 -2
- data/lib/neetob/cli/monthly_audit/security/code/brakeman.rb +7 -4
- data/lib/neetob/cli/monthly_audit/security/code/bundle_audit.rb +13 -4
- data/lib/neetob/cli/monthly_audit/security/code/fasterer.rb +2 -2
- data/lib/neetob/cli/monthly_audit/security/code/yarn_audit.rb +1 -1
- data/lib/neetob/cli/monthly_audit/security/github/dependabot_prs_merged.rb +20 -5
- 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 +24 -6
- data/lib/neetob/cli/monthly_audit/instances_and_addons/neeto_deploy_or_heroku/auto_scaling_enabled.rb +0 -67
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
import { GITHUB_ORGANIZATION_BASE_URL } from "./routes";
|
|
2
|
+
import { GITHUB_TEXTS } from "./texts";
|
|
3
|
+
|
|
4
|
+
export const DEPLOY_PASSWORD_PATTERN = /^[0-9a-z]+$/i;
|
|
5
|
+
|
|
6
|
+
export const SPARKPOST_KEY_PATTERN = /^[0-9a-z•]+$/i;
|
|
7
|
+
|
|
8
|
+
export const NEETO_HEALTH_WORKSPACE = "neeto-health workspace";
|
|
9
|
+
|
|
10
|
+
export const DEPENDABOT_SETTINGS = [
|
|
11
|
+
{
|
|
12
|
+
setting: GITHUB_TEXTS.disableDependabotAlerts,
|
|
13
|
+
message: "alerts",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
setting: GITHUB_TEXTS.disableDependabotSecurity,
|
|
17
|
+
message: "security updates",
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export const PRODUCTION_APPS = [
|
|
22
|
+
{
|
|
23
|
+
name: "auth",
|
|
24
|
+
honebadgerId: "97236",
|
|
25
|
+
channelId: "3204790",
|
|
26
|
+
integrationName: "auth",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "chat",
|
|
30
|
+
honebadgerId: "84832",
|
|
31
|
+
channelId: "3204820",
|
|
32
|
+
integrationName: "chat",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "cal",
|
|
36
|
+
honebadgerId: "93329",
|
|
37
|
+
channelId: "3204806",
|
|
38
|
+
integrationName: "cal",
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "desk",
|
|
42
|
+
honebadgerId: "65613",
|
|
43
|
+
channelId: "3204802",
|
|
44
|
+
integrationName: "desk",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "kb",
|
|
48
|
+
honebadgerId: "84778",
|
|
49
|
+
channelId: "3204785",
|
|
50
|
+
integrationName: "kb",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "invoice",
|
|
54
|
+
honebadgerId: "93324",
|
|
55
|
+
channelId: "3204800",
|
|
56
|
+
integrationName: "invoice",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "form",
|
|
60
|
+
honebadgerId: "93057",
|
|
61
|
+
channelId: "3204793",
|
|
62
|
+
integrationName: "form",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "runner",
|
|
66
|
+
honebadgerId: "92480",
|
|
67
|
+
channelId: "3204813",
|
|
68
|
+
integrationName: "runner",
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: "course",
|
|
72
|
+
honebadgerId: "94742",
|
|
73
|
+
channelId: "3204784",
|
|
74
|
+
integrationName: "course",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "ci",
|
|
78
|
+
honebadgerId: "106260",
|
|
79
|
+
channelId: "3204782",
|
|
80
|
+
integrationName: "ci",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "code",
|
|
84
|
+
honebadgerId: "94798",
|
|
85
|
+
channelId: "3204804",
|
|
86
|
+
integrationName: "code",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "crm",
|
|
90
|
+
honebadgerId: "94000",
|
|
91
|
+
channelId: "3204794",
|
|
92
|
+
integrationName: "crm",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: "git",
|
|
96
|
+
honebadgerId: "107322",
|
|
97
|
+
channelId: "3204783",
|
|
98
|
+
integrationName: "git",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "planner",
|
|
102
|
+
honebadgerId: "93325",
|
|
103
|
+
channelId: "3204805",
|
|
104
|
+
integrationName: "planner",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "quiz",
|
|
108
|
+
honebadgerId: "93314",
|
|
109
|
+
channelId: "3204819",
|
|
110
|
+
integrationName: "quiz",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "record",
|
|
114
|
+
honebadgerId: "114928",
|
|
115
|
+
channelId: "3471411",
|
|
116
|
+
integrationName: "record",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "replay",
|
|
120
|
+
honebadgerId: "93321",
|
|
121
|
+
channelId: "3204803",
|
|
122
|
+
integrationName: "replay",
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: "site",
|
|
126
|
+
honebadgerId: "109700",
|
|
127
|
+
channelId: "3204791",
|
|
128
|
+
integrationName: "site",
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "tower",
|
|
132
|
+
honebadgerId: "123186",
|
|
133
|
+
channelId: "3458437",
|
|
134
|
+
integrationName: "tower",
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "wireframe",
|
|
138
|
+
honebadgerId: "93323",
|
|
139
|
+
channelId: "3204814",
|
|
140
|
+
integrationName: "wireframe",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "publish",
|
|
144
|
+
honebadgerId: "125705",
|
|
145
|
+
channelId: "3564429",
|
|
146
|
+
integrationName: "publish",
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: "engage",
|
|
150
|
+
honebadgerId: "93319",
|
|
151
|
+
channelId: "3694840",
|
|
152
|
+
integrationName: "engage",
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: "deploy",
|
|
156
|
+
honebadgerId: "104343",
|
|
157
|
+
channelId: "3204786",
|
|
158
|
+
integrationName: "deploy",
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "playdash",
|
|
162
|
+
honebadgerId: "122962",
|
|
163
|
+
channelId: "3463543",
|
|
164
|
+
integrationName: "playdash",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "pay",
|
|
168
|
+
honebadgerId: "131892",
|
|
169
|
+
channelId: "",
|
|
170
|
+
integrationName: "pay",
|
|
171
|
+
},
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
export const REPOSITORIES = [
|
|
175
|
+
{
|
|
176
|
+
name: "neeto-chat-web",
|
|
177
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-chat-web/`,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "neeto-desk-web",
|
|
181
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-desk-web/`,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "neeto-kb-web",
|
|
185
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-kb-web/`,
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
name: "neeto-invoice-web",
|
|
189
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-invoice-web/`,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "neeto-form-web",
|
|
193
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-form-web/`,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "neeto-cal-web",
|
|
197
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-cal-web/`,
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: "neeto-planner-web",
|
|
201
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-planner-web/`,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: "neeto-course-web",
|
|
205
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-course-web/`,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
name: "neeto-runner-web",
|
|
209
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-runner-web/`,
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: "neeto-wireframe-web",
|
|
213
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-wireframe-web/`,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
name: "neeto-engage-web",
|
|
217
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-engage-web/`,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
name: "neeto-quiz-web",
|
|
221
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-quiz-web/`,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: "neeto-site-web",
|
|
225
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-site-web/`,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: "neeto-crm-web",
|
|
229
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-crm-web/`,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "neeto-replay-web",
|
|
233
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-replay-web/`,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "neeto-deploy-web",
|
|
237
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-deploy-web/`,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "neeto-ci-web",
|
|
241
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-ci-web/`,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: "neeto-git-web",
|
|
245
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-git-web/`,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: "neeto-auth-web",
|
|
249
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-auth-web/`,
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
name: "neeto-wheel-web",
|
|
253
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-wheel-web/`,
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "neeto-record-web",
|
|
257
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-record-web/`,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
name: "neeto-tower-web",
|
|
261
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-tower-web/`,
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: "neeto-publish-web",
|
|
265
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-publish-web/`,
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
name: "neeto-playdash-web",
|
|
269
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-playdash-web/`,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: "neeto-code-web",
|
|
273
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-code-web/`,
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
name: "neeto-pay-web",
|
|
277
|
+
url: `${GITHUB_ORGANIZATION_BASE_URL}/neeto-pay-web/`,
|
|
278
|
+
},
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
export const DEPLOY_APPS = [
|
|
282
|
+
{
|
|
283
|
+
appName: "neeto-chat-web",
|
|
284
|
+
sparkPostName: "neetoChat",
|
|
285
|
+
workspace: "neetochathelp",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
appName: "neeto-desk-web",
|
|
289
|
+
sparkPostName: "neetoDesk",
|
|
290
|
+
workspace: "neetodeskhelp",
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
appName: "neeto-kb-web",
|
|
294
|
+
sparkPostName: "neetoKB",
|
|
295
|
+
workspace: "neetokbhelp",
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
appName: "neeto-invoice-web",
|
|
299
|
+
sparkPostName: "neetoInvoice",
|
|
300
|
+
workspace: "neetoinvoicehelp",
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
appName: "neeto-form-web",
|
|
304
|
+
sparkPostName: "neetoForm",
|
|
305
|
+
workspace: "neetoformhelp",
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
appName: "neeto-cal-web",
|
|
309
|
+
sparkPostName: "neetoCal",
|
|
310
|
+
workspace: "neetocalhelp",
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
appName: "neeto-planner-web",
|
|
314
|
+
sparkPostName: "neetoPlanner",
|
|
315
|
+
workspace: "neetoplannerhelp",
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
appName: "neeto-course-web",
|
|
319
|
+
sparkPostName: "neetoCourse",
|
|
320
|
+
workspace: "neetocoursehelp",
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
appName: "neeto-runner-web",
|
|
324
|
+
sparkPostName: "neetoRunner",
|
|
325
|
+
workspace: "neetorunnerhelp",
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
appName: "neeto-wireframe-web",
|
|
329
|
+
sparkPostName: "neetoWireframe",
|
|
330
|
+
workspace: "neetowireframehelp",
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
appName: "neeto-engage-web",
|
|
334
|
+
sparkPostName: "neetoEngage",
|
|
335
|
+
workspace: "neetoengagehelp",
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
appName: "neeto-quiz-web",
|
|
339
|
+
sparkPostName: "neetoQuiz",
|
|
340
|
+
workspace: "neetoquizhelp",
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
appName: "neeto-site-web",
|
|
344
|
+
sparkPostName: "neetoSite",
|
|
345
|
+
workspace: "neetositehelp",
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
appName: "neeto-crm-web",
|
|
349
|
+
sparkPostName: "neetoCRM",
|
|
350
|
+
workspace: "neetocrmhelp",
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
appName: "neeto-replay-web",
|
|
354
|
+
sparkPostName: "neetoReplay",
|
|
355
|
+
workspace: "neetoreplayhelp",
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
appName: "neeto-ci-web",
|
|
359
|
+
sparkPostName: "neetoCI",
|
|
360
|
+
workspace: "neetocihelp",
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
appName: "neeto-git-web",
|
|
364
|
+
sparkPostName: "neetoGit",
|
|
365
|
+
workspace: "neetogithelp",
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
appName: "neeto-auth-web",
|
|
369
|
+
sparkPostName: "neetoAuth",
|
|
370
|
+
workspace: "neetoauthhelp",
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
appName: "neeto-record-web",
|
|
374
|
+
sparkPostName: "neetoRecord",
|
|
375
|
+
workspace: "neetorecordhelp",
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
appName: "neeto-tower-web",
|
|
379
|
+
sparkPostName: "neetoTower",
|
|
380
|
+
workspace: "neetotowerhelp",
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
appName: "neeto-publish-web",
|
|
384
|
+
sparkPostName: "neetoPublish",
|
|
385
|
+
workspace: "neetopublishhelp",
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
appName: "neeto-playdash-web",
|
|
389
|
+
sparkPostName: "neetoPlaydash",
|
|
390
|
+
workspace: "neetoplaydashhelp",
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
appName: "neeto-code-web",
|
|
394
|
+
sparkPostName: "neetoCoding",
|
|
395
|
+
workspace: "neetocodehelp",
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
appName: "neeto-pay-web",
|
|
399
|
+
sparkPostName: "neetoPay",
|
|
400
|
+
workspace: "neetopayhelp",
|
|
401
|
+
},
|
|
402
|
+
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const GITHUB_ORGANIZATION_BASE_URL = "https://github.com/neetozone";
|
|
2
|
+
|
|
3
|
+
export const ROUTES = {
|
|
4
|
+
neetoDeploy: {
|
|
5
|
+
configure: (subdomain: string, app: string) =>
|
|
6
|
+
`https://${subdomain}.neetodeploy.com/admin/apps/${app}-production/configure/environment-variables`,
|
|
7
|
+
},
|
|
8
|
+
github: {
|
|
9
|
+
login: "https://github.com/login",
|
|
10
|
+
securityAnalysis: (repoUrl: string) =>
|
|
11
|
+
`${repoUrl}settings/security_analysis`,
|
|
12
|
+
},
|
|
13
|
+
honeybadger: {
|
|
14
|
+
signIn: "https://app.honeybadger.io/users/sign_in",
|
|
15
|
+
settings: {
|
|
16
|
+
general: (projectId: string) =>
|
|
17
|
+
`https://app.honeybadger.io/projects/${projectId}/edit`,
|
|
18
|
+
integrations: {
|
|
19
|
+
channels: (projectId: string) =>
|
|
20
|
+
`https://app.honeybadger.io/projects/${projectId}/channels`,
|
|
21
|
+
slack: (projectId: string, channelId: string) =>
|
|
22
|
+
`https://app.honeybadger.io/projects/${projectId}/channels/${channelId}/edit`,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
sparkPost: {
|
|
27
|
+
login: "https://app.sparkpost.com/auth",
|
|
28
|
+
apiKeys: "https://app.sparkpost.com/account/api-keys",
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const SPARKPOST_TABLE = [
|
|
2
|
+
[
|
|
3
|
+
"App",
|
|
4
|
+
"SPARKPOST_PASSWORD env variable first 4 characters same as corresponding sub-account in SparkPost dashboard",
|
|
5
|
+
"Comments",
|
|
6
|
+
"Audit Passed",
|
|
7
|
+
],
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
export const HONEYBADGER_TABLE = [
|
|
11
|
+
[
|
|
12
|
+
"App",
|
|
13
|
+
"Enable Notifications for production is turned on",
|
|
14
|
+
"GitHub is integrated to the correct project repo",
|
|
15
|
+
"Automatically create GitHub issue & Automatically re-open issue is turned on",
|
|
16
|
+
"Slack is integrated to the correct project channel in #neeto-health workspace",
|
|
17
|
+
"Comments",
|
|
18
|
+
"Audit Passed",
|
|
19
|
+
],
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export const DEPENDABOT_TABLE = [
|
|
23
|
+
[
|
|
24
|
+
"Repository",
|
|
25
|
+
"Dependabot alerts enabled",
|
|
26
|
+
"Dependabot security updates enabled",
|
|
27
|
+
"Comments",
|
|
28
|
+
"Audit Passed",
|
|
29
|
+
],
|
|
30
|
+
];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const GITHUB_TEXTS = {
|
|
2
|
+
disableDependabotAlerts: "Disable Dependabot alerts",
|
|
3
|
+
disableDependabotSecurity: "Disable Dependabot security",
|
|
4
|
+
disableDependabotActions: "Disable Dependabot on actions",
|
|
5
|
+
username: "Username",
|
|
6
|
+
password: "Password",
|
|
7
|
+
signIn: "Sign in",
|
|
8
|
+
recoveryCode: "Use a recovery code or begin",
|
|
9
|
+
placeholderCode: "XXXXXX",
|
|
10
|
+
verify: "Verify",
|
|
11
|
+
dismissMessage: "Dismiss this message",
|
|
12
|
+
dashboard: "Dashboard",
|
|
13
|
+
codeSecurity: "Code security",
|
|
14
|
+
errorMessage: "404 “This is not the web page",
|
|
15
|
+
search: "Search",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const HONEYBADGER_TEXTS = {
|
|
19
|
+
email: "Email",
|
|
20
|
+
password: "Password",
|
|
21
|
+
addProject: "Add a project",
|
|
22
|
+
signIn: "Sign in",
|
|
23
|
+
enableNotifications: "Enable notifications for production",
|
|
24
|
+
reOpenIssue: "Automatically re-open issue",
|
|
25
|
+
createIssue: "Automatically create an issue",
|
|
26
|
+
githubIntegration: (appname: string) =>
|
|
27
|
+
`GitHub - neetozone/neeto-${appname}-web`,
|
|
28
|
+
slackIntegration: (appname: string) => `Slack - #neeto-${appname}`,
|
|
29
|
+
projects: "Projects",
|
|
30
|
+
pageNotFound: "Page Not Found",
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const SPARKPOST_TEXTS = {
|
|
34
|
+
emailAddress: "Email Address",
|
|
35
|
+
password: "Password",
|
|
36
|
+
continue: "Continue",
|
|
37
|
+
welcome: "Welcome",
|
|
38
|
+
apiKeys: "API Keys",
|
|
39
|
+
hundredPerPage: "100 per page",
|
|
40
|
+
subaccount: (appName: string) => `${appName} subaccount`,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export const NEETO_DEPLOY_TEXTS = {
|
|
44
|
+
envVariable: "Add environment variable",
|
|
45
|
+
sparkPostPassword: "SPARKPOST_PASSWORD",
|
|
46
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const USER_AGENTS = [
|
|
2
|
+
"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/537.36",
|
|
3
|
+
"Mozilla/5.0 (Linux; Android 14; Pixel 8 Build/TQ1A.230805.001) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Mobile Safari/537.36",
|
|
4
|
+
"Mozilla/5.0 (Linux; Android 14; SM-G980F Build/SDM710) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Mobile Safari/537.36",
|
|
5
|
+
"Mozilla/5.0 (Linux; Android 14; OnePlus 11 Build/UDM240) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Mobile Safari/537.36",
|
|
6
|
+
"Mozilla/5.0 (Linux; Android 14; 14 Build/VD2A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Mobile Safari/537.36",
|
|
7
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Version/17.0 Safari/537.36",
|
|
8
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36",
|
|
9
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5) Gecko/20100101 Firefox/115.0",
|
|
10
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36 Edge/115.0.1901.183",
|
|
11
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36",
|
|
12
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:115.0) Gecko/20100101 Firefox/115.0",
|
|
13
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.5790.110 Safari/537.36 OPR/115.0.5790.115",
|
|
14
|
+
];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type TableRow = string[];
|
|
2
|
+
|
|
3
|
+
const generateRow = (row: TableRow) => `| ${row.join(" | ")} |\n`;
|
|
4
|
+
|
|
5
|
+
export const generateMdTable = (table: TableRow[]) => {
|
|
6
|
+
const markdownLines = [];
|
|
7
|
+
markdownLines.push(generateRow(table[0]));
|
|
8
|
+
|
|
9
|
+
markdownLines.push(
|
|
10
|
+
"| " + Array(table[0].length).fill("---").join(" | ") + " |\n"
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
for (let i = 1; i < table.length; i++) {
|
|
14
|
+
markdownLines.push(generateRow(table[i]));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return markdownLines.join("");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const addRow = (table: TableRow[], rowData: TableRow) =>
|
|
21
|
+
table.push(rowData);
|
|
22
|
+
|
|
23
|
+
export const mdLink = (text: string, url: string) => `[${text}](${url})`;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { initializeTotp } from "@neetoplaywright";
|
|
2
|
+
import { ROUTES } from "@routes";
|
|
3
|
+
import { GITHUB_TEXTS } from "@texts";
|
|
4
|
+
import { faker } from "@faker-js/faker";
|
|
5
|
+
import test, { expect } from "@playwright/test";
|
|
6
|
+
import { addRow, mdLink } from "@utils/markdown";
|
|
7
|
+
import { DEPENDABOT_TABLE } from "@constants/table";
|
|
8
|
+
import { REPOSITORIES, DEPENDABOT_SETTINGS } from "@constants/auditData";
|
|
9
|
+
|
|
10
|
+
const randomUserAgent = faker.internet.userAgent();
|
|
11
|
+
const randomTimezone = faker.location.timeZone();
|
|
12
|
+
test.use({ userAgent: randomUserAgent, timezoneId: randomTimezone });
|
|
13
|
+
|
|
14
|
+
test.describe("Dependabot", () => {
|
|
15
|
+
test.beforeEach(async ({ page }) => {
|
|
16
|
+
const totp = initializeTotp({
|
|
17
|
+
issuer: "GitHub",
|
|
18
|
+
secret: process.env.GITHUB_2FA_SECRET_KEY,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
await page.goto(ROUTES.github.login);
|
|
22
|
+
await page.waitForLoadState();
|
|
23
|
+
await page
|
|
24
|
+
.getByLabel(GITHUB_TEXTS.username)
|
|
25
|
+
.fill(process.env.GITHUB_USERNAME);
|
|
26
|
+
|
|
27
|
+
await page
|
|
28
|
+
.getByLabel(GITHUB_TEXTS.password)
|
|
29
|
+
.fill(process.env.GITHUB_PASSWORD);
|
|
30
|
+
|
|
31
|
+
await page
|
|
32
|
+
.getByRole("button", { name: GITHUB_TEXTS.signIn, exact: true })
|
|
33
|
+
.click();
|
|
34
|
+
|
|
35
|
+
const totpToken = totp.generate({ timestamp: Date.now() + 5_000 });
|
|
36
|
+
|
|
37
|
+
const verifyButton = page.getByRole("button", {
|
|
38
|
+
name: GITHUB_TEXTS.verify,
|
|
39
|
+
exact: true,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
await page.getByPlaceholder(GITHUB_TEXTS.placeholderCode).fill(totpToken);
|
|
43
|
+
(await verifyButton.isVisible()) && (await verifyButton.click());
|
|
44
|
+
|
|
45
|
+
await expect(
|
|
46
|
+
page.getByRole("link", { name: GITHUB_TEXTS.dashboard, exact: true })
|
|
47
|
+
).toBeVisible();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("Check whether dependabot is turned on for the repository", async ({
|
|
51
|
+
page,
|
|
52
|
+
}) => {
|
|
53
|
+
for (const [i, { name, url }] of REPOSITORIES.entries()) {
|
|
54
|
+
const row = [mdLink(name, url)];
|
|
55
|
+
const comments = [];
|
|
56
|
+
|
|
57
|
+
const securityHeading = page.getByRole("heading", {
|
|
58
|
+
name: GITHUB_TEXTS.codeSecurity,
|
|
59
|
+
});
|
|
60
|
+
const searchBtn = page.getByRole("button", {
|
|
61
|
+
name: GITHUB_TEXTS.search,
|
|
62
|
+
exact: true,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
await test.step(`${
|
|
66
|
+
i + 1
|
|
67
|
+
}: Check whether dependabot is enabled for ${name}`, async () => {
|
|
68
|
+
await page.goto(ROUTES.github.securityAnalysis(url));
|
|
69
|
+
await page.waitForLoadState();
|
|
70
|
+
await expect(searchBtn.or(securityHeading)).toBeVisible({
|
|
71
|
+
timeout: 30_000,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
if (await searchBtn.isVisible()) {
|
|
75
|
+
const comment = "Repository does not exist";
|
|
76
|
+
addRow(DEPENDABOT_TABLE, [name, "No", "No", "No", comment, "No"]);
|
|
77
|
+
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const { setting, message } of DEPENDABOT_SETTINGS) {
|
|
82
|
+
const isVisible = await page
|
|
83
|
+
.getByRole("button", { name: setting })
|
|
84
|
+
.first()
|
|
85
|
+
.isVisible();
|
|
86
|
+
|
|
87
|
+
const status = isVisible ? "Yes" : "No";
|
|
88
|
+
row.push(status);
|
|
89
|
+
|
|
90
|
+
if (status === "No") {
|
|
91
|
+
comments.push(`Dependabot ${message} is not enabled`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
row.push(comments.join(","));
|
|
96
|
+
row.push(row.includes("No") ? "No" : "Yes");
|
|
97
|
+
|
|
98
|
+
addRow(DEPENDABOT_TABLE, row);
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
console.log(JSON.stringify(DEPENDABOT_TABLE, null, 2));
|
|
103
|
+
});
|
|
104
|
+
});
|