@geek-fun/serverlessinsight 0.6.14 → 0.7.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/AGENTS.md +405 -10
- package/README.md +1 -0
- package/dist/package.json +8 -2
- package/dist/src/commands/deploy.js +4 -0
- package/dist/src/commands/destroy.js +4 -0
- package/dist/src/common/credentials.js +12 -0
- package/dist/src/common/providerEnum.js +1 -0
- package/dist/src/common/runtimeMapper.js +24 -3
- package/dist/src/common/volcengineClient/apigwOperations.js +271 -0
- package/dist/src/common/volcengineClient/iamOperations.js +349 -0
- package/dist/src/common/volcengineClient/index.js +99 -0
- package/dist/src/common/volcengineClient/tlsOperations.js +256 -0
- package/dist/src/common/volcengineClient/tosOperations.js +440 -0
- package/dist/src/common/volcengineClient/types.js +26 -0
- package/dist/src/common/volcengineClient/vefaasOperations.js +386 -0
- package/dist/src/lang/en.js +120 -0
- package/dist/src/lang/zh-CN.js +119 -0
- package/dist/src/stack/aliyunStack/fc3Resource.js +18 -3
- package/dist/src/stack/deploy.js +4 -0
- package/dist/src/stack/volcengineStack/apigwExecutor.js +87 -0
- package/dist/src/stack/volcengineStack/apigwPlanner.js +110 -0
- package/dist/src/stack/volcengineStack/apigwResource.js +302 -0
- package/dist/src/stack/volcengineStack/apigwTypes.js +106 -0
- package/dist/src/stack/volcengineStack/deployer.js +59 -0
- package/dist/src/stack/volcengineStack/destroyer.js +72 -0
- package/dist/src/stack/volcengineStack/index.js +44 -0
- package/dist/src/stack/volcengineStack/planner.js +27 -0
- package/dist/src/stack/volcengineStack/tosExecutor.js +106 -0
- package/dist/src/stack/volcengineStack/tosPlanner.js +96 -0
- package/dist/src/stack/volcengineStack/tosResource.js +103 -0
- package/dist/src/stack/volcengineStack/tosTypes.js +65 -0
- package/dist/src/stack/volcengineStack/vefaasExecutor.js +102 -0
- package/dist/src/stack/volcengineStack/vefaasPlanner.js +84 -0
- package/dist/src/stack/volcengineStack/vefaasResource.js +513 -0
- package/dist/src/stack/volcengineStack/vefaasTypes.js +75 -0
- package/dist/src/types/domains/state.js +3 -0
- package/dist/src/validator/functionSchema.js +13 -0
- package/dist/src/validator/rootSchema.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -2
- package/samples/volcengine-poc-advanced.yml +59 -0
- package/samples/volcengine-poc-api.yml +31 -0
- package/samples/volcengine-poc-bucket.yml +17 -0
- package/samples/volcengine-poc-function.yml +19 -0
- package/samples/volcengine-poc-vpc.yml +34 -0
package/AGENTS.md
CHANGED
|
@@ -247,22 +247,99 @@ logger.error(lang.__('FAILED_TO_DEPLOY_STACK', { error }));
|
|
|
247
247
|
|
|
248
248
|
### Testing
|
|
249
249
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
250
|
+
**Test Folder Structure**:
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
tests/
|
|
254
|
+
├── fixtures/ # Test fixtures (YAML configs, artifacts)
|
|
255
|
+
├── unit/ # Unit tests (end with .test.ts)
|
|
256
|
+
│ ├── common/
|
|
257
|
+
│ ├── stack/
|
|
258
|
+
│ └── ...
|
|
259
|
+
└── service/ # Service tests (end with .spec.test.ts)
|
|
260
|
+
└── ...
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Test Commands**:
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# Run all tests
|
|
267
|
+
npm test
|
|
268
|
+
|
|
269
|
+
# Run unit tests only
|
|
270
|
+
npm run test:unit
|
|
271
|
+
|
|
272
|
+
# Run service tests only
|
|
273
|
+
npm run test:service
|
|
274
|
+
|
|
275
|
+
# Run CI tests
|
|
276
|
+
npm run test:ci
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Unit Tests** (`.test.ts`):
|
|
280
|
+
|
|
281
|
+
- Test individual functions/modules in complete isolation
|
|
282
|
+
- Mock ALL external dependencies (SDK clients, file system, network)
|
|
283
|
+
- Focus on business logic and edge cases
|
|
284
|
+
- Run fast (< 100ms per test)
|
|
285
|
+
- Located in `tests/unit/`
|
|
286
|
+
|
|
287
|
+
**Service Tests** (`.spec.test.ts`):
|
|
288
|
+
|
|
289
|
+
- Test the complete flow from command entry to final result
|
|
290
|
+
- Mock ONLY external cloud SDK clients
|
|
291
|
+
- Test framework internals: parser → planner → executor → state
|
|
292
|
+
- Verify component interaction and state consistency
|
|
293
|
+
- Run slower (1-10s per test)
|
|
294
|
+
- Located in `tests/service/`
|
|
295
|
+
|
|
296
|
+
**When to Write Which Test**:
|
|
297
|
+
|
|
298
|
+
| Scenario | Unit Test | Service Test |
|
|
299
|
+
| ----------------------------------- | --------- | ------------ |
|
|
300
|
+
| New utility function | ✅ | ❌ |
|
|
301
|
+
| New SDK operation wrapper | ✅ | ❌ |
|
|
302
|
+
| New resource planner | ✅ | ❌ |
|
|
303
|
+
| Deploy command flow | ❌ | ✅ |
|
|
304
|
+
| State persistence across operations | ❌ | ✅ |
|
|
305
|
+
| Error handling in full flow | ❌ | ✅ |
|
|
306
|
+
|
|
307
|
+
**Mock Strategy**:
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Unit Test: Mock everything external
|
|
311
|
+
jest.mock('../../../../src/common/aliyunClient', () => ({
|
|
312
|
+
createAliyunClient: jest.fn(() => ({
|
|
313
|
+
fc3: { createFunction: jest.fn() },
|
|
314
|
+
})),
|
|
315
|
+
}));
|
|
316
|
+
|
|
317
|
+
// Service Test: Mock only cloud SDK
|
|
318
|
+
const mockCloudClient = {
|
|
319
|
+
fc3: { createFunction: jest.fn() },
|
|
320
|
+
apigw: { createApi: jest.fn() },
|
|
321
|
+
};
|
|
322
|
+
// Use real parser, real planner, real executor
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**CRITICAL: Test Coverage Requirements**
|
|
326
|
+
|
|
327
|
+
- Coverage threshold is set to **85%** for all metrics (branches, functions, lines, statements)
|
|
328
|
+
- **NEVER modify the coverage threshold** in `jest.config.js`
|
|
329
|
+
- If tests fail due to coverage, add more tests - do not lower the threshold
|
|
330
|
+
- This is a mandatory quality gate for the framework
|
|
331
|
+
|
|
332
|
+
**Unit Test Example**:
|
|
255
333
|
|
|
256
334
|
```typescript
|
|
257
335
|
describe('updateResource', () => {
|
|
258
336
|
it('should update resource and refresh state from provider', async () => {
|
|
259
|
-
|
|
260
|
-
|
|
337
|
+
const mockedFc3Operations = {
|
|
338
|
+
updateFunctionConfiguration: jest.fn(),
|
|
339
|
+
};
|
|
261
340
|
|
|
262
|
-
|
|
263
|
-
const result = await updateResource(mockContext, testFunction, initialState);
|
|
341
|
+
await updateResource(mockContext, testFunction, initialState);
|
|
264
342
|
|
|
265
|
-
// Assert
|
|
266
343
|
expect(mockedFc3Operations.updateFunctionConfiguration).toHaveBeenCalledWith(
|
|
267
344
|
expect.objectContaining({ functionName: 'test-function' }),
|
|
268
345
|
);
|
|
@@ -270,6 +347,284 @@ describe('updateResource', () => {
|
|
|
270
347
|
});
|
|
271
348
|
```
|
|
272
349
|
|
|
350
|
+
**Service Test Example**:
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
describe('Deploy Flow', () => {
|
|
354
|
+
it('should parse YAML, generate plan, execute, and save state', async () => {
|
|
355
|
+
const mockClient = createMockAliyunClient();
|
|
356
|
+
const config = loadTestConfig('fixtures/deploy-fixtures/oneFc');
|
|
357
|
+
|
|
358
|
+
await deployCommand({ config, client: mockClient });
|
|
359
|
+
|
|
360
|
+
expect(mockClient.fc3.createFunction).toHaveBeenCalled();
|
|
361
|
+
const state = await loadState(config.app, config.service);
|
|
362
|
+
expect(state.resources).toHaveLength(1);
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## Test Architecture & Rules (CRITICAL)
|
|
368
|
+
|
|
369
|
+
### Test Pyramid
|
|
370
|
+
|
|
371
|
+
```
|
|
372
|
+
/\
|
|
373
|
+
/ \
|
|
374
|
+
/ E2E \ (Future: Full integration tests)
|
|
375
|
+
/--------\
|
|
376
|
+
/ Service \ (Integration-style, mock ONLY cloud SDKs)
|
|
377
|
+
/------------\
|
|
378
|
+
/ Unit \ (Isolated, mock ALL externals)
|
|
379
|
+
/----------------\
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Unit Test Rules (`.test.ts`)
|
|
383
|
+
|
|
384
|
+
**Purpose**: Test individual functions/modules in complete isolation
|
|
385
|
+
|
|
386
|
+
**DO**:
|
|
387
|
+
|
|
388
|
+
- Mock ALL external dependencies (SDK clients, file system, network, logger)
|
|
389
|
+
- Test pure business logic
|
|
390
|
+
- Use inline `jest.mock()` for dependencies
|
|
391
|
+
- Keep tests fast (< 100ms)
|
|
392
|
+
- Test edge cases and error handling
|
|
393
|
+
- Use descriptive test names that explain the scenario
|
|
394
|
+
|
|
395
|
+
**DON'T**:
|
|
396
|
+
|
|
397
|
+
- Import real cloud SDKs
|
|
398
|
+
- Access real file system
|
|
399
|
+
- Make network calls
|
|
400
|
+
- Test multiple functions together
|
|
401
|
+
- Rely on external state
|
|
402
|
+
|
|
403
|
+
**Example**:
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
// tests/unit/common/aliyunClient/fc3Operations.test.ts
|
|
407
|
+
import { createFc3Operations } from '../../../../src/common/aliyunClient/fc3Operations';
|
|
408
|
+
|
|
409
|
+
jest.mock('../../../../src/common/logger', () => ({
|
|
410
|
+
logger: { info: jest.fn(), warn: jest.fn(), error: jest.fn() },
|
|
411
|
+
}));
|
|
412
|
+
|
|
413
|
+
jest.mock('../../../../src/lang', () => ({
|
|
414
|
+
lang: { __: (key: string) => key },
|
|
415
|
+
}));
|
|
416
|
+
|
|
417
|
+
const mockFc3SdkClient = {
|
|
418
|
+
createFunction: jest.fn(),
|
|
419
|
+
getFunction: jest.fn(),
|
|
420
|
+
deleteFunction: jest.fn(),
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
describe('createFc3Operations', () => {
|
|
424
|
+
let operations: ReturnType<typeof createFc3Operations>;
|
|
425
|
+
|
|
426
|
+
beforeEach(() => {
|
|
427
|
+
operations = createFc3Operations(mockFc3SdkClient as any);
|
|
428
|
+
jest.clearAllMocks();
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should create function successfully', async () => {
|
|
432
|
+
mockFc3SdkClient.createFunction.mockResolvedValue({ body: { functionName: 'test-fn' } });
|
|
433
|
+
|
|
434
|
+
const result = await operations.createFunction({ functionName: 'test-fn' }, 'base64code');
|
|
435
|
+
|
|
436
|
+
expect(result).toEqual({ functionName: 'test-fn' });
|
|
437
|
+
expect(mockFc3SdkClient.createFunction).toHaveBeenCalledWith(
|
|
438
|
+
expect.objectContaining({ functionName: 'test-fn' }),
|
|
439
|
+
'base64code',
|
|
440
|
+
);
|
|
441
|
+
});
|
|
442
|
+
});
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Service Test Rules (`.spec.test.ts`)
|
|
446
|
+
|
|
447
|
+
**Purpose**: Test complete flows from command entry to final result
|
|
448
|
+
|
|
449
|
+
**DO**:
|
|
450
|
+
|
|
451
|
+
- Mock ONLY external cloud SDK clients via `createMockAliyunClient()` / `createMockTencentClient()`
|
|
452
|
+
- Use REAL internal modules (parser, planner, executor, state manager, lock manager)
|
|
453
|
+
- Use REAL fixture files from `tests/fixtures/`
|
|
454
|
+
- Test end-to-end scenarios
|
|
455
|
+
- Verify state persistence and component interactions
|
|
456
|
+
- Use `jest.mock()` at the top level for SDK modules only
|
|
457
|
+
|
|
458
|
+
**DON'T**:
|
|
459
|
+
|
|
460
|
+
- Mock internal modules (parser, planner, executor, stateManager, lockManager, etc.)
|
|
461
|
+
- Mock file system operations (use real fixtures)
|
|
462
|
+
- Mock logger (service tests can log)
|
|
463
|
+
- Mock hashUtils or other utilities
|
|
464
|
+
- Override `jest.requireActual()` - let internal code run normally
|
|
465
|
+
|
|
466
|
+
**CRITICAL**: Service tests are integration tests. They verify that all internal components work together correctly. Over-mocking defeats their purpose.
|
|
467
|
+
|
|
468
|
+
**Example**:
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
// tests/service/deploy-flow.spec.test.ts
|
|
472
|
+
import { deploy } from '../../src/commands/deploy';
|
|
473
|
+
import { createMockAliyunClient } from './mockCloudClient';
|
|
474
|
+
|
|
475
|
+
// ONLY mock external SDK
|
|
476
|
+
jest.mock('../../src/common/aliyunClient', () => ({
|
|
477
|
+
createAliyunClient: jest.fn(),
|
|
478
|
+
}));
|
|
479
|
+
|
|
480
|
+
jest.mock('../../src/common/imsClient', () => ({
|
|
481
|
+
getIamInfo: jest.fn().mockResolvedValue({
|
|
482
|
+
accountId: '123456789012',
|
|
483
|
+
displayName: 'Test User',
|
|
484
|
+
userId: 'test-user-id',
|
|
485
|
+
}),
|
|
486
|
+
}));
|
|
487
|
+
|
|
488
|
+
jest.mock('../../src/common/logger', () => ({
|
|
489
|
+
logger: { info: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn() },
|
|
490
|
+
}));
|
|
491
|
+
|
|
492
|
+
jest.mock('../../src/lang', () => ({
|
|
493
|
+
lang: { __: (key: string) => key },
|
|
494
|
+
}));
|
|
495
|
+
|
|
496
|
+
const mockCreateAliyunClient = require('../../src/common/aliyunClient').createAliyunClient;
|
|
497
|
+
|
|
498
|
+
describe('Deploy Flow Service Test', () => {
|
|
499
|
+
let mockClient: ReturnType<typeof createMockAliyunClient>;
|
|
500
|
+
|
|
501
|
+
beforeEach(() => {
|
|
502
|
+
jest.clearAllMocks();
|
|
503
|
+
mockClient = createMockAliyunClient();
|
|
504
|
+
mockCreateAliyunClient.mockReturnValue(mockClient);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
it('should deploy FC3 function and save state', async () => {
|
|
508
|
+
// Use REAL fixtures, REAL parser, REAL planner, REAL executor
|
|
509
|
+
await deploy({
|
|
510
|
+
location: path.join(__dirname, '../fixtures'),
|
|
511
|
+
stage: 'dev',
|
|
512
|
+
autoApprove: true,
|
|
513
|
+
region: 'cn-hangzhou',
|
|
514
|
+
provider: 'aliyun',
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// Verify cloud SDK was called correctly
|
|
518
|
+
expect(mockClient.fc3.createFunction).toHaveBeenCalled();
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Mock Cloud Client Pattern
|
|
524
|
+
|
|
525
|
+
**Location**: `tests/service/mockCloudClient.ts`
|
|
526
|
+
|
|
527
|
+
All service tests should use the shared mock cloud client:
|
|
528
|
+
|
|
529
|
+
```typescript
|
|
530
|
+
// Create mock client with all services
|
|
531
|
+
const mockClient = createMockAliyunClient();
|
|
532
|
+
|
|
533
|
+
// Configure specific behavior per test
|
|
534
|
+
mockClient.fc3.getFunction.mockRejectedValueOnce({ code: 'FunctionNotFound' });
|
|
535
|
+
mockClient.fc3.createFunction.mockResolvedValue({ body: { functionName: 'test-fn' } });
|
|
536
|
+
|
|
537
|
+
// Return from mocked createAliyunClient
|
|
538
|
+
mockCreateAliyunClient.mockReturnValue(mockClient);
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
**Services to Mock**:
|
|
542
|
+
|
|
543
|
+
- `fc3` - Function Compute
|
|
544
|
+
- `apigw` - API Gateway
|
|
545
|
+
- `oss` - Object Storage Service
|
|
546
|
+
- `sls` - Log Service
|
|
547
|
+
- `ram` - Resource Access Management
|
|
548
|
+
- `nas` - Network Attached Storage
|
|
549
|
+
- `rds` - Relational Database Service
|
|
550
|
+
- `ecs` - Elastic Compute Service
|
|
551
|
+
- `es` - Elasticsearch Serverless
|
|
552
|
+
- `dns` - DNS (for domain operations)
|
|
553
|
+
- `cas` - Certificate Authority Service
|
|
554
|
+
|
|
555
|
+
### Common Mistakes to Avoid
|
|
556
|
+
|
|
557
|
+
**WRONG - Over-mocking in service tests**:
|
|
558
|
+
|
|
559
|
+
```typescript
|
|
560
|
+
// DON'T DO THIS in service tests
|
|
561
|
+
jest.mock('../../src/parser', () => ({
|
|
562
|
+
parseYaml: jest.fn(() => ({
|
|
563
|
+
/* mock data */
|
|
564
|
+
})),
|
|
565
|
+
}));
|
|
566
|
+
|
|
567
|
+
jest.mock('../../src/common/stateManager', () => ({
|
|
568
|
+
getResource: jest.fn(),
|
|
569
|
+
setResource: jest.fn(),
|
|
570
|
+
}));
|
|
571
|
+
|
|
572
|
+
jest.mock('../../src/common/lockManager', () => ({
|
|
573
|
+
withLock: jest.fn(),
|
|
574
|
+
}));
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
**CORRECT - Only mock external SDKs**:
|
|
578
|
+
|
|
579
|
+
```typescript
|
|
580
|
+
// DO THIS - only mock cloud SDK
|
|
581
|
+
jest.mock('../../src/common/aliyunClient', () => ({
|
|
582
|
+
createAliyunClient: jest.fn(),
|
|
583
|
+
}));
|
|
584
|
+
|
|
585
|
+
jest.mock('../../src/common/imsClient', () => ({
|
|
586
|
+
getIamInfo: jest.fn().mockResolvedValue({
|
|
587
|
+
/* IAM data */
|
|
588
|
+
}),
|
|
589
|
+
}));
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Test File Naming
|
|
593
|
+
|
|
594
|
+
- **Unit tests**: `*.test.ts` (e.g., `fc3Resource.test.ts`)
|
|
595
|
+
- **Service tests**: `*.spec.test.ts` (e.g., `deploy-flow.spec.test.ts`)
|
|
596
|
+
- **Fixtures**: `tests/fixtures/` (YAML configs, artifacts, state files)
|
|
597
|
+
|
|
598
|
+
### Running Tests
|
|
599
|
+
|
|
600
|
+
```bash
|
|
601
|
+
# All tests
|
|
602
|
+
npm test
|
|
603
|
+
|
|
604
|
+
# Unit tests only (fast, isolated)
|
|
605
|
+
npm run test:unit
|
|
606
|
+
|
|
607
|
+
# Service tests only (slower, integration)
|
|
608
|
+
npm run test:service
|
|
609
|
+
|
|
610
|
+
# CI mode (no coverage, faster)
|
|
611
|
+
npm run test:ci
|
|
612
|
+
|
|
613
|
+
# Specific test file
|
|
614
|
+
npm test -- tests/unit/common/aliyunClient/fc3Operations.test.ts
|
|
615
|
+
|
|
616
|
+
# Test name pattern
|
|
617
|
+
npm test -- --testNamePattern="should create function"
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Coverage Requirements
|
|
621
|
+
|
|
622
|
+
- **Minimum 85%** for all metrics (branches, functions, lines, statements)
|
|
623
|
+
- **NEVER lower the threshold** in `jest.config.js`
|
|
624
|
+
- If coverage fails, add more tests
|
|
625
|
+
- Unit tests should cover edge cases
|
|
626
|
+
- Service tests should cover full flows
|
|
627
|
+
|
|
273
628
|
## Formatting
|
|
274
629
|
|
|
275
630
|
Prettier configuration (`.prettierrc`):
|
|
@@ -370,3 +725,43 @@ export const createRamOperations = (ramClient: RamSdkClient) => ({
|
|
|
370
725
|
- State is stored in `.serverlessinsight/state-{app}-{service}.json`
|
|
371
726
|
- Use `setResource`, `getResource`, `removeResource` from `src/common/stateManager`
|
|
372
727
|
- Resources have a `status`: `'ready'` | `'tainted'`
|
|
728
|
+
|
|
729
|
+
## Commit Policy - CRITICAL
|
|
730
|
+
|
|
731
|
+
**NEVER commit changes unless the user explicitly requests it.**
|
|
732
|
+
|
|
733
|
+
- Do NOT commit after implementing features
|
|
734
|
+
- Do NOT commit after fixing bugs
|
|
735
|
+
- Do NOT commit after refactoring
|
|
736
|
+
- Do NOT commit for "cleanliness" or "convenience"
|
|
737
|
+
- Wait for explicit user instruction like "commit the changes" or "create a commit"
|
|
738
|
+
|
|
739
|
+
**Rationale**: Users may want to:
|
|
740
|
+
|
|
741
|
+
- Review changes before committing
|
|
742
|
+
- Combine multiple changes into one commit
|
|
743
|
+
- Split changes into different commits
|
|
744
|
+
- Test changes before committing
|
|
745
|
+
- Discard changes without polluting git history
|
|
746
|
+
|
|
747
|
+
**If you accidentally commit**: Immediately revert and apologize.
|
|
748
|
+
|
|
749
|
+
## Commit Policy - CRITICAL
|
|
750
|
+
|
|
751
|
+
**NEVER commit changes unless the user explicitly requests it.**
|
|
752
|
+
|
|
753
|
+
- Do NOT commit after implementing features
|
|
754
|
+
- Do NOT commit after fixing bugs
|
|
755
|
+
- Do NOT commit after refactoring
|
|
756
|
+
- Do NOT commit for "cleanliness" or "convenience"
|
|
757
|
+
- Wait for explicit user instruction like "commit the changes" or "create a commit"
|
|
758
|
+
|
|
759
|
+
**Rationale**: Users may want to:
|
|
760
|
+
|
|
761
|
+
- Review changes before committing
|
|
762
|
+
- Combine multiple changes into one commit
|
|
763
|
+
- Split changes into different commits
|
|
764
|
+
- Test changes before committing
|
|
765
|
+
- Discard changes without polluting git history
|
|
766
|
+
|
|
767
|
+
**If you accidentally commit**: Immediately revert and apologize.
|
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ ServerlessInsight supports the following cloud providers:
|
|
|
52
52
|
| ----------------- | ---------------- | -------------- | -------------- | ---------------- | ------- |
|
|
53
53
|
| **Alibaba Cloud** | ✅ FC3 | ✅ API Gateway | ✅ OSS | ✅ RDS, OTS, ESS | Stable |
|
|
54
54
|
| **Tencent Cloud** | ✅ SCF | 🚧 Coming Soon | ✅ COS | ✅ TDSQL-C | Stable |
|
|
55
|
+
| **Volcengine** | ✅ veFaaS | ✅ API Gateway | ✅ TOS | — | Stable |
|
|
55
56
|
| **Huawei Cloud** | ✅ FunctionGraph | 🚧 Coming Soon | 🚧 Coming Soon | 🚧 Coming Soon | Beta |
|
|
56
57
|
| **AWS** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
|
57
58
|
| **Azure** | 🔜 Planned | 🔜 Planned | 🔜 Planned | 🔜 Planned | Planned |
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geek-fun/serverlessinsight",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Full life cycle cross providers serverless application management for your fast-growing business.",
|
|
5
5
|
"homepage": "https://serverlessinsight.geekfun.club",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
12
12
|
"test": "cross-env DEBUG=ServerlessInsight jest --runInBand --detectOpenHandles --coverage --coverageReporters json-summary text html lcov",
|
|
13
|
-
"test:
|
|
13
|
+
"test:unit": "cross-env DEBUG=ServerlessInsight jest --runInBand --detectOpenHandles --testPathPattern=unit",
|
|
14
|
+
"test:service": "cross-env DEBUG=ServerlessInsight TEST_TYPE=service jest --runInBand --detectOpenHandles --testPathPattern=service",
|
|
15
|
+
"test:ci": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" jest --runInBand --ci --coverage --coverageReporters json-summary text html lcov",
|
|
14
16
|
"build": "tsc --build",
|
|
15
17
|
"lint:fix": "eslint --fix ./",
|
|
16
18
|
"lint:check": "eslint ./",
|
|
@@ -35,6 +37,7 @@
|
|
|
35
37
|
"tencent-cloud-functions",
|
|
36
38
|
"alibaba-cloud-functions",
|
|
37
39
|
"huawei-cloud-functions",
|
|
40
|
+
"volcengine-cloud-functions",
|
|
38
41
|
"serverless-framework",
|
|
39
42
|
"serverless-management",
|
|
40
43
|
"serverless-automation",
|
|
@@ -46,6 +49,7 @@
|
|
|
46
49
|
"azure",
|
|
47
50
|
"huawei",
|
|
48
51
|
"google",
|
|
52
|
+
"volcengine",
|
|
49
53
|
"function"
|
|
50
54
|
],
|
|
51
55
|
"dependencies": {
|
|
@@ -61,6 +65,8 @@
|
|
|
61
65
|
"@alicloud/ram20150501": "^1.2.0",
|
|
62
66
|
"@alicloud/rds20140815": "^15.5.1",
|
|
63
67
|
"@alicloud/sls20201230": "^5.9.0",
|
|
68
|
+
"@volcengine/openapi": "^1.36.0",
|
|
69
|
+
"@volcengine/tos-sdk": "^2.7.0",
|
|
64
70
|
"ajv": "^8.18.0",
|
|
65
71
|
"ali-oss": "^6.23.0",
|
|
66
72
|
"commander": "^14.0.3",
|
|
@@ -41,6 +41,7 @@ const stateBackend_1 = require("../common/stateBackend");
|
|
|
41
41
|
const parser_1 = require("../parser");
|
|
42
42
|
const scfStack_1 = require("../stack/scfStack");
|
|
43
43
|
const aliyunStack_1 = require("../stack/aliyunStack");
|
|
44
|
+
const volcengineStack_1 = require("../stack/volcengineStack");
|
|
44
45
|
const lang_1 = require("../lang");
|
|
45
46
|
const askConfirmation = async () => {
|
|
46
47
|
if (!process.stdin.isTTY) {
|
|
@@ -82,6 +83,9 @@ const deploy = async (options) => {
|
|
|
82
83
|
else if (iac.provider.name === common_1.ProviderEnum.ALIYUN) {
|
|
83
84
|
planResult = await (0, aliyunStack_1.generateAliyunPlan)(iac, backend);
|
|
84
85
|
}
|
|
86
|
+
else if (iac.provider.name === common_1.ProviderEnum.VOLCENGINE) {
|
|
87
|
+
planResult = await (0, volcengineStack_1.generateVolcenginePlan)(iac, backend);
|
|
88
|
+
}
|
|
85
89
|
else {
|
|
86
90
|
throw new Error(lang_1.lang.__('PLAN_COMMAND_NOT_SUPPORTED'));
|
|
87
91
|
}
|
|
@@ -7,6 +7,7 @@ const parser_1 = require("../parser");
|
|
|
7
7
|
const lang_1 = require("../lang");
|
|
8
8
|
const scfStack_1 = require("../stack/scfStack");
|
|
9
9
|
const aliyunStack_1 = require("../stack/aliyunStack");
|
|
10
|
+
const volcengineStack_1 = require("../stack/volcengineStack");
|
|
10
11
|
const destroyStack = async (options) => {
|
|
11
12
|
const iacLocation = (0, common_1.getIacLocation)(options.location);
|
|
12
13
|
const rawIac = (0, parser_1.parseYaml)(iacLocation);
|
|
@@ -33,6 +34,9 @@ const destroyStack = async (options) => {
|
|
|
33
34
|
else if (iac.provider.name === common_1.ProviderEnum.ALIYUN) {
|
|
34
35
|
await (0, aliyunStack_1.destroyAliyunStack)(backend);
|
|
35
36
|
}
|
|
37
|
+
else if (iac.provider.name === common_1.ProviderEnum.VOLCENGINE) {
|
|
38
|
+
await (0, volcengineStack_1.destroyVolcengineStack)(backend);
|
|
39
|
+
}
|
|
36
40
|
else {
|
|
37
41
|
throw new Error(`Unsupported provider: ${iac.provider.name}`);
|
|
38
42
|
}
|
|
@@ -11,6 +11,18 @@ const getCredentials = (config, provider) => {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
switch (provider) {
|
|
14
|
+
case providerEnum_1.ProviderEnum.VOLCENGINE:
|
|
15
|
+
return {
|
|
16
|
+
accessKeyId: config?.accessKeyId ??
|
|
17
|
+
process.env.VOLCSTACK_ACCESS_KEY_ID ??
|
|
18
|
+
process.env.VOLCENGINE_ACCESS_KEY_ID,
|
|
19
|
+
accessKeySecret: config?.accessKeySecret ??
|
|
20
|
+
process.env.VOLCSTACK_SECRET_ACCESS_KEY ??
|
|
21
|
+
process.env.VOLCENGINE_ACCESS_KEY_SECRET,
|
|
22
|
+
securityToken: config?.securityToken ??
|
|
23
|
+
process.env.VOLCSTACK_SESSION_TOKEN ??
|
|
24
|
+
process.env.VOLCENGINE_SESSION_TOKEN,
|
|
25
|
+
};
|
|
14
26
|
case providerEnum_1.ProviderEnum.TENCENT:
|
|
15
27
|
return {
|
|
16
28
|
accessKeyId: config?.accessKeyId ?? process.env.TENCENTCLOUD_SECRET_ID,
|
|
@@ -144,14 +144,35 @@ const mapRuntime = (standardRuntime, provider) => {
|
|
|
144
144
|
return providerRuntime;
|
|
145
145
|
};
|
|
146
146
|
exports.mapRuntime = mapRuntime;
|
|
147
|
-
const
|
|
148
|
-
|
|
147
|
+
const VOLCENGINE_NATIVE_RUNTIMES = [
|
|
148
|
+
'nodejs/v20',
|
|
149
|
+
'nodejs/v18',
|
|
150
|
+
'nodejs/v16',
|
|
151
|
+
'nodejs/v14',
|
|
152
|
+
'python/v3.12',
|
|
153
|
+
'python/v3.11',
|
|
154
|
+
'python/v3.10',
|
|
155
|
+
'python/v3.9',
|
|
156
|
+
'golang/v1',
|
|
157
|
+
'java/v21',
|
|
158
|
+
'java/v17',
|
|
159
|
+
'java/v11',
|
|
160
|
+
'java/v8',
|
|
161
|
+
];
|
|
162
|
+
const isRuntimeSupported = (runtime, provider) => {
|
|
163
|
+
if (provider === providerEnum_1.ProviderEnum.VOLCENGINE) {
|
|
164
|
+
return VOLCENGINE_NATIVE_RUNTIMES.includes(runtime);
|
|
165
|
+
}
|
|
166
|
+
const mapping = runtimeMappings[runtime];
|
|
149
167
|
return !!mapping && !!mapping[provider];
|
|
150
168
|
};
|
|
151
169
|
exports.isRuntimeSupported = isRuntimeSupported;
|
|
152
170
|
const getSupportedRuntimes = (provider) => {
|
|
153
171
|
if (!provider) {
|
|
154
|
-
return Object.values(StandardRuntime);
|
|
172
|
+
return [...Object.values(StandardRuntime), ...VOLCENGINE_NATIVE_RUNTIMES];
|
|
173
|
+
}
|
|
174
|
+
if (provider === providerEnum_1.ProviderEnum.VOLCENGINE) {
|
|
175
|
+
return VOLCENGINE_NATIVE_RUNTIMES;
|
|
155
176
|
}
|
|
156
177
|
return Object.entries(runtimeMappings)
|
|
157
178
|
.filter(([, mapping]) => !!mapping[provider])
|