Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cfnlintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ignore_checks:
- W3002
123 changes: 123 additions & 0 deletions .github/workflows/on-manual-publish-to-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,126 @@ jobs:

- name: "Delegated Deployment via AWS CodeDeploy"
run: echo "Deployment has been delegated to AWS CodeDeploy"

build_and_deploy_lambda:
name: Deploy Lambda to Dev
runs-on: ubuntu-latest
permissions:
id-token: write

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
persist-credentials: false
ref: ${{ inputs.gitRef }}

- name: Set up AWS creds
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # pin@v1-node16
with:
role-to-assume: ${{ secrets.DEV_GH_ACTIONS_ROLE_ARN }}
aws-region: eu-west-2

- name: Set up Node
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
with:
node-version-file: .nvmrc

- name: Set commit SHA
if: github.event.inputs.refType == 'Commit SHA'
run: echo GIT_REF_SHA=${GIT_REF} >> $GITHUB_ENV
env:
GIT_REF: ${{ inputs.gitRef }}

- name: Set commit SHA by branch name
if: github.event.inputs.refType == 'Branch name'
run: echo GIT_REF_SHA=$(git log -1 ${GIT_REF} --pretty=format:%H) >> $GITHUB_ENV
env:
GIT_REF: ${{ inputs.gitRef }}

- name: Set commit SHA by tag
if: github.event.inputs.refType == 'Tag'
run: echo GIT_REF_SHA=$(git rev-list -n 1 ${GIT_REF}) >> $GITHUB_ENV
env:
GIT_REF: ${{ inputs.gitRef }}

- name: Set tag
run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT

- name: Set current datetime
run: echo "date=$(date +'%Y-%m-%dT%H:%M:%S')" >> $GITHUB_OUTPUT

- name: Set up SAM CLI
uses: aws-actions/setup-sam@c71dd89d980e49367c70391e8ada4353f52f2800
with:
use-installer: true
token: ${{ secrets.GITHUB_TOKEN }}

- name: Install dependencies
run: npm ci

- name: Build app
run: npm run build
- name: Install ESbuild
run: npm install -g esbuild@0.23

- name: Set up Python 3.9
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # pin@v4
with:
python-version: "3.9"

- name: SAM validate
run: sam validate --template-file=./nested-stacks/request-count-scaling/template.yaml

- name: SAM build
run: sam build --manifest package.json --template-file=./nested-stacks/request-count-scaling/template.yaml

- name: Deploy app
uses: govuk-one-login/devplatform-upload-action@fda75612a1b0e5a8c84ae7c44a23340e50e5bbde
with:
artifact-bucket-name: ${{ secrets.FRONTEND_LAMBDA_BUCKET_NAME }}
signing-profile-name: ${{ secrets.DEV_SIGNING_PROFILE_NAME }}
template-file: .aws-sam/build/template.yaml


unzip_template_for_nested_stacks:
name: Unzip template for nested stack
runs-on: ubuntu-latest
needs: build_and_deploy_lambda
permissions:
id-token: write

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
persist-credentials: false
ref: ${{ inputs.gitRef }}

- name: Set up AWS creds
uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef # pin@v1-node16
with:
role-to-assume: ${{ secrets.DEV_GH_ACTIONS_ROLE_ARN }}
aws-region: eu-west-2

- name: Set up SAM CLI
uses: aws-actions/setup-sam@c71dd89d980e49367c70391e8ada4353f52f2800
with:
use-installer: true
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Python 3.9
uses: actions/setup-python@d27e3f3d7c64b4bbf8e4abfb9b63b83e846e0435 # pin@v4
with:
python-version: "3.9"

- name: Unzip template for nested stack
id: publish-template
env:
NESTED_STACK_BUCKET_NAME: ${{ secrets.FRONTEND_LAMBDA_BUCKET_NAME }}
run: |
echo "Unzipping template yaml for nested stack"
aws s3 cp "s3://$NESTED_STACK_BUCKET_NAME/template.zip" template.zip
unzip template.zip
aws s3 cp cf-template.yaml "s3://$NESTED_STACK_BUCKET_NAME/nested-stack-template.yaml"

122 changes: 26 additions & 96 deletions deploy/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ Parameters:
AllowedValues:
- CodeDeployDefault.ECSLinear10PercentEvery3Minutes
- CodeDeployDefault.ECSAllAtOnce
# RequestCountScalingTemplateBucket:
# Type: String
# Description: "Request count scaling template S3 bucket name"
# Default: "request-count-scaling"

Conditions:
UseCodeSigning:
Expand Down Expand Up @@ -390,53 +394,6 @@ Resources:
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs

ALBRequestCountScaleOutPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: ALBRequestCountScaleOutPolicy
PolicyType: StepScaling
ResourceId: !Join
- "/"
- - "service"
- !Ref ECSCluster
- !GetAtt ContainerService.Name
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
StepScalingPolicyConfiguration:
AdjustmentType: ChangeInCapacity
Cooldown: 30
StepAdjustments:
- MetricIntervalLowerBound: 0
MetricIntervalUpperBound: 100
ScalingAdjustment: 1 # Add 1 task if requests are 201–300
- MetricIntervalLowerBound: 100
MetricIntervalUpperBound: 300
ScalingAdjustment: 2 # Add 2 tasks if requests are 301–500
- MetricIntervalLowerBound: 300
ScalingAdjustment: 3 # Add 3 tasks if requests > 500

ALBRequestCountScaleInPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: ALBRequestCountScaleInPolicy
PolicyType: StepScaling
ResourceId: !Join
- "/"
- - "service"
- !Ref ECSCluster
- !GetAtt ContainerService.Name
ScalableDimension: ecs:service:DesiredCount
ServiceNamespace: ecs
StepScalingPolicyConfiguration:
AdjustmentType: ChangeInCapacity
Cooldown: 30
StepAdjustments:
- MetricIntervalUpperBound: -100
ScalingAdjustment: -2 # Requests < 100
- MetricIntervalLowerBound: -100
MetricIntervalUpperBound: 0
ScalingAdjustment: -1 # Requests between 100–200

ECSStepScaleOutPolicy:
DependsOn: ContainerAutoScalingTarget
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Expand Down Expand Up @@ -534,50 +491,6 @@ Resources:
Period: "60"
Threshold: "30"

ALBRequestCountScaleOutAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: "ALB-RequestCount-High"
MetricName: "RequestCount"
ActionsEnabled: true
AlarmActions:
- !Ref ALBRequestCountScaleOutPolicy
AlarmDescription: "ALB-RequestCount-Above-200"
DatapointsToAlarm: "1"
Namespace: AWS/ApplicationELB
ComparisonOperator: "GreaterThanThreshold"
Dimensions:
- Name: LoadBalancer
Value: !GetAtt ApplicationLoadBalancer.LoadBalancerFullName
Statistic: Sum
Period: "60"
EvaluationPeriods: 1
Threshold: "2000"
TreatMissingData: "notBreaching"

ALBRequestCountScaleInAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: "ALB-RequestCount-Normal"
MetricName: "RequestCountPerTarget"
ActionsEnabled: true
AlarmActions:
- !Ref ALBRequestCountScaleInPolicy
AlarmDescription: "ALB-RequestCount-Below-200"
DatapointsToAlarm: "1"
Namespace: AWS/ApplicationELB
ComparisonOperator: "LessThanThreshold"
Dimensions:
- Name: LoadBalancer
Value: !GetAtt ApplicationLoadBalancer.LoadBalancerFullName
- Name: TargetGroup
Value: !Ref ContainerAutoScalingTarget
Statistic: Sum
Period: "60"
EvaluationPeriods: 1
Threshold: "1000"
TreatMissingData: "notBreaching"

ContainerServiceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
Expand Down Expand Up @@ -2079,10 +1992,6 @@ Resources:
DependsOn:
- AppFrontCustomDomain

#
# Metrics and Alarms
#

# API Gateway Alarms

# 4xx Status Code
Expand Down Expand Up @@ -2338,7 +2247,6 @@ Resources:
#
# Canary Deployment
#

ECSCanaryDeploymentStack:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
Expand Down Expand Up @@ -2367,6 +2275,28 @@ Resources:
- ELB5XX10PercentAlarm: !Ref ELB5XX10PercentAlarm
LoggerErrorRateAlarm: !Ref LoggerErrorRateAlarm

#
# RequestCount Scale Stack
#
RequestCountScaleStack:
Type: AWS::CloudFormation::Stack
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
TemplateURL: https://template-bucket-templatebucket-civakigopbg2.s3.eu-west-2.amazonaws.com/request-count-scaling/template.yaml
Parameters:
PermissionsBoundary: !Sub "arn:aws:iam::${AWS::AccountId}:policy/account-mgmt-frontend-pipeline-RequestCountScalingBoundary"
CodeSigningConfigArn: !If
- UseCodeSigning
- !Ref CodeSigningConfigArn
- !Ref AWS::NoValue
ECSClusterName: !Ref ECSCluster
ECSServiceName: !GetAtt ContainerService.Name
ApplicationLoadBalancerName: !GetAtt ApplicationLoadBalancer.LoadBalancerFullName
ContainerAutoScalingTarget: !Ref ContainerAutoScalingTarget
ParentStackName: !Sub "${AWS::StackName}"
VpcStackName: !Sub "${VpcStackName}"

Outputs:
ApiGatewayEndpoint:
Description: The base URI for this application.
Expand Down
1 change: 1 addition & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default [
"dev-app.js",
"integration-tests",
"eslint.config.mjs",
"src/lambda-handlers/ecs-status-handler.ts"
],
},
{
Expand Down
Loading
Loading