From 8fb6241244f6f7f1027d02274c2e707f0d79c100 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Mon, 20 Mar 2023 17:57:34 +0100 Subject: [PATCH 01/21] add new file for integration/deploy test, implement custom stacks for deployment params --- .github/workflows/tests-deploy.yml | 31 +++++++++++++ .github/workflows/tests-integration.yml | 62 +++++++++++++++++++++---- scripts/deploy-sar-app.yml | 4 ++ 3 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/tests-deploy.yml diff --git a/.github/workflows/tests-deploy.yml b/.github/workflows/tests-deploy.yml new file mode 100644 index 00000000..13702c50 --- /dev/null +++ b/.github/workflows/tests-deploy.yml @@ -0,0 +1,31 @@ +name: aws-lambda-power-tuning-deploy-test +run-name: ${{ github.actor }} is deploying the current branch +on: pull_request +jobs: + build: + permissions: + id-token: write + contents: read + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 16.x + uses: actions/setup-node@v3 + with: + node-version: 16.x + + - uses: aws-actions/configure-aws-credentials@v2 + with: + audience: sts.amazonaws.com + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ secrets.AWS_REGION }} + + - run: npm ci + - uses: aws-actions/setup-sam@v2 + with: + use-installer: true + + - run: sam build --use-container + + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --stack-name aws-lambda-power-tuning-gh-${GITHUB_REF_NAME/\//-} --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 6d72a2fd..0001245d 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -1,4 +1,4 @@ -name: aws-lambda-power-tuning-integration-tests +name: aws-lambda-power-tuning-integration-tests-pr run-name: ${{ github.actor }} is running integration tests on: push: @@ -11,17 +11,28 @@ jobs: id-token: write contents: read runs-on: ubuntu-latest - strategy: - matrix: - node-version: [16.x] + + env: + PowerValues: 512,1024,1536 # shorter list + VisualizationURL: https://my-custom-url.io/ + LambdaResource: 'arn:aws:lambda:eu-west-1:*:function:*' # specific region + TotalExecutionTimeout: '900' #max value + PermissionsBoundary: ARN + S3Bucket: lpt-payloads # existing bucket + S3Key: "payload.json" # only allow this object + LayerSdkName: custom-layer-name + LogGroupRetentionInDays: 7 + SecurityGroupIds: sg-06ad5b959d0ce9f57 # existing SG + SubnetIDs: subnet-0126a3daed78354c7,subnet-00e2995006f41811e # existing subnets + steps: - uses: actions/checkout@v3 - - name: Use Node.js ${{ matrix.node-version }} + - name: Use Node.js 16.x uses: actions/setup-node@v3 with: - node-version: ${{ matrix.node-version }} + node-version: 16.x - - uses: aws-actions/configure-aws-credentials@master + - uses: aws-actions/configure-aws-credentials@v2 with: audience: sts.amazonaws.com role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} @@ -33,4 +44,39 @@ jobs: use-installer: true - run: sam build --use-container - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --stack-name aws-lambda-power-tuning-gh-${GITHUB_REF_NAME/\//-} --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ No newline at end of file + + - run: sam validate + + # deploy with default params + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + --stack-name aws-lambda-power-tuning-gh-defaults + + # deploy with VPC params + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + --stack-name aws-lambda-power-tuning-gh-vpc\ + --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds + + # deploy with S3 payload params + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + --stack-name aws-lambda-power-tuning-gh-s3\ + --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key + + # deploy with regional limitation (via Lambda Resource) + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + --stack-name aws-lambda-power-tuning-gh-lambda-resource\ + --parameter-overrides lambdaResource=$LambdaResource + + + # deploy with a bunch of custom parameters + - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + --stack-name aws-lambda-power-tuning-gh-custom-params\ + --parameter-overrides \ + PowerValues=$PowerValues \ + visualizationURL=$VisualizationURL \ + totalExecutionTimeout=$TotalExecutionTimeout \ + layerSdkName=$LayerSdkName \ + logGroupRetentionInDays=$LogGroupRetentionInDays \ + permissionsBoundary=$PermissionsBoundary + + +# # # # \ No newline at end of file diff --git a/scripts/deploy-sar-app.yml b/scripts/deploy-sar-app.yml index 1ed55d60..928fc469 100644 --- a/scripts/deploy-sar-app.yml +++ b/scripts/deploy-sar-app.yml @@ -18,6 +18,10 @@ Resources: # permissionsBoundary: ARN # payloadS3Bucket: my-bucket # payloadS3Key: my-key.json + # layerSdkName: custom-layer-name + # logGroupRetentionInDays: 7 + # securityGroupIds: id1, id2 + # subnetIds: id1, id2 Outputs: PowerTuningStateMachine: From d88b2d6fdac432718ac221465911d5260891b304 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Mon, 20 Mar 2023 18:08:41 +0100 Subject: [PATCH 02/21] GHA - fix newlines --- .github/workflows/tests-integration.yml | 35 ++++++++++++++----------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 0001245d..01df66c3 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -48,34 +48,39 @@ jobs: - run: sam validate # deploy with default params - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ + - run: > + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} --stack-name aws-lambda-power-tuning-gh-defaults # deploy with VPC params - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ - --stack-name aws-lambda-power-tuning-gh-vpc\ + - run: > + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} + --stack-name aws-lambda-power-tuning-gh-vpc --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds # deploy with S3 payload params - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ - --stack-name aws-lambda-power-tuning-gh-s3\ + - run: > + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} + --stack-name aws-lambda-power-tuning-gh-s3 --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key # deploy with regional limitation (via Lambda Resource) - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ - --stack-name aws-lambda-power-tuning-gh-lambda-resource\ + - run: > + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} + --stack-name aws-lambda-power-tuning-gh-lambda-resource --parameter-overrides lambdaResource=$LambdaResource # deploy with a bunch of custom parameters - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }}\ - --stack-name aws-lambda-power-tuning-gh-custom-params\ - --parameter-overrides \ - PowerValues=$PowerValues \ - visualizationURL=$VisualizationURL \ - totalExecutionTimeout=$TotalExecutionTimeout \ - layerSdkName=$LayerSdkName \ - logGroupRetentionInDays=$LogGroupRetentionInDays \ + - run: > + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} + --stack-name aws-lambda-power-tuning-gh-custom-params + --parameter-overrides + PowerValues=$PowerValues + visualizationURL=$VisualizationURL + totalExecutionTimeout=$TotalExecutionTimeout + layerSdkName=$LayerSdkName + logGroupRetentionInDays=$LogGroupRetentionInDays permissionsBoundary=$PermissionsBoundary From 6bdfc2dc7608c477499915e406386a869ff7cfaf Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Mon, 20 Mar 2023 18:14:41 +0100 Subject: [PATCH 03/21] GHA - fix newlines (again) --- .github/workflows/tests-integration.yml | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 01df66c3..d34d66fe 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -48,39 +48,39 @@ jobs: - run: sam validate # deploy with default params - - run: > - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} + - run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name aws-lambda-power-tuning-gh-defaults # deploy with VPC params - - run: > - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} - --stack-name aws-lambda-power-tuning-gh-vpc + - run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name aws-lambda-power-tuning-gh-vpc \ --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds # deploy with S3 payload params - - run: > - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} - --stack-name aws-lambda-power-tuning-gh-s3 + - run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name aws-lambda-power-tuning-gh-s3 \ --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key # deploy with regional limitation (via Lambda Resource) - - run: > - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} - --stack-name aws-lambda-power-tuning-gh-lambda-resource + - run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name aws-lambda-power-tuning-gh-lambda-resource \ --parameter-overrides lambdaResource=$LambdaResource # deploy with a bunch of custom parameters - - run: > - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} - --stack-name aws-lambda-power-tuning-gh-custom-params - --parameter-overrides - PowerValues=$PowerValues - visualizationURL=$VisualizationURL - totalExecutionTimeout=$TotalExecutionTimeout - layerSdkName=$LayerSdkName - logGroupRetentionInDays=$LogGroupRetentionInDays + - run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name aws-lambda-power-tuning-gh-custom-params \ + --parameter-overrides \ + PowerValues=$PowerValues \ + visualizationURL=$VisualizationURL \ + totalExecutionTimeout=$TotalExecutionTimeout \ + layerSdkName=$LayerSdkName \ + logGroupRetentionInDays=$LogGroupRetentionInDays \ permissionsBoundary=$PermissionsBoundary From ed4de0e5e2ba87f926ad3d9b5158ddda27ce1f54 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Mon, 20 Mar 2023 18:31:16 +0100 Subject: [PATCH 04/21] GHA - add permission boundary ARN --- .github/workflows/tests-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index d34d66fe..114ca9c7 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -17,7 +17,7 @@ jobs: VisualizationURL: https://my-custom-url.io/ LambdaResource: 'arn:aws:lambda:eu-west-1:*:function:*' # specific region TotalExecutionTimeout: '900' #max value - PermissionsBoundary: ARN + PermissionsBoundary: arn:aws:iam::aws:policy/AdministratorAccess S3Bucket: lpt-payloads # existing bucket S3Key: "payload.json" # only allow this object LayerSdkName: custom-layer-name From 599b019ba65c353ce980ff7d1ca90bed079ac3fd Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 13:40:32 +0100 Subject: [PATCH 05/21] GHA - run deployments in parallel (matrix) --- .github/workflows/tests-deploy.yml | 31 ------- .github/workflows/tests-integration.yml | 112 +++++++++++++++--------- 2 files changed, 73 insertions(+), 70 deletions(-) delete mode 100644 .github/workflows/tests-deploy.yml diff --git a/.github/workflows/tests-deploy.yml b/.github/workflows/tests-deploy.yml deleted file mode 100644 index 13702c50..00000000 --- a/.github/workflows/tests-deploy.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: aws-lambda-power-tuning-deploy-test -run-name: ${{ github.actor }} is deploying the current branch -on: pull_request -jobs: - build: - permissions: - id-token: write - contents: read - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - name: Use Node.js 16.x - uses: actions/setup-node@v3 - with: - node-version: 16.x - - - uses: aws-actions/configure-aws-credentials@v2 - with: - audience: sts.amazonaws.com - role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} - aws-region: ${{ secrets.AWS_REGION }} - - - run: npm ci - - uses: aws-actions/setup-sam@v2 - with: - use-installer: true - - - run: sam build --use-container - - - run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --stack-name aws-lambda-power-tuning-gh-${GITHUB_REF_NAME/\//-} --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 114ca9c7..5aaad45c 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -1,80 +1,105 @@ -name: aws-lambda-power-tuning-integration-tests-pr +name: aws-lambda-power-tuning-integration-tests run-name: ${{ github.actor }} is running integration tests +permissions: + id-token: write + contents: read + on: push: branches: - 'master' pull_request: + +env: + # stack names are reused across jobs + STACK_NAME_DEFAULTS: aws-lpt-gh-defaults-${GITHUB_REF_NAME/\//-} + STACK_NAME_S3: aws-lpt-gh-s3-${GITHUB_REF_NAME/\//-} + STACK_NAME_VPC: aws-lpt-gh-vpc-${GITHUB_REF_NAME/\//-} + STACK_NAME_LAMBDA_RESOURCE: aws-lpt-gh-lambda-resource-${GITHUB_REF_NAME/\//-} + STACK_NAME_CUSTOM_PARAMS: aws-lpt-gh-custom-params-${GITHUB_REF_NAME/\//-} + + # deployment parameters are reused across jobs + PowerValues: 512,1024,1536 # shorter list + VisualizationURL: https://my-custom-url.io/ + LambdaResource: 'arn:aws:lambda:eu-west-1:*:function:*' # specific region + TotalExecutionTimeout: '900' #max value + PermissionsBoundary: arn:aws:iam::aws:policy/AdministratorAccess + S3Bucket: lpt-payloads # existing bucket + S3Key: "payload.json" # only allow this object + LayerSdkName: custom-layer-name + LogGroupRetentionInDays: 7 + SecurityGroupIds: sg-06ad5b959d0ce9f57 # existing SG + SubnetIDs: subnet-0126a3daed78354c7,subnet-00e2995006f41811e # existing subnets + jobs: build: - permissions: - id-token: write - contents: read runs-on: ubuntu-latest - - env: - PowerValues: 512,1024,1536 # shorter list - VisualizationURL: https://my-custom-url.io/ - LambdaResource: 'arn:aws:lambda:eu-west-1:*:function:*' # specific region - TotalExecutionTimeout: '900' #max value - PermissionsBoundary: arn:aws:iam::aws:policy/AdministratorAccess - S3Bucket: lpt-payloads # existing bucket - S3Key: "payload.json" # only allow this object - LayerSdkName: custom-layer-name - LogGroupRetentionInDays: 7 - SecurityGroupIds: sg-06ad5b959d0ce9f57 # existing SG - SubnetIDs: subnet-0126a3daed78354c7,subnet-00e2995006f41811e # existing subnets - steps: - uses: actions/checkout@v3 - - name: Use Node.js 16.x - uses: actions/setup-node@v3 + - uses: actions/setup-node@v3 with: node-version: 16.x + cache: 'npm' + - run: npm ci + - uses: aws-actions/setup-sam@v2 + with: + use-installer: true + - run: sam validate + - run: sam build --use-container + - uses: actions/upload-artifact@v2 + with: + name: sam-build-artifacts + path: ${{ github.workspace }}/.aws-sam + deploy: + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + # this will deploy the 5 stacks in parallel, + # without defining each job individually + # (see the conditional trick below) + stack: ['default', 'vpc', 's3', 'resource', 'custom'] + steps: - uses: aws-actions/configure-aws-credentials@v2 with: audience: sts.amazonaws.com role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} aws-region: ${{ secrets.AWS_REGION }} - - - run: npm ci - uses: aws-actions/setup-sam@v2 with: use-installer: true - - - run: sam build --use-container - - - run: sam validate - + - uses: actions/download-artifact@v2 + with: + name: sam-build-artifacts # deploy with default params - run: | - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name aws-lambda-power-tuning-gh-defaults + [[ "${{ matrix.stack }}" = "default" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_DEFAULTS # deploy with VPC params - run: | - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name aws-lambda-power-tuning-gh-vpc \ + [[ "${{ matrix.stack }}" = "vpc" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_VPC \ --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds # deploy with S3 payload params - run: | - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name aws-lambda-power-tuning-gh-s3 \ + [[ "${{ matrix.stack }}" = "s3" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_S3 \ --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key # deploy with regional limitation (via Lambda Resource) - run: | - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name aws-lambda-power-tuning-gh-lambda-resource \ + [[ "${{ matrix.stack }}" = "resource" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_LAMBDA_RESOURCE \ --parameter-overrides lambdaResource=$LambdaResource # deploy with a bunch of custom parameters - run: | - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name aws-lambda-power-tuning-gh-custom-params \ + [[ "${{ matrix.stack }}" = "custom" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_CUSTOM_PARAMS \ --parameter-overrides \ PowerValues=$PowerValues \ visualizationURL=$VisualizationURL \ @@ -83,5 +108,14 @@ jobs: logGroupRetentionInDays=$LogGroupRetentionInDays \ permissionsBoundary=$PermissionsBoundary - -# # # # \ No newline at end of file + test: + needs: deploy + runs-on: ubuntu-latest + strategy: + matrix: + # this will test the 5 stacks in parallel, + # without defining each job individually + # (see the conditional trick below) + stack: ['default', 'vpc', 's3', 'resource', 'custom'] + steps: + - run: echo "Running tests for stack ${{ matrix.stack }}" \ No newline at end of file From e41b0825a345f03766a144380baf43e49ee23fb8 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 13:43:44 +0100 Subject: [PATCH 06/21] GHA remove sam validate --- .github/workflows/tests-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 5aaad45c..acea60cc 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -44,7 +44,7 @@ jobs: - uses: aws-actions/setup-sam@v2 with: use-installer: true - - run: sam validate + #- run: sam validate - run: sam build --use-container - uses: actions/upload-artifact@v2 with: From ee76090827ccdc1b7ed2e24197bce9e372fe881d Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 13:57:09 +0100 Subject: [PATCH 07/21] GHA - fix string comparison, merge into one deploy job without artifacts --- .github/workflows/tests-integration.yml | 87 +++++++++++++------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index acea60cc..06a4c91c 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -32,27 +32,7 @@ env: SubnetIDs: subnet-0126a3daed78354c7,subnet-00e2995006f41811e # existing subnets jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 16.x - cache: 'npm' - - run: npm ci - - uses: aws-actions/setup-sam@v2 - with: - use-installer: true - #- run: sam validate - - run: sam build --use-container - - uses: actions/upload-artifact@v2 - with: - name: sam-build-artifacts - path: ${{ github.workspace }}/.aws-sam - deploy: - needs: build runs-on: ubuntu-latest strategy: matrix: @@ -61,6 +41,12 @@ jobs: # (see the conditional trick below) stack: ['default', 'vpc', 's3', 'resource', 'custom'] steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16.x + cache: 'npm' + - run: npm ci - uses: aws-actions/configure-aws-credentials@v2 with: audience: sts.amazonaws.com @@ -69,44 +55,59 @@ jobs: - uses: aws-actions/setup-sam@v2 with: use-installer: true - - uses: actions/download-artifact@v2 - with: - name: sam-build-artifacts + - run: sam validate + - run: sam build --use-container + # deploy with default params - run: | - [[ "${{ matrix.stack }}" = "default" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_DEFAULTS + if [[ "${{ matrix.stack }}" == "default" ]] + then + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_DEFAULTS + fi # deploy with VPC params - run: | - [[ "${{ matrix.stack }}" = "vpc" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_VPC \ - --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds + if [[ "${{ matrix.stack }}" == "vpc" ]] + then + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_VPC \ + --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds + fi # deploy with S3 payload params - run: | - [[ "${{ matrix.stack }}" = "s3" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_S3 \ - --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key + if [[ "${{ matrix.stack }}" == "s3" ]] + then + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_S3 \ + --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key + fi # deploy with regional limitation (via Lambda Resource) - run: | - [[ "${{ matrix.stack }}" = "resource" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_LAMBDA_RESOURCE \ - --parameter-overrides lambdaResource=$LambdaResource + if [[ "${{ matrix.stack }}" == "resource" ]] + then + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_LAMBDA_RESOURCE \ + --parameter-overrides lambdaResource=$LambdaResource + fi # deploy with a bunch of custom parameters - run: | - [[ "${{ matrix.stack }}" = "custom" ]] && sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_CUSTOM_PARAMS \ - --parameter-overrides \ - PowerValues=$PowerValues \ - visualizationURL=$VisualizationURL \ - totalExecutionTimeout=$TotalExecutionTimeout \ - layerSdkName=$LayerSdkName \ - logGroupRetentionInDays=$LogGroupRetentionInDays \ - permissionsBoundary=$PermissionsBoundary + if [[ "${{ matrix.stack }}" == "custom" ]] + then + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_CUSTOM_PARAMS \ + --parameter-overrides \ + PowerValues=$PowerValues \ + visualizationURL=$VisualizationURL \ + totalExecutionTimeout=$TotalExecutionTimeout \ + layerSdkName=$LayerSdkName \ + logGroupRetentionInDays=$LogGroupRetentionInDays \ + permissionsBoundary=$PermissionsBoundary + fi test: needs: deploy From d73e68bcfb86efef7309d5c0a1b6d07cdd006629 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 14:02:51 +0100 Subject: [PATCH 08/21] GHA - fix stack name with current branch --- .github/workflows/tests-integration.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 06a4c91c..3d8fe259 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -12,11 +12,11 @@ on: env: # stack names are reused across jobs - STACK_NAME_DEFAULTS: aws-lpt-gh-defaults-${GITHUB_REF_NAME/\//-} - STACK_NAME_S3: aws-lpt-gh-s3-${GITHUB_REF_NAME/\//-} - STACK_NAME_VPC: aws-lpt-gh-vpc-${GITHUB_REF_NAME/\//-} - STACK_NAME_LAMBDA_RESOURCE: aws-lpt-gh-lambda-resource-${GITHUB_REF_NAME/\//-} - STACK_NAME_CUSTOM_PARAMS: aws-lpt-gh-custom-params-${GITHUB_REF_NAME/\//-} + STACK_NAME_DEFAULTS: aws-lpt-gh-defaults + STACK_NAME_S3: aws-lpt-gh-s3 + STACK_NAME_VPC: aws-lpt-gh-vpc + STACK_NAME_LAMBDA_RESOURCE: aws-lpt-gh-lambda-resource + STACK_NAME_CUSTOM_PARAMS: aws-lpt-gh-custom-params # deployment parameters are reused across jobs PowerValues: 512,1024,1536 # shorter list @@ -63,7 +63,7 @@ jobs: if [[ "${{ matrix.stack }}" == "default" ]] then sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_DEFAULTS + --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} fi # deploy with VPC params @@ -71,7 +71,7 @@ jobs: if [[ "${{ matrix.stack }}" == "vpc" ]] then sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_VPC \ + --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} \ --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds fi @@ -80,7 +80,7 @@ jobs: if [[ "${{ matrix.stack }}" == "s3" ]] then sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_S3 \ + --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} \ --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key fi @@ -89,7 +89,7 @@ jobs: if [[ "${{ matrix.stack }}" == "resource" ]] then sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_LAMBDA_RESOURCE \ + --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} \ --parameter-overrides lambdaResource=$LambdaResource fi @@ -99,7 +99,7 @@ jobs: if [[ "${{ matrix.stack }}" == "custom" ]] then sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_CUSTOM_PARAMS \ + --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} \ --parameter-overrides \ PowerValues=$PowerValues \ visualizationURL=$VisualizationURL \ From ac5aefa62629c275494a3bfe4c4f7ba0e1e8091b Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 15:35:31 +0100 Subject: [PATCH 09/21] GHA - add SAM build cache, simplify if conditions, add stack deletion --- .github/workflows/tests-integration.yml | 154 +++++++++++++++++------- 1 file changed, 110 insertions(+), 44 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 3d8fe259..576343bd 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -34,11 +34,11 @@ env: jobs: deploy: runs-on: ubuntu-latest + if: always() # run all stacks even if one fails strategy: matrix: # this will deploy the 5 stacks in parallel, # without defining each job individually - # (see the conditional trick below) stack: ['default', 'vpc', 's3', 'resource', 'custom'] steps: - uses: actions/checkout@v3 @@ -46,77 +46,143 @@ jobs: with: node-version: 16.x cache: 'npm' + + # install dependencies - run: npm ci + + # configure AWS CLI and SAM CLI credentials - uses: aws-actions/configure-aws-credentials@v2 with: audience: sts.amazonaws.com role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} aws-region: ${{ secrets.AWS_REGION }} + + # install SAM CLI - uses: aws-actions/setup-sam@v2 with: use-installer: true + + # validate SAM template (nice to have) - run: sam validate - - run: sam build --use-container + + # sam build takes about 40 seconds, if not cached + - name: Cache SAM Build + id: cache-sam-build + uses: actions/cache@v3 + with: + path: .aws-sam/** + key: aws-sam-build + + # build app and layer, if cache miss + - name: SAM Build + if: steps.cache-sam-build.outputs.cache-hit != 'true' + run: sam build --use-container # deploy with default params - - run: | - if [[ "${{ matrix.stack }}" == "default" ]] - then - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} - fi + - if: matrix.stack == "default" + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} # deploy with VPC params - - run: | - if [[ "${{ matrix.stack }}" == "vpc" ]] - then - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} \ - --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds - fi + - if: matrix.stack == "vpc" + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} \ + --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds # deploy with S3 payload params - - run: | - if [[ "${{ matrix.stack }}" == "s3" ]] - then - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} \ - --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key - fi + - if: matrix.stack == "s3" + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} \ + --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key # deploy with regional limitation (via Lambda Resource) - - run: | - if [[ "${{ matrix.stack }}" == "resource" ]] - then - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} \ - --parameter-overrides lambdaResource=$LambdaResource - fi + - if: matrix.stack == "resource" + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} \ + --parameter-overrides lambdaResource=$LambdaResource # deploy with a bunch of custom parameters - - run: | - if [[ "${{ matrix.stack }}" == "custom" ]] - then - sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ - --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} \ - --parameter-overrides \ - PowerValues=$PowerValues \ - visualizationURL=$VisualizationURL \ - totalExecutionTimeout=$TotalExecutionTimeout \ - layerSdkName=$LayerSdkName \ - logGroupRetentionInDays=$LogGroupRetentionInDays \ - permissionsBoundary=$PermissionsBoundary - fi + - if: matrix.stack == "custom" + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} \ + --parameter-overrides \ + PowerValues=$PowerValues \ + visualizationURL=$VisualizationURL \ + totalExecutionTimeout=$TotalExecutionTimeout \ + layerSdkName=$LayerSdkName \ + logGroupRetentionInDays=$LogGroupRetentionInDays \ + permissionsBoundary=$PermissionsBoundary test: needs: deploy + if: always() # run even if something failed (100% sure?) runs-on: ubuntu-latest strategy: matrix: # this will test the 5 stacks in parallel, # without defining each job individually - # (see the conditional trick below) stack: ['default', 'vpc', 's3', 'resource', 'custom'] steps: - - run: echo "Running tests for stack ${{ matrix.stack }}" \ No newline at end of file + - run: echo "Running tests for stack matrix.stack" + + + # delete all Cfn stacks created above + # (whether tests have succedeed or not) + # note: sam delete doesn't fail if the stack doesn't exist + cleanup: + needs: test + if: always() # run even if something failed + runs-on: ubuntu-latest + strategy: + matrix: + # this will delete the 5 stacks in parallel, + # without defining each job individually + stack: ['default', 'vpc', 's3', 'resource', 'custom'] + steps: + # configure AWS CLI and SAM CLI credentials + - uses: aws-actions/configure-aws-credentials@v2 + with: + audience: sts.amazonaws.com + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ secrets.AWS_REGION }} + + # install SAM CLI + - uses: aws-actions/setup-sam@v2 + with: + use-installer: true + + # delete stack with default params + - if: matrix.stack == "default" + run: | + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} + + # delete stack with VPC params + - if: matrix.stack == "vpc" + run: | + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} + + # delete stack with S3 payload params + - if: matrix.stack == "s3" + run: | + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} + --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} + + # delete stack with regional limitation (via Lambda Resource) + - if: matrix.stack == "resource" + run: | + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} + + # delete stack with a bunch of custom parameters + - if: matrix.stack == "custom" + run: | + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ + --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} From b8736058c31388c54e543ccf4921faafd10b93d7 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 15:48:41 +0100 Subject: [PATCH 10/21] GHA - syntax fix --- .github/workflows/tests-integration.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 576343bd..5e2f25c4 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -69,9 +69,9 @@ jobs: - name: Cache SAM Build id: cache-sam-build uses: actions/cache@v3 - with: - path: .aws-sam/** - key: aws-sam-build + with: + path: .aws-sam/** + key: aws-sam-build # build app and layer, if cache miss - name: SAM Build @@ -129,7 +129,7 @@ jobs: # without defining each job individually stack: ['default', 'vpc', 's3', 'resource', 'custom'] steps: - - run: echo "Running tests for stack matrix.stack" + - run: echo "Running tests for stack ${{ matrix.stack }}" # delete all Cfn stacks created above From 2a477d36095470696f3af0a8cd9c5b1dec00a071 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Tue, 21 Mar 2023 15:53:26 +0100 Subject: [PATCH 11/21] GHA - another syntax fix --- .github/workflows/tests-integration.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 5e2f25c4..2bb34f69 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -79,27 +79,27 @@ jobs: run: sam build --use-container # deploy with default params - - if: matrix.stack == "default" + - if: matrix.stack == 'default' run: | sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} # deploy with VPC params - - if: matrix.stack == "vpc" + - if: matrix.stack == 'vpc' run: | sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} \ --parameter-overrides subnetIds=$SubnetIDs securityGroupIds=$SecurityGroupIds # deploy with S3 payload params - - if: matrix.stack == "s3" + - if: matrix.stack == 's3' run: | sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} \ --parameter-overrides payloadS3Bucket=$S3Bucket payloadS3Key=$S3Key # deploy with regional limitation (via Lambda Resource) - - if: matrix.stack == "resource" + - if: matrix.stack == 'resource' run: | sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} \ @@ -107,7 +107,7 @@ jobs: # deploy with a bunch of custom parameters - - if: matrix.stack == "custom" + - if: matrix.stack == 'custom' run: | sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} \ @@ -158,31 +158,31 @@ jobs: use-installer: true # delete stack with default params - - if: matrix.stack == "default" + - if: matrix.stack == 'default' run: | sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_DEFAULTS-${GITHUB_REF_NAME/\//-} # delete stack with VPC params - - if: matrix.stack == "vpc" + - if: matrix.stack == 'vpc' run: | sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_VPC-${GITHUB_REF_NAME/\//-} # delete stack with S3 payload params - - if: matrix.stack == "s3" + - if: matrix.stack == 's3' run: | sam delete --no-prompts --region ${{ secrets.AWS_REGION }} --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} # delete stack with regional limitation (via Lambda Resource) - - if: matrix.stack == "resource" + - if: matrix.stack == 'resource' run: | sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_LAMBDA_RESOURCE-${GITHUB_REF_NAME/\//-} # delete stack with a bunch of custom parameters - - if: matrix.stack == "custom" + - if: matrix.stack == 'custom' run: | sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_CUSTOM_PARAMS-${GITHUB_REF_NAME/\//-} From 0a2f935744b78f8dbf00a42d5d5b12c0cf0b3ce5 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:21:04 +0100 Subject: [PATCH 12/21] GHA - add sample payloads --- test/integration/payloads/index.js | 22 +++++++++++++++++++ test/integration/payloads/sample-2.json | 7 ++++++ test/integration/payloads/sample-invalid.json | 6 +++++ test/integration/payloads/sample.json | 7 ++++++ 4 files changed, 42 insertions(+) create mode 100644 test/integration/payloads/index.js create mode 100644 test/integration/payloads/sample-2.json create mode 100644 test/integration/payloads/sample-invalid.json create mode 100644 test/integration/payloads/sample.json diff --git a/test/integration/payloads/index.js b/test/integration/payloads/index.js new file mode 100644 index 00000000..bee0e08b --- /dev/null +++ b/test/integration/payloads/index.js @@ -0,0 +1,22 @@ + +const FUNCTION_ARN = process.env.FUNCTION_ARN; + +const payloads = { + sample: require('./sample.json'), + sample2: require('./sample-2.json'), + invalid: require('./sample-invalid.json'), +}; + +module.exports.get = (name, functionName) => { + const p = payloads[name]; + if (!p) { + throw new Error("Invalid payload name", name); + } + if (functionName === undefined && FUNCTION_ARN) { + functionName = FUNCTION_ARN; + } + if (functionName) { + p.lambdaARN = functionName; + } + return p; +}; \ No newline at end of file diff --git a/test/integration/payloads/sample-2.json b/test/integration/payloads/sample-2.json new file mode 100644 index 00000000..dd95414b --- /dev/null +++ b/test/integration/payloads/sample-2.json @@ -0,0 +1,7 @@ +{ + "lambdaARN": "PLACEHOLDER", + "powerValues": [512, 1024, 3008], + "num": 5, + "payload": {}, + "parallelInvocation": true +} diff --git a/test/integration/payloads/sample-invalid.json b/test/integration/payloads/sample-invalid.json new file mode 100644 index 00000000..44da3bdd --- /dev/null +++ b/test/integration/payloads/sample-invalid.json @@ -0,0 +1,6 @@ +{ + "lambdaARN": "PLACEHOLDER", + "powerValues": [512, 1024], + "num": 3, + "payload": "{}" +} diff --git a/test/integration/payloads/sample.json b/test/integration/payloads/sample.json new file mode 100644 index 00000000..693a43dd --- /dev/null +++ b/test/integration/payloads/sample.json @@ -0,0 +1,7 @@ +{ + "lambdaARN": "PLACEHOLDER", + "powerValues": [256, 512, 1024], + "num": 10, + "payload": "{}", + "parallelInvocation": true +} From 57d0792d93f8ee352ae1beafbb7c7c140dc946be Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:23:23 +0100 Subject: [PATCH 13/21] GHA - update dependencies --- package-lock.json | 1207 +-------------------------------------------- package.json | 3 +- 2 files changed, 9 insertions(+), 1201 deletions(-) diff --git a/package-lock.json b/package-lock.json index c1bae6b9..39b4da4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,314 +17,10 @@ "expect.js": "^0.3.1", "json-schema": ">=0.4.0", "mocha": "^9.2.2", - "nyc": "^15.1.0", "path-parse": ">=1.0.7", "sinon": "^9.0.2" } }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.16.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", - "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.7.tgz", - "integrity": "sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.7", - "@babel/helper-compilation-targets": "^7.16.7", - "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.7.tgz", - "integrity": "sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", - "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.16.4", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", - "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", - "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz", - "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.7.tgz", - "integrity": "sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.7.tgz", - "integrity": "sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.7.tgz", - "integrity": "sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.16.7", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.7.tgz", - "integrity": "sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -414,31 +110,6 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -586,19 +257,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -636,18 +294,6 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -661,33 +307,6 @@ "node": ">= 8" } }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -894,29 +513,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/browserslist": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", - "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001286", - "electron-to-chromium": "^1.4.17", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, "node_modules/buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", @@ -1112,21 +708,6 @@ "node": ">=10" } }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -1149,39 +730,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001295", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001295.tgz", - "integrity": "sha512-lSP16vcyC0FEy0R4ECc9duSPoKoZy+YkpGkue9G4D81OfPnliopaZrU10+qtPdT8PbGXad/PNx43TIQrOmJZSQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1221,47 +769,6 @@ "node": ">= 6" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1329,33 +836,12 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", - "dev": true, - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -1377,24 +863,12 @@ "node": ">=6.0.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.31", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.31.tgz", - "integrity": "sha512-t3XVQtk+Frkv6aTD4RRk0OqosU+VLe1dQFW83MDer78ZD6a52frgXuYOIsLYTQiH2Lm+JB2OKYcn7zrX+YGAiQ==", - "dev": true - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1404,15 +878,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/eslint": { "version": "8.35.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", @@ -1709,19 +1174,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -1830,36 +1282,6 @@ "node": ">=8" } }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -1925,26 +1347,6 @@ "node": ">=8.0.0" } }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1971,15 +1373,6 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -2003,15 +1396,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -2071,12 +1455,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, "node_modules/grapheme-splitter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", @@ -2104,15 +1482,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -2140,31 +1509,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2220,15 +1564,6 @@ "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2357,18 +1692,6 @@ "node": ">=8" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-typed-array": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", @@ -2388,12 +1711,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -2406,15 +1723,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -2436,61 +1744,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", @@ -2515,38 +1768,15 @@ } }, "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/istanbul-reports": { @@ -2581,37 +1811,6 @@ "url": "https://opencollective.com/js-sdsl" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -2630,18 +1829,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/just-extend": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", @@ -2661,24 +1848,6 @@ "node": ">= 0.8.0" } }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -3169,24 +2338,6 @@ "path-to-regexp": "^1.7.0" } }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "dev": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3196,56 +2347,6 @@ "node": ">=0.10.0" } }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3272,69 +2373,6 @@ "node": ">= 0.8.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3395,12 +2433,6 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -3413,18 +2445,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3434,18 +2454,6 @@ "node": ">= 0.8.0" } }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", @@ -3515,18 +2523,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3536,12 +2532,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3629,12 +2619,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3711,38 +2695,6 @@ "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3799,15 +2751,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3820,18 +2763,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -3852,15 +2783,6 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3912,15 +2834,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -4000,12 +2913,6 @@ "node": ">= 8" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "node_modules/which-typed-array": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", @@ -4041,71 +2948,12 @@ "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, "node_modules/xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", @@ -4125,47 +2973,6 @@ "node": ">=4.0" } }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", diff --git a/package.json b/package.json index 4aae4d4f..09f8fad6 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "deploy": "bash deploy.sh", "execute": "bash execute.sh", "lint": "eslint --ignore-path .gitignore .", - "test": "mocha", + "test": "mocha test/unit/*.js", + "test-integration": "mocha -p -j 5 test/integration/*.js", "coverage": "c8 --reporter=lcov --reporter=cobertura --reporter=text-summary mocha" }, "devDependencies": { From ec9f5ccf48af7f0bcd7b82d8749142cfd2e00004 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:23:47 +0100 Subject: [PATCH 14/21] GHA - update cleaner code to re-raise errors and make the execution fail --- lambda/cleaner.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lambda/cleaner.js b/lambda/cleaner.js index 4c1d3c35..42e38f79 100644 --- a/lambda/cleaner.js +++ b/lambda/cleaner.js @@ -19,6 +19,11 @@ module.exports.handler = async(event, context) => { // run everything in parallel and wait until completed await Promise.all(ops); + if (event.error) { + // re-raise so that the state machine execution fails (correctly) + throw new Error(event.error.Cause); + } + return 'OK'; }; From ad0d8ef782530899cf0695e2818a486c41544fa4 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:24:36 +0100 Subject: [PATCH 15/21] GHA - implement integration test logic with mocha, fix action structure --- .github/workflows/tests-integration.yml | 45 ++++++++++++------- .mocharc.js | 3 +- test/integration/default.js | 59 +++++++++++++++++++++++++ test/integration/utils.js | 56 +++++++++++++++++++++++ test/integration/vpc.js | 55 +++++++++++++++++++++++ 5 files changed, 202 insertions(+), 16 deletions(-) create mode 100644 test/integration/default.js create mode 100644 test/integration/utils.js create mode 100644 test/integration/vpc.js diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 2bb34f69..9dc55ef6 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -3,13 +3,11 @@ run-name: ${{ github.actor }} is running integration tests permissions: id-token: write contents: read - -on: - push: - branches: - - 'master' - pull_request: - +on: pull_request_target +# make sure only one concurrent run per workflow/branch +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: # stack names are reused across jobs STACK_NAME_DEFAULTS: aws-lpt-gh-defaults @@ -36,6 +34,7 @@ jobs: runs-on: ubuntu-latest if: always() # run all stacks even if one fails strategy: + fail-fast: false matrix: # this will deploy the 5 stacks in parallel, # without defining each job individually @@ -70,7 +69,7 @@ jobs: id: cache-sam-build uses: actions/cache@v3 with: - path: .aws-sam/** + path: .aws-sam/ key: aws-sam-build # build app and layer, if cache miss @@ -123,13 +122,28 @@ jobs: needs: deploy if: always() # run even if something failed (100% sure?) runs-on: ubuntu-latest - strategy: - matrix: - # this will test the 5 stacks in parallel, - # without defining each job individually - stack: ['default', 'vpc', 's3', 'resource', 'custom'] + env: + # sample function for testing (more will come) + FUNCTION_ARN: ${{ secrets.FUNCTION_ARN }} + BRANCH_NAME: ${{ github.ref_name }} steps: - - run: echo "Running tests for stack ${{ matrix.stack }}" + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16.x + cache: 'npm' + # install dependencies (needed for AWS CLI and a few more utils) + - run: npm ci + + # configure AWS CLI credentials + - uses: aws-actions/configure-aws-credentials@v2 + with: + audience: sts.amazonaws.com + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ secrets.AWS_REGION }} + + # run integrations tests (all in parallel) + - run: npm run test-integration # delete all Cfn stacks created above @@ -140,6 +154,7 @@ jobs: if: always() # run even if something failed runs-on: ubuntu-latest strategy: + fail-fast: false matrix: # this will delete the 5 stacks in parallel, # without defining each job individually @@ -172,7 +187,7 @@ jobs: # delete stack with S3 payload params - if: matrix.stack == 's3' run: | - sam delete --no-prompts --region ${{ secrets.AWS_REGION }} + sam delete --no-prompts --region ${{ secrets.AWS_REGION }} \ --stack-name $STACK_NAME_S3-${GITHUB_REF_NAME/\//-} # delete stack with regional limitation (via Lambda Resource) diff --git a/.mocharc.js b/.mocharc.js index 4c260141..8336ec4b 100644 --- a/.mocharc.js +++ b/.mocharc.js @@ -2,5 +2,6 @@ module.exports = { require: [ './test/setup.spec.js', ], - spec: './test/unit/**/*.js' + //spec: './test/**/*.js', + timeout: 60 * 1000 // 1 minute per test }; diff --git a/test/integration/default.js b/test/integration/default.js new file mode 100644 index 00000000..5bfd01ac --- /dev/null +++ b/test/integration/default.js @@ -0,0 +1,59 @@ +'use strict'; + + +const expect = require('expect.js'), + utils = require('./utils'), + payloads = require('./payloads'); + + +//also required: process.env.AWS_REGION; +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS, process.env.BRANCH_NAME), + payloadSample = payloads.get('sample'), + payloadSample2 = payloads.get('sample2'), + payloadInvalid = payloads.get('invalid'); + +var stateMachineArn, cfnStack; + +const asyncTestsSetup = [ + {payload: payloadSample, name: 'sample', status: 'SUCCEEDED'}, + {payload: payloadSample2, name: 'sample2', status: 'SUCCEEDED'}, + {payload: payloadInvalid, name: 'invalid', status: 'FAILED'}, +]; + +// this will start all the executions in parallel +// mocha doesn't allow this for tests in the same file +const fetchStackPromise = utils.fetchStackDetails(STACK_NAME); +fetchStackPromise.then((resp)=>{ + cfnStack = resp.stack; + stateMachineArn = resp.stateMachine; + asyncTestsSetup.forEach((test) => { + test.promise = utils.startExecution(stateMachineArn, test.payload, test.name); + }); +}) + + +describe('Default Stack', () => { + + // make sure stack details are fetched only once + // (while state machine executions have already started) + beforeEach('fetch stack details', async() => { + if (stateMachineArn) return; + await fetchStackPromise; + }); + + it('should exist and be ready to use', async() => { + expect(cfnStack).to.not.be(null); + expect(cfnStack.StackStatus).to.be('CREATE_COMPLETE'); + }); + + describe('State Machine', async() => { + + it('should have a valid ARN', async() => { + expect(stateMachineArn.length).to.be.greaterThan(0); + }); + + // generate dynamically + utils.generateTests(asyncTestsSetup) + }); + +}); diff --git a/test/integration/utils.js b/test/integration/utils.js new file mode 100644 index 00000000..23c55c62 --- /dev/null +++ b/test/integration/utils.js @@ -0,0 +1,56 @@ +'use strict'; + +const AWS = require('aws-sdk'), + expect = require('expect.js'), + crypto = require("crypto"), + utils = module.exports, + cfn = new AWS.CloudFormation(), + stepFunctions = new AWS.StepFunctions(); + + +module.exports.buildStackName = (prefix, branchRef) => { + return `${prefix}-${branchRef.replace('/', '-')}`; +}; + +module.exports.generateTests = (tests) => { + tests.forEach((test) => { + it(`should run payload ${test.name} with status ${test.status}`, async() => { + const resp = await test.promise; + expect(resp.executionArn.length).to.be.greaterThan(0); + const status = await utils.waitForCompletedExecution(resp.executionArn); + expect(status).to.be(test.status); + }); + }); +}; + + +module.exports.fetchStackDetails = async(stackName) => { + console.log('fetching stack details'); + const resp = await cfn.describeStacks({StackName: stackName}).promise(); + const stack = resp.Stacks[0]; + const stateMachine = stack.Outputs[0].OutputValue + return {stack, stateMachine}; +}; + +module.exports.startExecution = async(stateMachineArn, input, namePrefix) => { + input = JSON.stringify(input); + const name = namePrefix + `-` + crypto.randomBytes(10).toString('hex'); + return await stepFunctions.startExecution({ + stateMachineArn, + input, + name, + }).promise(); +}; + +module.exports.waitForCompletedExecution = async(executionArn) => { + var exec; + do { + console.log('waiting 1s'); + await new Promise((resolve) => setTimeout(resolve, 1000)); + console.log('fetching execution status'); + exec = await stepFunctions.describeExecution({ executionArn }).promise(); + } while (exec.status === 'RUNNING') + console.log('completed with status', exec.status); + // return final status + return exec.status; +}; diff --git a/test/integration/vpc.js b/test/integration/vpc.js new file mode 100644 index 00000000..1471d6ea --- /dev/null +++ b/test/integration/vpc.js @@ -0,0 +1,55 @@ +'use strict'; + +const expect = require('expect.js'), + utils = require('./utils'), + payloads = require('./payloads'); + + +//also required: process.env.AWS_REGION; +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS, process.env.BRANCH_NAME), + payloadSample2 = payloads.get('sample2'), + payloadInvalid = payloads.get('invalid'); + +var stateMachineArn, cfnStack; + +const asyncTestsSetup = [ + {payload: payloadSample2, name: 'sample2', status: 'SUCCEEDED'}, + {payload: payloadInvalid, name: 'invalid', status: 'FAILED'}, +]; + +// this will start all the executions in parallel +// mocha doesn't allow this for tests in the same file +const fetchStackPromise = utils.fetchStackDetails(STACK_NAME); +fetchStackPromise.then((resp)=>{ + cfnStack = resp.stack; + stateMachineArn = resp.stateMachine; + asyncTestsSetup.forEach((test) => { + test.promise = utils.startExecution(stateMachineArn, test.payload, test.name); + }); +}) + + +describe('VPC Stack', () => { + + // make sure stack details are loaded + // (while state machine executions have already started in parallel) + beforeEach('fetch stack details', async() => { + if (stateMachineArn) return; + await fetchStackPromise; + }); + + it('should exist and be ready to use', async() => { + expect(cfnStack).to.not.be(null); + expect(cfnStack.StackStatus).to.be('CREATE_COMPLETE'); + }); + + describe('State Machine', async() => { + + it('should have a valid ARN', async() => { + expect(stateMachineArn.length).to.be.greaterThan(0); + }); + + utils.generateTests(asyncTestsSetup) + }); + +}); From 1d0a898fb661a7774f4295664a6ed89a4bde337e Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:31:51 +0100 Subject: [PATCH 16/21] GHA - fix coverage cmd --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 09f8fad6..c155b9c9 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "lint": "eslint --ignore-path .gitignore .", "test": "mocha test/unit/*.js", "test-integration": "mocha -p -j 5 test/integration/*.js", - "coverage": "c8 --reporter=lcov --reporter=cobertura --reporter=text-summary mocha" + "coverage": "c8 --reporter=lcov --reporter=cobertura --reporter=text-summary npm test" }, "devDependencies": { "ansi-regex": ">=5.0.1", From 4eaa947fe1e72202046e22fe7c865c0821ac45f3 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:32:09 +0100 Subject: [PATCH 17/21] GHA - update cleaner unit tests for re-throw --- test/unit/test-lambda.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/test/unit/test-lambda.js b/test/unit/test-lambda.js index 2b1dfeca..91df2ccd 100644 --- a/test/unit/test-lambda.js +++ b/test/unit/test-lambda.js @@ -336,7 +336,7 @@ describe('Lambda Functions', async() => { await invokeForSuccess(handler, eventOK); }); - it('should fail is something goes wrong with the cleaup API calls', async() => { + it('should fail if something goes wrong with the cleaup API calls', async() => { deleteLambdaVersionStub && deleteLambdaVersionStub.restore(); deleteLambdaVersionStub = sandBox.stub(utils, 'deleteLambdaVersion') .callsFake(async() => { @@ -347,6 +347,18 @@ describe('Lambda Functions', async() => { await invokeForFailure(handler, eventOK); }); + it('should re-throw errors if cleaning-up-on-error', async() => { + const eventError = { + lambdaARN: 'arnOK', + powerValues: ['128', '256', '512'], + error: { + "Error": "Error", + "Cause": "{\"errorType\":\"Error\",\"errorMessage\":\"Whatever\",\"trace\":[...]}", + }, + }; + await invokeForFailure(handler, eventError); + }); + }); describe('executor', () => { From 5b78f9a9ecc3c0918dd59d260d83f6d5ac94bc86 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 15:35:13 +0100 Subject: [PATCH 18/21] GHA - only trigger on PR --- .github/workflows/tests-integration.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 9dc55ef6..39f24d84 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -3,7 +3,7 @@ run-name: ${{ github.actor }} is running integration tests permissions: id-token: write contents: read -on: pull_request_target +on: pull_request # make sure only one concurrent run per workflow/branch concurrency: group: ${{ github.workflow }}-${{ github.ref }} From 92e9c65b674889c158199c3281eb8bdb38425f42 Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 17:28:04 +0100 Subject: [PATCH 19/21] GHA - add new stack for functions --- .github/workflows/tests-integration.yml | 18 ++++++- test/integration/default.js | 5 +- test/integration/functions.yml | 69 +++++++++++++++++++++++++ test/integration/payloads/index.js | 33 +++++++++--- test/integration/utils.js | 6 ++- test/integration/vpc.js | 4 +- 6 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 test/integration/functions.yml diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 39f24d84..1ab03acc 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -10,6 +10,7 @@ concurrency: cancel-in-progress: true env: # stack names are reused across jobs + STACK_NAME_FUNCTIONS: aws-lpt-gh-functions STACK_NAME_DEFAULTS: aws-lpt-gh-defaults STACK_NAME_S3: aws-lpt-gh-s3 STACK_NAME_VPC: aws-lpt-gh-vpc @@ -38,7 +39,7 @@ jobs: matrix: # this will deploy the 5 stacks in parallel, # without defining each job individually - stack: ['default', 'vpc', 's3', 'resource', 'custom'] + stack: ['functions', 'default', 'vpc', 's3', 'resource', 'custom'] steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 @@ -77,6 +78,13 @@ jobs: if: steps.cache-sam-build.outputs.cache-hit != 'true' run: sam build --use-container + + - if: matrix.stack == 'functions' + run: | + sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --s3-bucket ${{ secrets.AWS_S3_BUCKET }} --capabilities CAPABILITY_IAM --region ${{ secrets.AWS_REGION }} \ + --template test/integration/functions.yml \ + --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} + # deploy with default params - if: matrix.stack == 'default' run: | @@ -124,7 +132,6 @@ jobs: runs-on: ubuntu-latest env: # sample function for testing (more will come) - FUNCTION_ARN: ${{ secrets.FUNCTION_ARN }} BRANCH_NAME: ${{ github.ref_name }} steps: - uses: actions/checkout@v3 @@ -142,6 +149,13 @@ jobs: role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} aws-region: ${{ secrets.AWS_REGION }} + # define env variable for integration tests (function arns) + - run: | + FUNCTION_ARNS_DEFAULTS=$(aws cloudformation describe-stacks --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} --query 'Stacks[0].Outputs[?OutputKey==`FunctionsDefaults`].OutputValue' --output text) + FUNCTION_ARNS_VPC=$(aws cloudformation describe-stacks --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} --query 'Stacks[0].Outputs[?OutputKey==`FunctionsVpc`].OutputValue' --output text) + echo "FUNCTION_ARNS_DEFAULTS=${FUNCTION_ARNS_DEFAULTS}" >> $GITHUB_ENV + echo "FUNCTION_ARNS_VPC=${FUNCTION_ARNS_VPC}" >> $GITHUB_ENV + # run integrations tests (all in parallel) - run: npm run test-integration diff --git a/test/integration/default.js b/test/integration/default.js index 5bfd01ac..3a1ea031 100644 --- a/test/integration/default.js +++ b/test/integration/default.js @@ -1,13 +1,12 @@ 'use strict'; - const expect = require('expect.js'), utils = require('./utils'), payloads = require('./payloads'); +payloads.init(process.env.FUNCTION_ARNS_DEFAULTS); -//also required: process.env.AWS_REGION; -const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS, process.env.BRANCH_NAME), +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS), payloadSample = payloads.get('sample'), payloadSample2 = payloads.get('sample2'), payloadInvalid = payloads.get('invalid'); diff --git a/test/integration/functions.yml b/test/integration/functions.yml new file mode 100644 index 00000000..05c284f1 --- /dev/null +++ b/test/integration/functions.yml @@ -0,0 +1,69 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 + +Globals: + Function: + Runtime: nodejs16.x + MemorySize: 128 + Timeout: 5 + +Resources: + + FunctionDefaults1: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return "OK" + } + + FunctionDefaults2: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return {'message': 'OK'} + } + + FunctionDefaults3: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return {'statusCode': 200, 'body': JSON.stringify('OK')} + } + + FunctionVpc1: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return "OK" + } + + FunctionVpc2: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return {'message': 'OK'} + } + + +Outputs: + FunctionsDefaults: + Value: !Join [ ",", [ + !GetAtt FunctionDefaults1.Arn, + !GetAtt FunctionDefaults2.Arn, + !GetAtt FunctionDefaults3.Arn, + ]] + FunctionsVpc: + Value: !Join [ ",", [ + !GetAtt FunctionVpc1.Arn, + !GetAtt FunctionVpc2.Arn + ]] diff --git a/test/integration/payloads/index.js b/test/integration/payloads/index.js index bee0e08b..6061cf2a 100644 --- a/test/integration/payloads/index.js +++ b/test/integration/payloads/index.js @@ -1,5 +1,6 @@ -const FUNCTION_ARN = process.env.FUNCTION_ARN; +var functionArns; +var incrementalIndex; const payloads = { sample: require('./sample.json'), @@ -7,16 +8,34 @@ const payloads = { invalid: require('./sample-invalid.json'), }; +module.exports.init = (arns) => { + functionArns = arns; + incrementalIndex = 0; + if (!Array.isArray(functionArns)) { + functionArns = functionArns.split(','); + } + functionArns.forEach((arn, index) => { + functionArns[index] = arn.trim(); // remove spaces + }); +} + module.exports.get = (name, functionName) => { const p = payloads[name]; if (!p) { - throw new Error("Invalid payload name", name); + throw new Error("Invalid payload name:", name); } - if (functionName === undefined && FUNCTION_ARN) { - functionName = FUNCTION_ARN; - } - if (functionName) { - p.lambdaARN = functionName; + + if (functionName === undefined) { + // if enough arns left + if (incrementalIndex < functionArns.length) { + functionName = functionArns[incrementalIndex++]; + } else { + throw new Error("Not enough function arns to run tests"); + } } + + // replace function ARN in payload structure + p.lambdaARN = functionName; + return p; }; \ No newline at end of file diff --git a/test/integration/utils.js b/test/integration/utils.js index 23c55c62..743789b6 100644 --- a/test/integration/utils.js +++ b/test/integration/utils.js @@ -5,10 +5,14 @@ const AWS = require('aws-sdk'), crypto = require("crypto"), utils = module.exports, cfn = new AWS.CloudFormation(), - stepFunctions = new AWS.StepFunctions(); + stepFunctions = new AWS.StepFunctions(), + BRANCH_NAME = process.env.BRANCH_NAME; module.exports.buildStackName = (prefix, branchRef) => { + if (!branchRef && BRANCH_NAME) { + branchRef = BRANCH_NAME; + } return `${prefix}-${branchRef.replace('/', '-')}`; }; diff --git a/test/integration/vpc.js b/test/integration/vpc.js index 1471d6ea..ab6a00ac 100644 --- a/test/integration/vpc.js +++ b/test/integration/vpc.js @@ -4,9 +4,9 @@ const expect = require('expect.js'), utils = require('./utils'), payloads = require('./payloads'); +payloads.init(process.env.FUNCTION_ARNS_VPC); -//also required: process.env.AWS_REGION; -const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS, process.env.BRANCH_NAME), +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS), payloadSample2 = payloads.get('sample2'), payloadInvalid = payloads.get('invalid'); From f67889f0d7eb30a40fb91981736c37ee184924ca Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 17:55:11 +0100 Subject: [PATCH 20/21] GHA - use environment to pause stack deletion --- .github/workflows/tests-integration.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 1ab03acc..82a2cf15 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -167,6 +167,7 @@ jobs: needs: test if: always() # run even if something failed runs-on: ubuntu-latest + environment: Deletion # this will require approval before deleting all stacks strategy: fail-fast: false matrix: From 60b9a6e9e424032e951f4a28880357752a9478fb Mon Sep 17 00:00:00 2001 From: Alex Casalboni Date: Wed, 22 Mar 2023 18:10:05 +0100 Subject: [PATCH 21/21] add environment for deployments, add new test file for S3 stack --- .github/workflows/tests-integration.yml | 3 ++ test/integration/functions.yml | 13 +++++ .../{default.js => test-default.js} | 0 test/integration/test-s3.js | 53 +++++++++++++++++++ test/integration/{vpc.js => test-vpc.js} | 2 +- 5 files changed, 70 insertions(+), 1 deletion(-) rename test/integration/{default.js => test-default.js} (100%) create mode 100644 test/integration/test-s3.js rename test/integration/{vpc.js => test-vpc.js} (95%) diff --git a/.github/workflows/tests-integration.yml b/.github/workflows/tests-integration.yml index 82a2cf15..1a3ba5bd 100644 --- a/.github/workflows/tests-integration.yml +++ b/.github/workflows/tests-integration.yml @@ -34,6 +34,7 @@ jobs: deploy: runs-on: ubuntu-latest if: always() # run all stacks even if one fails + environment: Deployment # this will require approval before deploying all stacks strategy: fail-fast: false matrix: @@ -153,8 +154,10 @@ jobs: - run: | FUNCTION_ARNS_DEFAULTS=$(aws cloudformation describe-stacks --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} --query 'Stacks[0].Outputs[?OutputKey==`FunctionsDefaults`].OutputValue' --output text) FUNCTION_ARNS_VPC=$(aws cloudformation describe-stacks --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} --query 'Stacks[0].Outputs[?OutputKey==`FunctionsVpc`].OutputValue' --output text) + FUNCTION_ARNS_S3=$(aws cloudformation describe-stacks --stack-name $STACK_NAME_FUNCTIONS-${GITHUB_REF_NAME/\//-} --query 'Stacks[0].Outputs[?OutputKey==`FunctionsS3`].OutputValue' --output text) echo "FUNCTION_ARNS_DEFAULTS=${FUNCTION_ARNS_DEFAULTS}" >> $GITHUB_ENV echo "FUNCTION_ARNS_VPC=${FUNCTION_ARNS_VPC}" >> $GITHUB_ENV + echo "FUNCTION_ARNS_S3=${FUNCTION_ARNS_S3}" >> $GITHUB_ENV # run integrations tests (all in parallel) - run: npm run test-integration diff --git a/test/integration/functions.yml b/test/integration/functions.yml index 05c284f1..8b7a5d12 100644 --- a/test/integration/functions.yml +++ b/test/integration/functions.yml @@ -53,6 +53,15 @@ Resources: exports.handler = async (event) => { return {'message': 'OK'} } + + FunctionS3: + Type: AWS::Serverless::Function + Properties: + Handler: index.handler + InlineCode: | + exports.handler = async (event) => { + return {'message': 'OK'} + } Outputs: @@ -67,3 +76,7 @@ Outputs: !GetAtt FunctionVpc1.Arn, !GetAtt FunctionVpc2.Arn ]] + FunctionsS3: + Value: !Join [ ",", [ + !GetAtt FunctionS3.Arn + ]] diff --git a/test/integration/default.js b/test/integration/test-default.js similarity index 100% rename from test/integration/default.js rename to test/integration/test-default.js diff --git a/test/integration/test-s3.js b/test/integration/test-s3.js new file mode 100644 index 00000000..7fb6d995 --- /dev/null +++ b/test/integration/test-s3.js @@ -0,0 +1,53 @@ +'use strict'; + +const expect = require('expect.js'), + utils = require('./utils'), + payloads = require('./payloads'); + +payloads.init(process.env.FUNCTION_ARNS_S3); + +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_S3), + payloadSample = payloads.get('sample'); + +var stateMachineArn, cfnStack; + +const asyncTestsSetup = [ + {payload: payloadSample, name: 'sample', status: 'SUCCEEDED'}, +]; + +// this will start all the executions in parallel +// mocha doesn't allow this for tests in the same file +const fetchStackPromise = utils.fetchStackDetails(STACK_NAME); +fetchStackPromise.then((resp)=>{ + cfnStack = resp.stack; + stateMachineArn = resp.stateMachine; + asyncTestsSetup.forEach((test) => { + test.promise = utils.startExecution(stateMachineArn, test.payload, test.name); + }); +}) + + +describe('S3 Stack', () => { + + // make sure stack details are loaded + // (while state machine executions have already started in parallel) + beforeEach('fetch stack details', async() => { + if (stateMachineArn) return; + await fetchStackPromise; + }); + + it('should exist and be ready to use', async() => { + expect(cfnStack).to.not.be(null); + expect(cfnStack.StackStatus).to.be('CREATE_COMPLETE'); + }); + + describe('State Machine', async() => { + + it('should have a valid ARN', async() => { + expect(stateMachineArn.length).to.be.greaterThan(0); + }); + + utils.generateTests(asyncTestsSetup) + }); + +}); diff --git a/test/integration/vpc.js b/test/integration/test-vpc.js similarity index 95% rename from test/integration/vpc.js rename to test/integration/test-vpc.js index ab6a00ac..67a2f188 100644 --- a/test/integration/vpc.js +++ b/test/integration/test-vpc.js @@ -6,7 +6,7 @@ const expect = require('expect.js'), payloads.init(process.env.FUNCTION_ARNS_VPC); -const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_DEFAULTS), +const STACK_NAME = utils.buildStackName(process.env.STACK_NAME_VPC), payloadSample2 = payloads.get('sample2'), payloadInvalid = payloads.get('invalid');