Skip to content

Commit

Permalink
feat: enable --stage option
Browse files Browse the repository at this point in the history
Signed-off-by: seven <[email protected]>
  • Loading branch information
Blankll committed Oct 22, 2024
1 parent 3e4ca95 commit 6974dd8
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 15 deletions.
37 changes: 32 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"chalk": "^5.3.0",
"commander": "^12.1.0",
"i18n": "^0.15.1",
"lodash": "^4.17.21",
"pino": "^9.4.0",
"pino-pretty": "^11.2.2",
"yaml": "^2.5.1"
Expand All @@ -67,6 +68,7 @@
"@types/i18n": "^0.13.12",
"@types/jest": "^29.5.13",
"@types/node": "^22.7.4",
"@types/lodash": "^4.17.12",
"@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0",
"eslint": "^8.57.1",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { constructActionContext, logger } from '../common';

export const deploy = async (
stackName: string,
options: { location: string; parameters: { [key: string]: string } },
options: { location: string; parameters: { [key: string]: string }; stage: string | undefined },
) => {
const context = constructActionContext({ ...options, stackName });
logger.info('Validating yaml...');
Expand Down
10 changes: 6 additions & 4 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,17 @@ program
.command('validate [stackName]')
.description('validate serverless Iac yaml')
.option('-f, --file <path>', 'specify the yaml file')
.action((stackName, options) => {
.option('-s, --stage <stage>', 'specify the stage')
.action((stackName, { file, stage }) => {
logger.debug('log command info');
validate(options.file);
validate(file, stage);
});

program
.command('deploy <stackName>')
.description('deploy serverless Iac yaml')
.option('-f, --file <path>', 'specify the yaml file')
.option('-s, --stage <stage>', 'specify the stage')
.option(
'-p, --parameter <key=value>',
'override parameters',
Expand All @@ -45,9 +47,9 @@ program
},
{},
)
.action(async (stackName, options) => {
.action(async (stackName, { file, parameter, stage }) => {
logger.debug('log command info');
await deploy(stackName, { location: options.file, parameters: options.parameter });
await deploy(stackName, { location: file, parameters: parameter, stage });
});

program.parse();
4 changes: 2 additions & 2 deletions src/commands/validate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { constructActionContext, logger } from '../common';
import { parseYaml } from '../stack';

export const validate = (location?: string) => {
const context = constructActionContext({ location });
export const validate = (location: string | undefined, stage: string | undefined) => {
const context = constructActionContext({ location, stage });
parseYaml(context.iacLocation);
logger.info('Yaml is valid! 🎉');
logger.debug('Yaml is valid! debug🎉');
Expand Down
2 changes: 1 addition & 1 deletion src/common/iacHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const replaceReference = <T>(value: T, stage: string): T => {
return ros.Fn.ref(matchVar[1]) as T;
}
if (matchMap?.length) {
return ros.Fn.findInMap('stages', '', matchMap[1]) as T;
return ros.Fn.findInMap('stages', stage, matchMap[1]) as T;
}

if (matchFn?.length) {
Expand Down
6 changes: 5 additions & 1 deletion tests/commands/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ describe('unit test for deploy command', () => {
it('should construct valid context and deploy the stack when deploy with valid iac', async () => {
const stackName = 'my-demo-stack';

await deploy(stackName, { location: 'tests/fixtures/serverless-insight.yml', parameters: {} });
await deploy(stackName, {
location: 'tests/fixtures/serverless-insight.yml',
parameters: {},
stage: undefined,
});

expect(mockedDeployStack).toHaveBeenCalledTimes(1);
expect(mockedDeployStack).toHaveBeenCalledWith(stackName, expect.any(Object), defaultContext);
Expand Down
76 changes: 76 additions & 0 deletions tests/fixtures/deployFixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,82 @@ export const oneFcRos = {
},
};

export const oneFcIacWithStage = {
service: 'my-demo-service',
version: '0.0.1',
provider: 'aliyun',
vars: {
region: 'cn-hangzhou',
account_id: 1234567890,
},
stages: {
default: {
node_env: 'default',
},
dev: {
region: '${vars.region}',
account_id: '${vars.account_id}',
node_env: 'develop',
},
},
functions: [
{
key: 'hello_fn',
name: 'hello_fn',
runtime: 'nodejs18',
handler: 'index.handler',
code: 'artifact.zip',
memory: 128,
timeout: 10,
environment: {
NODE_ENV: '${stages.node_env}',
},
},
],
tags: [
{
key: 'owner',
value: 'geek-fun',
},
],
} as ServerlessIac;

export const oneFcWithStageRos = {
Description: 'my-demo-service stack',
Mappings: {
stages: {
default: {
node_env: 'default',
},
dev: {
account_id: { Ref: 'account_id' },
region: { Ref: 'region' },
node_env: 'develop',
},
},
},
Metadata: { 'ALIYUN::ROS::Interface': { TemplateTags: ['Create by ROS CDK'] } },
Parameters: {
account_id: { Default: 1234567890, Type: 'String' },
region: { Default: 'cn-hangzhou', Type: 'String' },
},
ROSTemplateFormatVersion: '2015-09-01',
Resources: {
hello_fn: {
Properties: {
Code: { ZipFile: 'resolved-code' },
EnvironmentVariables: { NODE_ENV: { 'Fn::FindInMap': ['stages', 'default', 'node_env'] } },
FunctionName: 'hello_fn',
Handler: 'index.handler',
MemorySize: 128,
Runtime: 'nodejs18',
Timeout: 10,
},
Type: 'ALIYUN::FC3::Function',
},
},
};

export const defaultContext = {
accessKeyId: 'access key id',
accessKeySecret: 'access key secret',
Expand Down
6 changes: 5 additions & 1 deletion tests/fixtures/serverless-insight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ vars:
handler: index.handler

stages:
default:
region: ${vars.region}
node_env: default
dev:
region: ${vars.region}
node_env: development
prod:
region: cn-shanghai

Expand All @@ -26,7 +30,7 @@ functions:
memory: 512
timeout: 10
environment:
NODE_ENV: production
NODE_ENV: ${stages.node_env}
TEST_VAR: ${vars.testv}
TEST_VAR_EXTRA: abcds-${vars.testv}-andyou

Expand Down
35 changes: 35 additions & 0 deletions tests/stack/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { deployStack } from '../../src/stack';
import { ActionContext } from '../../src/types';
import {
oneFcIac,
oneFcIacWithStage,
oneFcOneGatewayIac,
oneFcOneGatewayRos,
oneFcRos,
oneFcWithStageRos,
} from '../fixtures/deployFixture';
import { cloneDeep, set } from 'lodash';

const mockedRosStackDeploy = jest.fn();
const mockedResolveCode = jest.fn();
Expand Down Expand Up @@ -40,4 +43,36 @@ describe('Unit tests for stack deployment', () => {
expect(mockedRosStackDeploy).toHaveBeenCalledTimes(1);
expect(mockedRosStackDeploy).toHaveBeenCalledWith(stackName, oneFcRos, { stackName });
});

it('should reference to default stage mappings when --stage not provided', async () => {
const options = { stackName: 'my-demo-stack-fc-with-stage-1', stage: 'default' };
mockedRosStackDeploy.mockResolvedValueOnce(options.stackName);

await deployStack(options.stackName, oneFcIacWithStage, options as ActionContext);

expect(mockedRosStackDeploy).toHaveBeenCalledTimes(1);
expect(mockedRosStackDeploy).toHaveBeenCalledWith(
options.stackName,
oneFcWithStageRos,
options,
);
});

it('should reference to specified stage mappings when --stage is provided', async () => {
const options = { stackName: 'my-demo-stack-fc-with-stage-1', stage: 'dev' };
mockedRosStackDeploy.mockResolvedValueOnce(options.stackName);

await deployStack(options.stackName, oneFcIacWithStage, options as ActionContext);

expect(mockedRosStackDeploy).toHaveBeenCalledTimes(1);
expect(mockedRosStackDeploy).toHaveBeenCalledWith(
options.stackName,
set(
cloneDeep(oneFcWithStageRos),
'Resources.hello_fn.Properties.EnvironmentVariables.NODE_ENV.Fn::FindInMap',
['stages', 'dev', 'node_env'],
),
options,
);
});
});

0 comments on commit 6974dd8

Please sign in to comment.