@friggframework/admin-scripts 2.0.0--canary.517.a353e20.0 → 2.0.0--canary.517.5b0b222.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.
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@friggframework/admin-scripts",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.517.a353e20.0",
4
+ "version": "2.0.0--canary.517.5b0b222.0",
5
5
  "description": "Admin Script Runner for Frigg - Execute maintenance and operational scripts in hosted environments",
6
6
  "dependencies": {
7
7
  "@aws-sdk/client-scheduler": "^3.588.0",
8
- "@friggframework/core": "2.0.0--canary.517.a353e20.0",
8
+ "@friggframework/core": "2.0.0--canary.517.5b0b222.0",
9
9
  "@hapi/boom": "^10.0.1",
10
10
  "express": "^4.18.2",
11
11
  "serverless-http": "^3.2.0"
12
12
  },
13
13
  "devDependencies": {
14
- "@friggframework/eslint-config": "2.0.0--canary.517.a353e20.0",
15
- "@friggframework/prettier-config": "2.0.0--canary.517.a353e20.0",
16
- "@friggframework/test": "2.0.0--canary.517.a353e20.0",
14
+ "@friggframework/eslint-config": "2.0.0--canary.517.5b0b222.0",
15
+ "@friggframework/prettier-config": "2.0.0--canary.517.5b0b222.0",
16
+ "@friggframework/test": "2.0.0--canary.517.5b0b222.0",
17
17
  "eslint": "^8.22.0",
18
18
  "jest": "^29.7.0",
19
19
  "prettier": "^2.7.1",
@@ -44,5 +44,5 @@
44
44
  "maintenance",
45
45
  "operations"
46
46
  ],
47
- "gitHead": "a353e204564567f210a23149f4fa7fdb6d779d72"
47
+ "gitHead": "5b0b222431533db4fe13b46369d88026a6fd4a19"
48
48
  }
@@ -27,11 +27,23 @@ const {
27
27
  } = require('../../adapters/scheduler-adapter-factory');
28
28
 
29
29
  describe('Admin Script Router', () => {
30
+ let server;
30
31
  let mockFactory;
31
32
  let mockRunner;
32
33
  let mockCommands;
33
34
  let mockSchedulerAdapter;
34
35
 
36
+ // One persistent HTTP server for the whole file. Using request(server) spins up
37
+ // a fresh ephemeral server per call (35+ here); under load that occasionally
38
+ // mis-serves (empty-body 404s), which is the source of the flake.
39
+ beforeAll((done) => {
40
+ server = app.listen(0, done);
41
+ });
42
+
43
+ afterAll((done) => {
44
+ server.close(done);
45
+ });
46
+
35
47
  class TestScript extends AdminScriptBase {
36
48
  static Definition = {
37
49
  name: 'test-script',
@@ -98,7 +110,7 @@ describe('Admin Script Router', () => {
98
110
 
99
111
  describe('GET /admin/scripts', () => {
100
112
  it('should list all registered scripts', async () => {
101
- const response = await request(app).get('/admin/scripts');
113
+ const response = await request(server).get('/admin/scripts');
102
114
 
103
115
  expect(response.status).toBe(200);
104
116
  expect(response.body.scripts).toHaveLength(1);
@@ -116,7 +128,7 @@ describe('Admin Script Router', () => {
116
128
  throw new Error('Factory error');
117
129
  });
118
130
 
119
- const response = await request(app).get('/admin/scripts');
131
+ const response = await request(server).get('/admin/scripts');
120
132
 
121
133
  expect(response.status).toBe(500);
122
134
  expect(response.body.error).toBe('Failed to list scripts');
@@ -125,7 +137,7 @@ describe('Admin Script Router', () => {
125
137
 
126
138
  describe('GET /admin/scripts/:scriptName', () => {
127
139
  it('should return script details', async () => {
128
- const response = await request(app).get(
140
+ const response = await request(server).get(
129
141
  '/admin/scripts/test-script'
130
142
  );
131
143
 
@@ -138,7 +150,7 @@ describe('Admin Script Router', () => {
138
150
  it('should return 404 for non-existent script', async () => {
139
151
  mockFactory.has.mockReturnValue(false);
140
152
 
141
- const response = await request(app).get(
153
+ const response = await request(server).get(
142
154
  '/admin/scripts/non-existent-script'
143
155
  );
144
156
 
@@ -157,7 +169,7 @@ describe('Admin Script Router', () => {
157
169
  metrics: { durationMs: 100 },
158
170
  });
159
171
 
160
- const response = await request(app)
172
+ const response = await request(server)
161
173
  .post('/admin/scripts/test-script')
162
174
  .send({
163
175
  params: { foo: 'bar' },
@@ -189,7 +201,7 @@ describe('Admin Script Router', () => {
189
201
  id: 'exec-456',
190
202
  });
191
203
 
192
- const response = await request(app)
204
+ const response = await request(server)
193
205
  .post('/admin/scripts/test-script')
194
206
  .send({
195
207
  params: { foo: 'bar' },
@@ -216,7 +228,7 @@ describe('Admin Script Router', () => {
216
228
  id: 'exec-789',
217
229
  });
218
230
 
219
- const response = await request(app)
231
+ const response = await request(server)
220
232
  .post('/admin/scripts/test-script')
221
233
  .send({
222
234
  params: { foo: 'bar' },
@@ -230,7 +242,7 @@ describe('Admin Script Router', () => {
230
242
  it('should return 503 when ADMIN_SCRIPT_QUEUE_URL is not set', async () => {
231
243
  delete process.env.ADMIN_SCRIPT_QUEUE_URL;
232
244
 
233
- const response = await request(app)
245
+ const response = await request(server)
234
246
  .post('/admin/scripts/test-script')
235
247
  .send({
236
248
  params: { foo: 'bar' },
@@ -244,7 +256,7 @@ describe('Admin Script Router', () => {
244
256
  it('should return 404 for non-existent script', async () => {
245
257
  mockFactory.has.mockReturnValue(false);
246
258
 
247
- const response = await request(app)
259
+ const response = await request(server)
248
260
  .post('/admin/scripts/non-existent')
249
261
  .send({
250
262
  params: {},
@@ -258,7 +270,7 @@ describe('Admin Script Router', () => {
258
270
  // TestScript.Definition.config.timeout is 300000 (> 25000)
259
271
  process.env.AWS_LAMBDA_FUNCTION_NAME = 'admin-script-router';
260
272
 
261
- const response = await request(app)
273
+ const response = await request(server)
262
274
  .post('/admin/scripts/test-script')
263
275
  .send({ params: {}, mode: 'sync' });
264
276
 
@@ -290,7 +302,7 @@ describe('Admin Script Router', () => {
290
302
  metrics: { durationMs: 1 },
291
303
  });
292
304
 
293
- const response = await request(app)
305
+ const response = await request(server)
294
306
  .post('/admin/scripts/short-script')
295
307
  .send({ params: {}, mode: 'sync' });
296
308
 
@@ -308,7 +320,7 @@ describe('Admin Script Router', () => {
308
320
  code: 'DB_ERROR',
309
321
  });
310
322
 
311
- const response = await request(app)
323
+ const response = await request(server)
312
324
  .post('/admin/scripts/test-script')
313
325
  .send({ params: { foo: 'bar' }, mode: 'async' });
314
326
 
@@ -327,7 +339,7 @@ describe('Admin Script Router', () => {
327
339
  status: 'COMPLETED',
328
340
  });
329
341
 
330
- const response = await request(app).get(
342
+ const response = await request(server).get(
331
343
  '/admin/scripts/test-script/executions/exec-123'
332
344
  );
333
345
 
@@ -343,7 +355,7 @@ describe('Admin Script Router', () => {
343
355
  code: 'EXECUTION_NOT_FOUND',
344
356
  });
345
357
 
346
- const response = await request(app).get(
358
+ const response = await request(server).get(
347
359
  '/admin/scripts/test-script/executions/non-existent'
348
360
  );
349
361
 
@@ -359,7 +371,7 @@ describe('Admin Script Router', () => {
359
371
  { id: 'exec-2', name: 'test-script', state: 'RUNNING' },
360
372
  ]);
361
373
 
362
- const response = await request(app).get(
374
+ const response = await request(server).get(
363
375
  '/admin/scripts/test-script/executions'
364
376
  );
365
377
 
@@ -376,7 +388,7 @@ describe('Admin Script Router', () => {
376
388
  it('should accept query parameters (status maps to state, limit is bounded)', async () => {
377
389
  mockCommands.findExecutionsByName.mockResolvedValue([]);
378
390
 
379
- await request(app).get(
391
+ await request(server).get(
380
392
  '/admin/scripts/test-script/executions?status=COMPLETED&limit=10'
381
393
  );
382
394
 
@@ -410,7 +422,7 @@ describe('Admin Script Router', () => {
410
422
  .fn()
411
423
  .mockResolvedValue(dbSchedule);
412
424
 
413
- const response = await request(app).get(
425
+ const response = await request(server).get(
414
426
  '/admin/scripts/test-script/schedule'
415
427
  );
416
428
 
@@ -441,7 +453,7 @@ describe('Admin Script Router', () => {
441
453
 
442
454
  mockFactory.get.mockReturnValue(ScheduledTestScript);
443
455
 
444
- const response = await request(app).get(
456
+ const response = await request(server).get(
445
457
  '/admin/scripts/test-script/schedule'
446
458
  );
447
459
 
@@ -455,7 +467,7 @@ describe('Admin Script Router', () => {
455
467
  .fn()
456
468
  .mockResolvedValue(null);
457
469
 
458
- const response = await request(app).get(
470
+ const response = await request(server).get(
459
471
  '/admin/scripts/test-script/schedule'
460
472
  );
461
473
 
@@ -467,7 +479,7 @@ describe('Admin Script Router', () => {
467
479
  it('should return 404 for non-existent script', async () => {
468
480
  mockFactory.has.mockReturnValue(false);
469
481
 
470
- const response = await request(app).get(
482
+ const response = await request(server).get(
471
483
  '/admin/scripts/non-existent/schedule'
472
484
  );
473
485
 
@@ -493,7 +505,7 @@ describe('Admin Script Router', () => {
493
505
  .fn()
494
506
  .mockResolvedValue(newSchedule);
495
507
 
496
- const response = await request(app)
508
+ const response = await request(server)
497
509
  .put('/admin/scripts/test-script/schedule')
498
510
  .send({
499
511
  enabled: true,
@@ -530,7 +542,7 @@ describe('Admin Script Router', () => {
530
542
  .fn()
531
543
  .mockResolvedValue(updatedSchedule);
532
544
 
533
- const response = await request(app)
545
+ const response = await request(server)
534
546
  .put('/admin/scripts/test-script/schedule')
535
547
  .send({
536
548
  enabled: false,
@@ -542,7 +554,7 @@ describe('Admin Script Router', () => {
542
554
  });
543
555
 
544
556
  it('should require enabled field', async () => {
545
- const response = await request(app)
557
+ const response = await request(server)
546
558
  .put('/admin/scripts/test-script/schedule')
547
559
  .send({
548
560
  cronExpression: '0 12 * * *',
@@ -553,7 +565,7 @@ describe('Admin Script Router', () => {
553
565
  });
554
566
 
555
567
  it('should require cronExpression when enabled is true', async () => {
556
- const response = await request(app)
568
+ const response = await request(server)
557
569
  .put('/admin/scripts/test-script/schedule')
558
570
  .send({
559
571
  enabled: true,
@@ -566,7 +578,7 @@ describe('Admin Script Router', () => {
566
578
  it('should return 404 for non-existent script', async () => {
567
579
  mockFactory.has.mockReturnValue(false);
568
580
 
569
- const response = await request(app)
581
+ const response = await request(server)
570
582
  .put('/admin/scripts/non-existent/schedule')
571
583
  .send({
572
584
  enabled: true,
@@ -601,7 +613,7 @@ describe('Admin Script Router', () => {
601
613
  scheduleName: 'frigg-script-test-script',
602
614
  });
603
615
 
604
- const response = await request(app)
616
+ const response = await request(server)
605
617
  .put('/admin/scripts/test-script/schedule')
606
618
  .send({
607
619
  enabled: true,
@@ -648,7 +660,7 @@ describe('Admin Script Router', () => {
648
660
  .mockResolvedValue(existingSchedule);
649
661
  mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
650
662
 
651
- const response = await request(app)
663
+ const response = await request(server)
652
664
  .put('/admin/scripts/test-script/schedule')
653
665
  .send({
654
666
  enabled: false,
@@ -683,7 +695,7 @@ describe('Admin Script Router', () => {
683
695
  new Error('AWS Scheduler API error')
684
696
  );
685
697
 
686
- const response = await request(app)
698
+ const response = await request(server)
687
699
  .put('/admin/scripts/test-script/schedule')
688
700
  .send({
689
701
  enabled: true,
@@ -711,7 +723,7 @@ describe('Admin Script Router', () => {
711
723
  },
712
724
  });
713
725
 
714
- const response = await request(app).delete(
726
+ const response = await request(server).delete(
715
727
  '/admin/scripts/test-script/schedule'
716
728
  );
717
729
 
@@ -745,7 +757,7 @@ describe('Admin Script Router', () => {
745
757
 
746
758
  mockFactory.get.mockReturnValue(ScheduledTestScript);
747
759
 
748
- const response = await request(app).delete(
760
+ const response = await request(server).delete(
749
761
  '/admin/scripts/test-script/schedule'
750
762
  );
751
763
 
@@ -760,7 +772,7 @@ describe('Admin Script Router', () => {
760
772
  deletedCount: 0,
761
773
  });
762
774
 
763
- const response = await request(app).delete(
775
+ const response = await request(server).delete(
764
776
  '/admin/scripts/test-script/schedule'
765
777
  );
766
778
 
@@ -774,7 +786,7 @@ describe('Admin Script Router', () => {
774
786
  it('should return 404 for non-existent script', async () => {
775
787
  mockFactory.has.mockReturnValue(false);
776
788
 
777
- const response = await request(app).delete(
789
+ const response = await request(server).delete(
778
790
  '/admin/scripts/non-existent/schedule'
779
791
  );
780
792
 
@@ -797,7 +809,7 @@ describe('Admin Script Router', () => {
797
809
  });
798
810
  mockSchedulerAdapter.deleteSchedule.mockResolvedValue();
799
811
 
800
- const response = await request(app).delete(
812
+ const response = await request(server).delete(
801
813
  '/admin/scripts/test-script/schedule'
802
814
  );
803
815
 
@@ -819,7 +831,7 @@ describe('Admin Script Router', () => {
819
831
  },
820
832
  });
821
833
 
822
- const response = await request(app).delete(
834
+ const response = await request(server).delete(
823
835
  '/admin/scripts/test-script/schedule'
824
836
  );
825
837
 
@@ -843,7 +855,7 @@ describe('Admin Script Router', () => {
843
855
  new Error('Scheduler delete failed')
844
856
  );
845
857
 
846
- const response = await request(app).delete(
858
+ const response = await request(server).delete(
847
859
  '/admin/scripts/test-script/schedule'
848
860
  );
849
861