diff --git a/.github/workflows/ar-ci.yml b/.github/workflows/ar-ci.yml deleted file mode 100644 index cc325399f7d..00000000000 --- a/.github/workflows/ar-ci.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: AR CI - -on: - push: - workflow_dispatch: - -# Allow queued workflows to interrupt previous runs -concurrency: - group: ${{ github.workflow }}-${{ github.event.number || github.ref }} - cancel-in-progress: true - -# Allow GitHub to request an OIDC JWT ID token, and to comment on pull requests -# as required by guardian/actions-riff-raff -permissions: - id-token: write - contents: read - pull-requests: write - -jobs: - build: - name: AR CI - runs-on: ubuntu-latest - - # Checkout the repository - steps: - - uses: actions/checkout@v6 - - - name: Set up Node environment - uses: ./.github/actions/setup-node-env - - # Execute some tasks from the `apps-rendering/package.json` file, using `pnpm` - - name: Build and package - working-directory: apps-rendering - run: | - pnpm test - pnpm build:client:prod - pnpm build:server:prod - pnpm copy-manifest - pnpm copy-fonts - pnpm synth - zip -j dist/server/mobile-apps-rendering.zip dist/server/* - - - name: Upload to riff-raff - uses: guardian/actions-riff-raff@v4 - with: - githubToken: ${{ secrets.GITHUB_TOKEN }} - roleArn: ${{ secrets.GU_RIFF_RAFF_ROLE_ARN }} - configPath: apps-rendering/riff-raff.yaml - projectName: Mobile::mobile-apps-rendering - buildNumberOffset: 27000 # This is the last build number from TeamCity - contentDirectories: | - mobile-apps-rendering-cfn: - - apps-rendering/cdk.out/MobileAppsRendering-CODE.template.json - - apps-rendering/cdk.out/MobileAppsRendering-PROD.template.json - mobile-apps-rendering-preview-cfn: - - apps-rendering/cdk.out/MobileAppsRenderingPreview-CODE.template.json - - apps-rendering/cdk.out/MobileAppsRenderingPreview-PROD.template.json - mobile-apps-rendering: - - apps-rendering/dist/server/mobile-apps-rendering.zip - mobile-assets: - - apps-rendering/dist/assets/ diff --git a/apps-rendering/.eslintignore b/apps-rendering/.eslintignore index c6bdc2f0462..626c5dfedd0 100644 --- a/apps-rendering/.eslintignore +++ b/apps-rendering/.eslintignore @@ -2,4 +2,3 @@ node_modules api-models webpack.config.ts -cdk.out diff --git a/apps-rendering/.gitignore b/apps-rendering/.gitignore index 4a60cbf2861..5fe6149f13c 100644 --- a/apps-rendering/.gitignore +++ b/apps-rendering/.gitignore @@ -25,7 +25,3 @@ dist # Istanbul/Jest code coverage coverage - -# CDK asset staging directory -.cdk.staging -cdk.out diff --git a/apps-rendering/artifact.json b/apps-rendering/artifact.json deleted file mode 100644 index 26c227f9c16..00000000000 --- a/apps-rendering/artifact.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "projectName": "Mobile::mobile-apps-rendering", - "vcsURL": "https://github.com/guardian/dotcom-rendering", - "actions": [ - { - "action": "mobile-apps-rendering", - "path": "dist/server", - "compress": "zip" - }, - { - "action": "mobile-assets", - "path": "dist/assets", - "compress": false - }, - { - "action": "mobile-apps-rendering-cfn", - "path": "cdk.out/MobileAppsRendering-CODE.template.json", - "compress": false - }, - { - "action": "mobile-apps-rendering-cfn", - "path": "cdk.out/MobileAppsRendering-PROD.template.json", - "compress": false - }, - { - "action": "mobile-apps-rendering-preview-cfn", - "path": "cdk.out/MobileAppsRenderingPreview-CODE.template.json", - "compress": false - }, - { - "action": "mobile-apps-rendering-preview-cfn", - "path": "cdk.out/MobileAppsRenderingPreview-PROD.template.json", - "compress": false - } - ] -} diff --git a/apps-rendering/cdk.json b/apps-rendering/cdk.json deleted file mode 100644 index 972a4f08ad9..00000000000 --- a/apps-rendering/cdk.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "app": "pnpm tsx cdk/bin/cdk.ts", - "context": { - "aws-cdk:enableDiffNoFail": "true", - "@aws-cdk/core:stackRelativeExports": "true" - } -} diff --git a/apps-rendering/cdk/README.md b/apps-rendering/cdk/README.md deleted file mode 100644 index aa31acc1103..00000000000 --- a/apps-rendering/cdk/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Infrastructure - -This directory defines the components to be deployed to AWS diff --git a/apps-rendering/cdk/bin/cdk.ts b/apps-rendering/cdk/bin/cdk.ts deleted file mode 100644 index 0be4a30ed31..00000000000 --- a/apps-rendering/cdk/bin/cdk.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { App } from 'aws-cdk-lib'; -import { MobileAppsRendering } from '../lib/mobile-apps-rendering'; -import { InstanceSize } from 'aws-cdk-lib/aws-ec2'; - -const app = new App(); - -// ----- MobileAppsRendering CODE ----- // -new MobileAppsRendering(app, 'MobileAppsRendering-CODE', { - stack: 'mobile', - stage: 'CODE', - recordPrefix: 'mobile-rendering', - asgCapacity: { - minimumInstances: 1, - maximumInstances: 2, - }, - instanceSize: InstanceSize.MICRO, - appsRenderingDomain: 'mobile-aws.code.dev-guardianapis.com', - hostedZoneId: 'Z6PRU8YR6TQDK', - targetCpuUtilisation: 20, -}); - -// ----- MobileAppsRendering PROD ----- // -new MobileAppsRendering(app, 'MobileAppsRendering-PROD', { - stack: 'mobile', - stage: 'PROD', - recordPrefix: 'mobile-rendering', - asgCapacity: { - minimumInstances: 3, - maximumInstances: 12, - }, - instanceSize: InstanceSize.MICRO, - appsRenderingDomain: 'mobile-aws.guardianapis.com', - hostedZoneId: 'Z1EYB4AREPXE3B', - targetCpuUtilisation: 20, -}); - -// ----- MobileAppsRenderingPreview CODE ----- // -new MobileAppsRendering(app, 'MobileAppsRenderingPreview-CODE', { - stack: 'mobile-preview', - stage: 'CODE', - recordPrefix: 'mobile-preview-rendering', - asgCapacity: { - minimumInstances: 1, - maximumInstances: 2, - }, - instanceSize: InstanceSize.MICRO, - appsRenderingDomain: 'mobile-aws.code.dev-guardianapis.com', - hostedZoneId: 'Z6PRU8YR6TQDK', - targetCpuUtilisation: 20, -}); - -// ----- MobileAppsRenderingPreview PROD ----- // -new MobileAppsRendering(app, 'MobileAppsRenderingPreview-PROD', { - stack: 'mobile-preview', - stage: 'PROD', - recordPrefix: 'mobile-preview-rendering', - asgCapacity: { - minimumInstances: 1, - maximumInstances: 2, - }, - instanceSize: InstanceSize.MICRO, - appsRenderingDomain: 'mobile-aws.guardianapis.com', - hostedZoneId: 'Z1EYB4AREPXE3B', - targetCpuUtilisation: 20, -}); diff --git a/apps-rendering/cdk/lib/__snapshots__/mobile-apps-rendering.test.ts.snap b/apps-rendering/cdk/lib/__snapshots__/mobile-apps-rendering.test.ts.snap deleted file mode 100644 index aacd44a4d46..00000000000 --- a/apps-rendering/cdk/lib/__snapshots__/mobile-apps-rendering.test.ts.snap +++ /dev/null @@ -1,1979 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`The MobileAppsRendering stack matches the snapshot 1`] = ` -{ - "Metadata": { - "gu:cdk:constructs": [ - "GuAllowPolicy", - "GuVpcParameter", - "GuSubnetListParameter", - "GuSubnetListParameter", - "GuEc2App", - "GuCertificate", - "GuInstanceRole", - "GuSsmSshPolicy", - "GuDescribeEC2Policy", - "GuLoggingStreamNameParameter", - "GuLogShippingPolicy", - "GuDistributionBucketParameter", - "GuGetDistributablePolicy", - "GuParameterStoreReadPolicy", - "GuAmiParameter", - "GuHttpsEgressSecurityGroup", - "GuAutoScalingGroup", - "GuApplicationLoadBalancer", - "GuApplicationTargetGroup", - "GuHttpsApplicationListener", - "GuSecurityGroup", - ], - "gu:cdk:version": "TEST", - }, - "Outputs": { - "LoadBalancerMobileappsrenderingDnsName": { - "Description": "DNS entry for LoadBalancerMobileappsrendering", - "Value": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingB8B00ACB", - "DNSName", - ], - }, - }, - }, - "Parameters": { - "AMIMobileappsrendering": { - "Description": "Amazon Machine Image ID for the app mobile-apps-rendering. Use this in conjunction with AMIgo to keep AMIs up to date.", - "Type": "AWS::EC2::Image::Id", - }, - "DistributionBucketName": { - "Default": "/account/services/artifact.bucket", - "Description": "SSM parameter containing the S3 bucket name holding distribution artifacts", - "Type": "AWS::SSM::Parameter::Value", - }, - "LoggingStreamName": { - "Default": "/account/services/logging.stream.name", - "Description": "SSM parameter containing the Name (not ARN) on the kinesis stream", - "Type": "AWS::SSM::Parameter::Value", - }, - "SsmParameterValueaccountservicesartifactbucketC96584B6F00A464EAD1953AFF4B05118Parameter": { - "Default": "/account/services/artifact.bucket", - "Type": "AWS::SSM::Parameter::Value", - }, - "VpcId": { - "Default": "/account/vpc/primary/id", - "Description": "Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.", - "Type": "AWS::SSM::Parameter::Value", - }, - "mobileappsrenderingPrivateSubnets": { - "Default": "/account/vpc/primary/subnets/private", - "Description": "A list of private subnets", - "Type": "AWS::SSM::Parameter::Value>", - }, - "mobileappsrenderingPublicSubnets": { - "Default": "/account/vpc/primary/subnets/public", - "Description": "A list of public subnets", - "Type": "AWS::SSM::Parameter::Value>", - }, - }, - "Resources": { - "AutoScalingGroupMobileappsrenderingASG42891F00": { - "Properties": { - "HealthCheckGracePeriod": 120, - "HealthCheckType": "ELB", - "LaunchTemplate": { - "LaunchTemplateId": { - "Ref": "mobileTESTmobileappsrenderingAD91FF83", - }, - "Version": { - "Fn::GetAtt": [ - "mobileTESTmobileappsrenderingAD91FF83", - "LatestVersionNumber", - ], - }, - }, - "MaxSize": "2", - "MetricsCollection": [ - { - "Granularity": "1Minute", - }, - ], - "MinSize": "1", - "Tags": [ - { - "Key": "App", - "PropagateAtLaunch": true, - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "PropagateAtLaunch": true, - "Value": "TEST", - }, - { - "Key": "gu:repo", - "PropagateAtLaunch": true, - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "LogKinesisStreamName", - "PropagateAtLaunch": true, - "Value": { - "Ref": "LoggingStreamName", - }, - }, - { - "Key": "Stack", - "PropagateAtLaunch": true, - "Value": "mobile", - }, - { - "Key": "Stage", - "PropagateAtLaunch": true, - "Value": "TEST", - }, - ], - "TargetGroupARNs": [ - { - "Ref": "TargetGroupMobileappsrendering29320E35", - }, - ], - "VPCZoneIdentifier": { - "Ref": "mobileappsrenderingPrivateSubnets", - }, - }, - "Type": "AWS::AutoScaling::AutoScalingGroup", - }, - "AutoScalingGroupMobileappsrenderingScalingPolicyCpuScalingPolicy25F424F1": { - "Properties": { - "AutoScalingGroupName": { - "Ref": "AutoScalingGroupMobileappsrenderingASG42891F00", - }, - "PolicyType": "TargetTrackingScaling", - "TargetTrackingConfiguration": { - "PredefinedMetricSpecification": { - "PredefinedMetricType": "ASGAverageCPUUtilization", - }, - "TargetValue": 10, - }, - }, - "Type": "AWS::AutoScaling::ScalingPolicy", - }, - "CertificateMobileappsrendering85649D08": { - "DeletionPolicy": "Retain", - "Properties": { - "DomainName": "mobile-rendering.mobile-aws.code.dev-guardianapis.com", - "DomainValidationOptions": [ - { - "DomainName": "mobile-rendering.mobile-aws.code.dev-guardianapis.com", - "HostedZoneId": "TEST-HOSTED-ZONE-ID", - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRendering/CertificateMobileappsrendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "ValidationMethod": "DNS", - }, - "Type": "AWS::CertificateManager::Certificate", - "UpdateReplacePolicy": "Retain", - }, - "DescribeEC2PolicyFF5F9295": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeTags", - "ec2:DescribeInstances", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "describe-ec2-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "DnsRecord": { - "Properties": { - "HostedZoneId": "TEST-HOSTED-ZONE-ID", - "Name": "mobile-rendering.mobile-aws.code.dev-guardianapis.com.", - "ResourceRecords": [ - { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingB8B00ACB", - "DNSName", - ], - }, - ], - "TTL": "3600", - "Type": "CNAME", - }, - "Type": "AWS::Route53::RecordSet", - }, - "GetDistributablePolicyMobileappsrendering8E649036": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:GetObject", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "DistributionBucketName", - }, - "/mobile/TEST/mobile-apps-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetDistributablePolicyMobileappsrendering8E649036", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GetParametersByPath37B32C62": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "ssm:GetParametersByPath", - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetParametersByPath37B32C62", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660": { - "Properties": { - "GroupDescription": "Allow all outbound HTTPS traffic", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound HTTPS traffic", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "GuHttpsEgressSecurityGroupMobileappsrenderingfromMobileAppsRenderingInternalIngressSecurityGroupMobileappsrenderingB407C3A230407E6A596B": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuHttpsEgressSecurityGroupMobileappsrenderingfromMobileAppsRenderingLoadBalancerMobileappsrenderingSecurityGroupE0CCF7183040505B735B": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuLogShippingPolicy981BFE5A": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "kinesis:Describe*", - "kinesis:Put*", - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:kinesis:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":stream/", - { - "Ref": "LoggingStreamName", - }, - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GuLogShippingPolicy981BFE5A", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "InstanceRoleMobileappsrenderingEC64402A": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "Path": "/", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "InternalIngressSecurityGroupMobileappsrendering486B411A": { - "Properties": { - "GroupDescription": "Allow restricted ingress from CIDR ranges", - "SecurityGroupIngress": [ - { - "CidrIp": "10.0.0.0/8", - "Description": "Allow access on port 443 from 10.0.0.0/8", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "InternalIngressSecurityGroupMobileappsrenderingtoMobileAppsRenderingGuHttpsEgressSecurityGroupMobileappsrenderingC4F35269304093993953": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "ListenerMobileappsrendering47F84352": { - "Properties": { - "Certificates": [ - { - "CertificateArn": { - "Ref": "CertificateMobileappsrendering85649D08", - }, - }, - ], - "DefaultActions": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupMobileappsrendering29320E35", - }, - "Type": "forward", - }, - ], - "LoadBalancerArn": { - "Ref": "LoadBalancerMobileappsrenderingB8B00ACB", - }, - "Port": 443, - "Protocol": "HTTPS", - "SslPolicy": "ELBSecurityPolicy-TLS13-1-2-2021-06", - }, - "Type": "AWS::ElasticLoadBalancingV2::Listener", - }, - "LoadBalancerMobileappsrenderingB8B00ACB": { - "Properties": { - "LoadBalancerAttributes": [ - { - "Key": "deletion_protection.enabled", - "Value": "true", - }, - { - "Key": "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", - "Value": "true", - }, - { - "Key": "routing.http.drop_invalid_header_fields.enabled", - "Value": "true", - }, - { - "Key": "access_logs.s3.enabled", - "Value": "false", - }, - { - "Key": "idle_timeout.timeout_seconds", - "Value": "4", - }, - ], - "Scheme": "internal", - "SecurityGroups": [ - { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - ], - "Subnets": { - "Ref": "mobileappsrenderingPrivateSubnets", - }, - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "Type": "application", - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - }, - "LoadBalancerMobileappsrenderingSecurityGroup86D57550": { - "Properties": { - "GroupDescription": "Automatically created Security Group for ELB MobileAppsRenderingLoadBalancerMobileappsrendering801C2FFB", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "LoadBalancerMobileappsrenderingSecurityGrouptoMobileAppsRenderingGuHttpsEgressSecurityGroupMobileappsrenderingC4F35269304019F57E42": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "ParameterStoreReadMobileappsrenderingA4006661": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "ssm:GetParametersByPath", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":parameter/TEST/mobile/mobile-apps-rendering", - ], - ], - }, - }, - { - "Action": [ - "ssm:GetParameters", - "ssm:GetParameter", - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":parameter/TEST/mobile/mobile-apps-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "parameter-store-read-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "SsmSshPolicy4CFC977E": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ec2messages:AcknowledgeMessage", - "ec2messages:DeleteMessage", - "ec2messages:FailMessage", - "ec2messages:GetEndpoint", - "ec2messages:GetMessages", - "ec2messages:SendReply", - "ssm:UpdateInstanceInformation", - "ssm:ListInstanceAssociations", - "ssm:DescribeInstanceProperties", - "ssm:DescribeDocumentParameters", - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "ssm-ssh-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "TargetGroupMobileappsrendering29320E35": { - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/healthcheck", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 5, - "Port": 3040, - "Protocol": "HTTP", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "30", - }, - { - "Key": "stickiness.enabled", - "Value": "false", - }, - ], - "TargetType": "instance", - "UnhealthyThresholdCount": 2, - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - }, - "mobileTESTmobileappsrenderingAD91FF83": { - "DependsOn": [ - "InstanceRoleMobileappsrenderingEC64402A", - ], - "Properties": { - "LaunchTemplateData": { - "IamInstanceProfile": { - "Arn": { - "Fn::GetAtt": [ - "mobileTESTmobileappsrenderingProfileA8EFA7CB", - "Arn", - ], - }, - }, - "ImageId": { - "Ref": "AMIMobileappsrendering", - }, - "InstanceType": "t4g.small", - "MetadataOptions": { - "HttpTokens": "required", - "InstanceMetadataTags": "enabled", - }, - "Monitoring": { - "Enabled": false, - }, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - ], - "TagSpecifications": [ - { - "ResourceType": "instance", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRendering/mobile-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - { - "ResourceType": "volume", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRendering/mobile-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - ], - "UserData": { - "Fn::Base64": { - "Fn::Join": [ - "", - [ - "#!/bin/bash -set -ev -groupadd mapi -useradd -r -m -s /usr/bin/nologin -g mapi mobile-apps-rendering -export App=mobile-apps-rendering -export Stack=mobile -export Stage=TEST -export NODE_ENV=production -aws s3 cp s3://", - { - "Ref": "SsmParameterValueaccountservicesartifactbucketC96584B6F00A464EAD1953AFF4B05118Parameter", - }, - "/mobile/TEST/mobile-apps-rendering/mobile-apps-rendering.zip /tmp -mkdir -p /opt/mobile-apps-rendering -unzip /tmp/mobile-apps-rendering.zip -d /opt/mobile-apps-rendering -chown -R mobile-apps-rendering:mapi /opt/mobile-apps-rendering -mkdir -p /usr/share/mobile-apps-rendering/logs -chown -R mobile-apps-rendering:mapi /usr/share/mobile-apps-rendering -ln -s /usr/share/mobile-apps-rendering/logs /var/log/mobile-apps-rendering -chown -R mobile-apps-rendering:mapi /var/log/mobile-apps-rendering -export PM2_HOME="/usr/share/mobile-apps-rendering" -export ASSETS_MANIFEST="/opt/mobile-apps-rendering/manifest.json" -/usr/local/node/pm2 start --name mobile-apps-rendering --uid mobile-apps-rendering --gid mapi /opt/mobile-apps-rendering/server.js -/opt/aws-kinesis-agent/configure-aws-kinesis-agent ", - { - "Ref": "AWS::Region", - }, - " mobile-log-aggregation-TEST '/var/log/mobile-apps-rendering/*' -/usr/local/node/pm2 logrotate -u mobile-apps-rendering", - ], - ], - }, - }, - }, - "TagSpecifications": [ - { - "ResourceType": "launch-template", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRendering/mobile-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - ], - }, - "Type": "AWS::EC2::LaunchTemplate", - }, - "mobileTESTmobileappsrenderingProfileA8EFA7CB": { - "Properties": { - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::InstanceProfile", - }, - }, -} -`; - -exports[`The MobileAppsRenderingPreview stack matches the snapshot 1`] = ` -{ - "Metadata": { - "gu:cdk:constructs": [ - "GuAllowPolicy", - "GuVpcParameter", - "GuSubnetListParameter", - "GuSubnetListParameter", - "GuEc2App", - "GuCertificate", - "GuInstanceRole", - "GuSsmSshPolicy", - "GuDescribeEC2Policy", - "GuLoggingStreamNameParameter", - "GuLogShippingPolicy", - "GuDistributionBucketParameter", - "GuGetDistributablePolicy", - "GuParameterStoreReadPolicy", - "GuAmiParameter", - "GuHttpsEgressSecurityGroup", - "GuAutoScalingGroup", - "GuApplicationLoadBalancer", - "GuApplicationTargetGroup", - "GuHttpsApplicationListener", - "GuSecurityGroup", - ], - "gu:cdk:version": "TEST", - }, - "Outputs": { - "LoadBalancerMobileappsrenderingDnsName": { - "Description": "DNS entry for LoadBalancerMobileappsrendering", - "Value": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingB8B00ACB", - "DNSName", - ], - }, - }, - }, - "Parameters": { - "AMIMobileappsrendering": { - "Description": "Amazon Machine Image ID for the app mobile-apps-rendering. Use this in conjunction with AMIgo to keep AMIs up to date.", - "Type": "AWS::EC2::Image::Id", - }, - "DistributionBucketName": { - "Default": "/account/services/artifact.bucket", - "Description": "SSM parameter containing the S3 bucket name holding distribution artifacts", - "Type": "AWS::SSM::Parameter::Value", - }, - "LoggingStreamName": { - "Default": "/account/services/logging.stream.name", - "Description": "SSM parameter containing the Name (not ARN) on the kinesis stream", - "Type": "AWS::SSM::Parameter::Value", - }, - "SsmParameterValueaccountservicesartifactbucketC96584B6F00A464EAD1953AFF4B05118Parameter": { - "Default": "/account/services/artifact.bucket", - "Type": "AWS::SSM::Parameter::Value", - }, - "VpcId": { - "Default": "/account/vpc/primary/id", - "Description": "Virtual Private Cloud to run EC2 instances within. Should NOT be the account default VPC.", - "Type": "AWS::SSM::Parameter::Value", - }, - "mobileappsrenderingPrivateSubnets": { - "Default": "/account/vpc/primary/subnets/private", - "Description": "A list of private subnets", - "Type": "AWS::SSM::Parameter::Value>", - }, - "mobileappsrenderingPublicSubnets": { - "Default": "/account/vpc/primary/subnets/public", - "Description": "A list of public subnets", - "Type": "AWS::SSM::Parameter::Value>", - }, - }, - "Resources": { - "AutoScalingGroupMobileappsrenderingASG42891F00": { - "Properties": { - "HealthCheckGracePeriod": 120, - "HealthCheckType": "ELB", - "LaunchTemplate": { - "LaunchTemplateId": { - "Ref": "mobilepreviewTESTmobileappsrenderingFF204ED7", - }, - "Version": { - "Fn::GetAtt": [ - "mobilepreviewTESTmobileappsrenderingFF204ED7", - "LatestVersionNumber", - ], - }, - }, - "MaxSize": "2", - "MetricsCollection": [ - { - "Granularity": "1Minute", - }, - ], - "MinSize": "1", - "Tags": [ - { - "Key": "App", - "PropagateAtLaunch": true, - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "PropagateAtLaunch": true, - "Value": "TEST", - }, - { - "Key": "gu:repo", - "PropagateAtLaunch": true, - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "LogKinesisStreamName", - "PropagateAtLaunch": true, - "Value": { - "Ref": "LoggingStreamName", - }, - }, - { - "Key": "Stack", - "PropagateAtLaunch": true, - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "PropagateAtLaunch": true, - "Value": "TEST", - }, - ], - "TargetGroupARNs": [ - { - "Ref": "TargetGroupMobileappsrendering29320E35", - }, - ], - "VPCZoneIdentifier": { - "Ref": "mobileappsrenderingPrivateSubnets", - }, - }, - "Type": "AWS::AutoScaling::AutoScalingGroup", - }, - "AutoScalingGroupMobileappsrenderingScalingPolicyCpuScalingPolicy25F424F1": { - "Properties": { - "AutoScalingGroupName": { - "Ref": "AutoScalingGroupMobileappsrenderingASG42891F00", - }, - "PolicyType": "TargetTrackingScaling", - "TargetTrackingConfiguration": { - "PredefinedMetricSpecification": { - "PredefinedMetricType": "ASGAverageCPUUtilization", - }, - "TargetValue": 10, - }, - }, - "Type": "AWS::AutoScaling::ScalingPolicy", - }, - "CertificateMobileappsrendering85649D08": { - "DeletionPolicy": "Retain", - "Properties": { - "DomainName": "mobile-preview-rendering.mobile-aws.code.dev-guardianapis.com", - "DomainValidationOptions": [ - { - "DomainName": "mobile-preview-rendering.mobile-aws.code.dev-guardianapis.com", - "HostedZoneId": "TEST-HOSTED-ZONE-ID", - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRenderingPreview/CertificateMobileappsrendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "ValidationMethod": "DNS", - }, - "Type": "AWS::CertificateManager::Certificate", - "UpdateReplacePolicy": "Retain", - }, - "DescribeEC2PolicyFF5F9295": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "autoscaling:DescribeAutoScalingInstances", - "autoscaling:DescribeAutoScalingGroups", - "ec2:DescribeTags", - "ec2:DescribeInstances", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "describe-ec2-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "DnsRecord": { - "Properties": { - "HostedZoneId": "TEST-HOSTED-ZONE-ID", - "Name": "mobile-preview-rendering.mobile-aws.code.dev-guardianapis.com.", - "ResourceRecords": [ - { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingB8B00ACB", - "DNSName", - ], - }, - ], - "TTL": "3600", - "Type": "CNAME", - }, - "Type": "AWS::Route53::RecordSet", - }, - "GetDistributablePolicyMobileappsrendering8E649036": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "s3:GetObject", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:s3:::", - { - "Ref": "DistributionBucketName", - }, - "/mobile-preview/TEST/mobile-apps-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetDistributablePolicyMobileappsrendering8E649036", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GetParametersByPath37B32C62": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "ssm:GetParametersByPath", - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GetParametersByPath37B32C62", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660": { - "Properties": { - "GroupDescription": "Allow all outbound HTTPS traffic", - "SecurityGroupEgress": [ - { - "CidrIp": "0.0.0.0/0", - "Description": "Allow all outbound HTTPS traffic", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "GuHttpsEgressSecurityGroupMobileappsrenderingfromMobileAppsRenderingPreviewInternalIngressSecurityGroupMobileappsrendering981D8A7F30401C964232": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuHttpsEgressSecurityGroupMobileappsrenderingfromMobileAppsRenderingPreviewLoadBalancerMobileappsrenderingSecurityGroupA08E152F304032151D11": { - "Properties": { - "Description": "Load balancer to target", - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "SourceSecurityGroupId": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupIngress", - }, - "GuLogShippingPolicy981BFE5A": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "kinesis:Describe*", - "kinesis:Put*", - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:kinesis:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":stream/", - { - "Ref": "LoggingStreamName", - }, - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "GuLogShippingPolicy981BFE5A", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "InstanceRoleMobileappsrenderingEC64402A": { - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": "ec2.amazonaws.com", - }, - }, - ], - "Version": "2012-10-17", - }, - "Path": "/", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - "Type": "AWS::IAM::Role", - }, - "InternalIngressSecurityGroupMobileappsrendering486B411A": { - "Properties": { - "GroupDescription": "Allow restricted ingress from CIDR ranges", - "SecurityGroupIngress": [ - { - "CidrIp": "10.0.0.0/8", - "Description": "Allow access on port 443 from 10.0.0.0/8", - "FromPort": 443, - "IpProtocol": "tcp", - "ToPort": 443, - }, - ], - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "InternalIngressSecurityGroupMobileappsrenderingtoMobileAppsRenderingPreviewGuHttpsEgressSecurityGroupMobileappsrendering86AAA55B30406414828D": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "ListenerMobileappsrendering47F84352": { - "Properties": { - "Certificates": [ - { - "CertificateArn": { - "Ref": "CertificateMobileappsrendering85649D08", - }, - }, - ], - "DefaultActions": [ - { - "TargetGroupArn": { - "Ref": "TargetGroupMobileappsrendering29320E35", - }, - "Type": "forward", - }, - ], - "LoadBalancerArn": { - "Ref": "LoadBalancerMobileappsrenderingB8B00ACB", - }, - "Port": 443, - "Protocol": "HTTPS", - "SslPolicy": "ELBSecurityPolicy-TLS13-1-2-2021-06", - }, - "Type": "AWS::ElasticLoadBalancingV2::Listener", - }, - "LoadBalancerMobileappsrenderingB8B00ACB": { - "Properties": { - "LoadBalancerAttributes": [ - { - "Key": "deletion_protection.enabled", - "Value": "true", - }, - { - "Key": "routing.http.x_amzn_tls_version_and_cipher_suite.enabled", - "Value": "true", - }, - { - "Key": "routing.http.drop_invalid_header_fields.enabled", - "Value": "true", - }, - { - "Key": "access_logs.s3.enabled", - "Value": "false", - }, - { - "Key": "idle_timeout.timeout_seconds", - "Value": "4", - }, - ], - "Scheme": "internal", - "SecurityGroups": [ - { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - { - "Fn::GetAtt": [ - "InternalIngressSecurityGroupMobileappsrendering486B411A", - "GroupId", - ], - }, - ], - "Subnets": { - "Ref": "mobileappsrenderingPrivateSubnets", - }, - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "Type": "application", - }, - "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", - }, - "LoadBalancerMobileappsrenderingSecurityGroup86D57550": { - "Properties": { - "GroupDescription": "Automatically created Security Group for ELB MobileAppsRenderingPreviewLoadBalancerMobileappsrenderingA476639F", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::EC2::SecurityGroup", - }, - "LoadBalancerMobileappsrenderingSecurityGrouptoMobileAppsRenderingPreviewGuHttpsEgressSecurityGroupMobileappsrendering86AAA55B3040C6508311": { - "Properties": { - "Description": "Load balancer to target", - "DestinationSecurityGroupId": { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - "FromPort": 3040, - "GroupId": { - "Fn::GetAtt": [ - "LoadBalancerMobileappsrenderingSecurityGroup86D57550", - "GroupId", - ], - }, - "IpProtocol": "tcp", - "ToPort": 3040, - }, - "Type": "AWS::EC2::SecurityGroupEgress", - }, - "ParameterStoreReadMobileappsrenderingA4006661": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": "ssm:GetParametersByPath", - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":parameter/TEST/mobile-preview/mobile-apps-rendering", - ], - ], - }, - }, - { - "Action": [ - "ssm:GetParameters", - "ssm:GetParameter", - ], - "Effect": "Allow", - "Resource": { - "Fn::Join": [ - "", - [ - "arn:aws:ssm:", - { - "Ref": "AWS::Region", - }, - ":", - { - "Ref": "AWS::AccountId", - }, - ":parameter/TEST/mobile-preview/mobile-apps-rendering/*", - ], - ], - }, - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "parameter-store-read-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "SsmSshPolicy4CFC977E": { - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "ec2messages:AcknowledgeMessage", - "ec2messages:DeleteMessage", - "ec2messages:FailMessage", - "ec2messages:GetEndpoint", - "ec2messages:GetMessages", - "ec2messages:SendReply", - "ssm:UpdateInstanceInformation", - "ssm:ListInstanceAssociations", - "ssm:DescribeInstanceProperties", - "ssm:DescribeDocumentParameters", - "ssmmessages:CreateControlChannel", - "ssmmessages:CreateDataChannel", - "ssmmessages:OpenControlChannel", - "ssmmessages:OpenDataChannel", - ], - "Effect": "Allow", - "Resource": "*", - }, - ], - "Version": "2012-10-17", - }, - "PolicyName": "ssm-ssh-policy", - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::Policy", - }, - "TargetGroupMobileappsrendering29320E35": { - "Properties": { - "HealthCheckIntervalSeconds": 10, - "HealthCheckPath": "/healthcheck", - "HealthCheckProtocol": "HTTP", - "HealthCheckTimeoutSeconds": 5, - "HealthyThresholdCount": 5, - "Port": 3040, - "Protocol": "HTTP", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - "TargetGroupAttributes": [ - { - "Key": "deregistration_delay.timeout_seconds", - "Value": "30", - }, - { - "Key": "stickiness.enabled", - "Value": "false", - }, - ], - "TargetType": "instance", - "UnhealthyThresholdCount": 2, - "VpcId": { - "Ref": "VpcId", - }, - }, - "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", - }, - "mobilepreviewTESTmobileappsrenderingFF204ED7": { - "DependsOn": [ - "InstanceRoleMobileappsrenderingEC64402A", - ], - "Properties": { - "LaunchTemplateData": { - "IamInstanceProfile": { - "Arn": { - "Fn::GetAtt": [ - "mobilepreviewTESTmobileappsrenderingProfile72DADF5F", - "Arn", - ], - }, - }, - "ImageId": { - "Ref": "AMIMobileappsrendering", - }, - "InstanceType": "t4g.micro", - "MetadataOptions": { - "HttpTokens": "required", - "InstanceMetadataTags": "enabled", - }, - "Monitoring": { - "Enabled": false, - }, - "SecurityGroupIds": [ - { - "Fn::GetAtt": [ - "GuHttpsEgressSecurityGroupMobileappsrendering089F1660", - "GroupId", - ], - }, - ], - "TagSpecifications": [ - { - "ResourceType": "instance", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRenderingPreview/mobile-preview-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - { - "ResourceType": "volume", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRenderingPreview/mobile-preview-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - ], - "UserData": { - "Fn::Base64": { - "Fn::Join": [ - "", - [ - "#!/bin/bash -set -ev -groupadd mapi -useradd -r -m -s /usr/bin/nologin -g mapi mobile-apps-rendering -export App=mobile-apps-rendering -export Stack=mobile-preview -export Stage=TEST -export NODE_ENV=production -aws s3 cp s3://", - { - "Ref": "SsmParameterValueaccountservicesartifactbucketC96584B6F00A464EAD1953AFF4B05118Parameter", - }, - "/mobile-preview/TEST/mobile-apps-rendering/mobile-apps-rendering.zip /tmp -mkdir -p /opt/mobile-apps-rendering -unzip /tmp/mobile-apps-rendering.zip -d /opt/mobile-apps-rendering -chown -R mobile-apps-rendering:mapi /opt/mobile-apps-rendering -mkdir -p /usr/share/mobile-apps-rendering/logs -chown -R mobile-apps-rendering:mapi /usr/share/mobile-apps-rendering -ln -s /usr/share/mobile-apps-rendering/logs /var/log/mobile-apps-rendering -chown -R mobile-apps-rendering:mapi /var/log/mobile-apps-rendering -export PM2_HOME="/usr/share/mobile-apps-rendering" -export ASSETS_MANIFEST="/opt/mobile-apps-rendering/manifest.json" -/usr/local/node/pm2 start --name mobile-apps-rendering --uid mobile-apps-rendering --gid mapi /opt/mobile-apps-rendering/server.js -/opt/aws-kinesis-agent/configure-aws-kinesis-agent ", - { - "Ref": "AWS::Region", - }, - " mobile-log-aggregation-TEST '/var/log/mobile-apps-rendering/*' -/usr/local/node/pm2 logrotate -u mobile-apps-rendering", - ], - ], - }, - }, - }, - "TagSpecifications": [ - { - "ResourceType": "launch-template", - "Tags": [ - { - "Key": "App", - "Value": "mobile-apps-rendering", - }, - { - "Key": "gu:cdk:version", - "Value": "TEST", - }, - { - "Key": "gu:repo", - "Value": "guardian/dotcom-rendering", - }, - { - "Key": "Name", - "Value": "MobileAppsRenderingPreview/mobile-preview-TEST-mobile-apps-rendering", - }, - { - "Key": "Stack", - "Value": "mobile-preview", - }, - { - "Key": "Stage", - "Value": "TEST", - }, - ], - }, - ], - }, - "Type": "AWS::EC2::LaunchTemplate", - }, - "mobilepreviewTESTmobileappsrenderingProfile72DADF5F": { - "Properties": { - "Roles": [ - { - "Ref": "InstanceRoleMobileappsrenderingEC64402A", - }, - ], - }, - "Type": "AWS::IAM::InstanceProfile", - }, - }, -} -`; diff --git a/apps-rendering/cdk/lib/mobile-apps-rendering.test.ts b/apps-rendering/cdk/lib/mobile-apps-rendering.test.ts deleted file mode 100644 index a8695796379..00000000000 --- a/apps-rendering/cdk/lib/mobile-apps-rendering.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { App } from 'aws-cdk-lib'; -import { Template } from 'aws-cdk-lib/assertions'; -import { InstanceSize } from 'aws-cdk-lib/aws-ec2'; -import { MobileAppsRendering } from './mobile-apps-rendering'; - -describe('The MobileAppsRendering stack', () => { - it('matches the snapshot', () => { - const app = new App(); - const stack = new MobileAppsRendering(app, 'MobileAppsRendering', { - stack: 'mobile', - stage: 'TEST', - recordPrefix: 'mobile-rendering', - asgCapacity: { - minimumInstances: 1, - maximumInstances: 2, - }, - instanceSize: InstanceSize.SMALL, - appsRenderingDomain: 'mobile-aws.code.dev-guardianapis.com', - hostedZoneId: 'TEST-HOSTED-ZONE-ID', - targetCpuUtilisation: 10, - }); - const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); - }); -}); - -describe('The MobileAppsRenderingPreview stack', () => { - it('matches the snapshot', () => { - const app = new App(); - const stack = new MobileAppsRendering( - app, - 'MobileAppsRenderingPreview', - { - stack: 'mobile-preview', - stage: 'TEST', - recordPrefix: 'mobile-preview-rendering', - asgCapacity: { - minimumInstances: 1, - maximumInstances: 2, - }, - instanceSize: InstanceSize.MICRO, - appsRenderingDomain: 'mobile-aws.code.dev-guardianapis.com', - hostedZoneId: 'TEST-HOSTED-ZONE-ID', - targetCpuUtilisation: 10, - }, - ); - const template = Template.fromStack(stack); - expect(template.toJSON()).toMatchSnapshot(); - }); -}); diff --git a/apps-rendering/cdk/lib/mobile-apps-rendering.ts b/apps-rendering/cdk/lib/mobile-apps-rendering.ts deleted file mode 100644 index c12c301ca85..00000000000 --- a/apps-rendering/cdk/lib/mobile-apps-rendering.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { GuEc2App } from '@guardian/cdk'; -import { AccessScope } from '@guardian/cdk/lib/constants'; -import type { GuStackProps } from '@guardian/cdk/lib/constructs/core'; -import { GuStack } from '@guardian/cdk/lib/constructs/core'; -import { GuAllowPolicy } from '@guardian/cdk/lib/constructs/iam'; -import type { GuAsgCapacity } from '@guardian/cdk/lib/types'; -import type { App, CfnElement } from 'aws-cdk-lib'; -import { Duration } from 'aws-cdk-lib'; -import type { InstanceSize } from 'aws-cdk-lib/aws-ec2'; -import { - InstanceClass, - InstanceType, - Peer, - UserData, -} from 'aws-cdk-lib/aws-ec2'; -import { - HostedZone, - RecordSet, - RecordTarget, - RecordType, -} from 'aws-cdk-lib/aws-route53'; -import * as ssm from 'aws-cdk-lib/aws-ssm'; - -interface AppsStackProps extends GuStackProps { - recordPrefix: string; - asgCapacity: GuAsgCapacity; - appsRenderingDomain: string; - hostedZoneId: string; - targetCpuUtilisation: number; - instanceSize: InstanceSize; -} - -export class MobileAppsRendering extends GuStack { - constructor(scope: App, id: string, props: AppsStackProps) { - super(scope, id, props); - - const appName = 'mobile-apps-rendering'; - const domainName = `${props.recordPrefix}.${props.appsRenderingDomain}`; - const hostedZone = HostedZone.fromHostedZoneAttributes( - this, - 'HostedZone', - { - zoneName: props.appsRenderingDomain, - hostedZoneId: props.hostedZoneId, - }, - ); - - const scalingTargetCpuUtilisation = props.targetCpuUtilisation; - const artifactBucketName = ssm.StringParameter.valueForStringParameter( - this, - '/account/services/artifact.bucket', - ); - - const userData = UserData.forLinux(); - userData.addCommands( - `set -ev`, - `groupadd mapi`, - `useradd -r -m -s /usr/bin/nologin -g mapi ${appName}`, - - `export App=${appName}`, - `export Stack=${this.stack}`, - `export Stage=${this.stage}`, - `export NODE_ENV=production`, - - `aws s3 cp s3://${artifactBucketName}/${this.stack}/${this.stage}/${appName}/${appName}.zip /tmp`, - `mkdir -p /opt/${appName}`, - `unzip /tmp/${appName}.zip -d /opt/${appName}`, - `chown -R ${appName}:mapi /opt/${appName}`, - - `mkdir -p /usr/share/${appName}/logs`, - `chown -R ${appName}:mapi /usr/share/${appName}`, - `ln -s /usr/share/${appName}/logs /var/log/${appName}`, - `chown -R ${appName}:mapi /var/log/${appName}`, - - `export PM2_HOME="/usr/share/${appName}"`, - `export ASSETS_MANIFEST="/opt/${appName}/manifest.json"`, - - `/usr/local/node/pm2 start --name ${appName} --uid ${appName} --gid mapi /opt/${appName}/server.js`, - `/opt/aws-kinesis-agent/configure-aws-kinesis-agent ${this.region} mobile-log-aggregation-${this.stage} '/var/log/${appName}/*'`, - `/usr/local/node/pm2 logrotate -u ${appName}`, - ); - - const appsRenderingApp = new GuEc2App(this, { - applicationPort: 3040, - app: 'mobile-apps-rendering', - access: { - scope: AccessScope.INTERNAL, - cidrRanges: [Peer.ipv4('10.0.0.0/8')], - }, - instanceType: InstanceType.of( - InstanceClass.T4G, - props.instanceSize, - ), - instanceMetricGranularity: '5Minute', - withAccessLogging: false, - certificateProps: { - domainName, - hostedZoneId: props.hostedZoneId, - }, - monitoringConfiguration: { - noMonitoring: true, - }, - roleConfiguration: { - additionalPolicies: [ - new GuAllowPolicy(this, 'GetParametersByPath', { - resources: ['*'], - actions: ['ssm:GetParametersByPath'], - }), - ], - }, - userData, - scaling: props.asgCapacity, - }); - - /** - * The default Node server keep alive timeout is 5 seconds - * @see https://nodejs.org/api/http.html#serverkeepalivetimeout - * - * This ensures that the load balancer idle timeout is less than the Node server keep alive - * timeout so that the Node app does not prematurely close the connection before the load - * balancer can accept the response. - * @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.html#connection-idle-timeout - */ - appsRenderingApp.loadBalancer.setAttribute( - 'idle_timeout.timeout_seconds', - '4', - ); - - const asg = appsRenderingApp.autoScalingGroup; - asg.scaleOnCpuUtilization('CpuScalingPolicy', { - targetUtilizationPercent: scalingTargetCpuUtilisation, - }); - - const recordSet = new RecordSet(this, 'DnsRecord', { - recordType: RecordType.CNAME, - target: RecordTarget.fromValues( - appsRenderingApp.loadBalancer.loadBalancerDnsName, - ), - zone: hostedZone, - recordName: props.recordPrefix, - ttl: Duration.hours(1), - }); - - const defaultChild = recordSet.node.defaultChild as CfnElement; - defaultChild.overrideLogicalId('DnsRecord'); - } -} diff --git a/apps-rendering/config/jestSetup.js b/apps-rendering/config/jestSetup.js index 7379e7fd813..b6500c58e54 100644 --- a/apps-rendering/config/jestSetup.js +++ b/apps-rendering/config/jestSetup.js @@ -1,5 +1,3 @@ -jest.mock('@guardian/cdk/lib/constants/tracking-tag'); - /** * Some tests use a JSDOM Jest environment. It appears that TextEncoder is not * available globally, and so we need to enable it here. diff --git a/apps-rendering/config/tsconfig.cdk.json b/apps-rendering/config/tsconfig.cdk.json deleted file mode 100644 index 88873a13c46..00000000000 --- a/apps-rendering/config/tsconfig.cdk.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "module": "ES2020", - "moduleResolution": "node", - "lib": ["ES2020"], - "declaration": true, - "strict": true, - "noImplicitAny": true, - "strictNullChecks": true, - "esModuleInterop": true, - "noImplicitThis": true, - "alwaysStrict": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": false, - "inlineSourceMap": true, - "inlineSources": true, - "experimentalDecorators": true, - "strictPropertyInitialization": false, - "outDir": "dist", - "skipLibCheck": true - }, - "include": ["../cdk/lib/*", "../cdk/bin/*"], - "exclude": ["../cdk/lib/*.test.ts", "../cdk/lib/__snapshots__/**"] -} diff --git a/apps-rendering/package.json b/apps-rendering/package.json index 91119eb6faa..041659cc041 100644 --- a/apps-rendering/package.json +++ b/apps-rendering/package.json @@ -17,15 +17,11 @@ "lint:fix": "eslint -c config/.eslintrc.js ./ --ext '.ts,.tsx' --fix --cache", "watch:server": "NODE_OPTIONS='--import tsx' webpack --config webpack.config.ts --config-name server --env watch", "watch:client": "NODE_OPTIONS='--import tsx' webpack serve --config webpack.config.ts --config-name client", - "watch:cdk": "tsc -w -p config/tsconfig.cdk.json", "watch": "pnpm '/^watch:(client|server)$/'", "build:server": "NODE_OPTIONS='--import tsx' webpack --config webpack.config.ts --config-name server", "build:client": "NODE_OPTIONS='--import tsx' webpack --config webpack.config.ts --config-name client", - "build:cdk": "tsc -p config/tsconfig.cdk.json", "build:server:prod": "NODE_OPTIONS='--import tsx' webpack --config webpack.config.ts --config-name server --env production", "build:client:prod": "NODE_OPTIONS='--import tsx' webpack --config webpack.config.ts --config-name clientProduction", - "synth": "cdk synth --path-metadata false --version-reporting false", - "diff": "cdk diff --path-metadata false --version-reporting false", "storybook": "storybook dev -p 4003", "build-storybook": "storybook build" }, @@ -43,7 +39,6 @@ "@emotion/server": "11.11.0", "@guardian/apps-rendering-api-models": "13.0.1", "@guardian/bridget": "7.0.0", - "@guardian/cdk": "62.0.1", "@guardian/content-api-models": "31.0.0", "@guardian/content-atom-model": "6.1.0", "@guardian/eslint-config-typescript": "12.0.0", @@ -66,8 +61,6 @@ "@types/react-dom": "18.3.0", "@types/react-test-renderer": "18.3.0", "@types/thrift": "0.10.17", - "aws-cdk": "2.1030.0", - "aws-cdk-lib": "2.220.0", "babel-loader": "10.0.0", "buffer": "6.0.3", "clean-css": "5.3.3", diff --git a/apps-rendering/riff-raff.yaml b/apps-rendering/riff-raff.yaml deleted file mode 100644 index c3b8877ef2d..00000000000 --- a/apps-rendering/riff-raff.yaml +++ /dev/null @@ -1,47 +0,0 @@ -stacks: [mobile, mobile-preview] -regions: [eu-west-1] -allowedStages: - - CODE - - PROD -templates: - cloudformation: - type: cloud-formation - app: mobile-apps-rendering - parameters: - amiParameter: AMIMobileappsrendering - amiEncrypted: true - amiTags: - # Keep the Node version in sync with `.nvmrc` - Recipe: apps-rendering-ARM-jammy-node-22.18.0 - AmigoStage: PROD -deployments: - mobile-apps-rendering-cfn: - template: cloudformation - stacks: - - mobile - parameters: - templateStagePaths: - CODE: MobileAppsRendering-CODE.template.json - PROD: MobileAppsRendering-PROD.template.json - mobile-apps-rendering-preview-cfn: - template: cloudformation - stacks: - - mobile-preview - parameters: - templateStagePaths: - CODE: MobileAppsRenderingPreview-CODE.template.json - PROD: MobileAppsRenderingPreview-PROD.template.json - mobile-apps-rendering: - type: autoscaling - parameters: - bucketSsmLookup: true - dependencies: - [mobile-apps-rendering-cfn, mobile-apps-rendering-preview-cfn] - mobile-assets: - type: aws-s3 - parameters: - bucketSsmLookup: true - bucketSsmKey: /account/services/apps-rendering-static.bucket - cacheControl: public, max-age=315360000 - prefixStack: false - publicReadAcl: false diff --git a/dotcom-rendering/scripts/check-node-versions.mjs b/dotcom-rendering/scripts/check-node-versions.mjs index e1f579fc60b..dafea9071f0 100644 --- a/dotcom-rendering/scripts/check-node-versions.mjs +++ b/dotcom-rendering/scripts/check-node-versions.mjs @@ -44,11 +44,6 @@ const requiredNodeVersionMatches = pattern: /^ +Recipe: dotcom-rendering.*-node-(\d+\.\d+\.\d+).*?$/m, matchLevel: 'patch', }, - { - filepath: '../apps-rendering/riff-raff.yaml', - pattern: /^ +Recipe: apps-rendering.*-node-(\d+\.\d+\.\d+).*?$/m, - matchLevel: 'patch', - }, { filepath: 'package.json', pattern: /^\t+"@types\/node"\: "(.+)",$/m, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 64eb84ea2d6..9df46affc57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -143,9 +143,6 @@ importers: '@guardian/bridget': specifier: 7.0.0 version: 7.0.0 - '@guardian/cdk': - specifier: 62.0.1 - version: 62.0.1(aws-cdk-lib@2.220.0(constructs@10.4.2))(aws-cdk@2.1030.0)(constructs@10.4.2) '@guardian/content-api-models': specifier: 31.0.0 version: 31.0.0 @@ -212,12 +209,6 @@ importers: '@types/thrift': specifier: 0.10.17 version: 0.10.17 - aws-cdk: - specifier: 2.1030.0 - version: 2.1030.0 - aws-cdk-lib: - specifier: 2.220.0 - version: 2.220.0(constructs@10.4.2) babel-loader: specifier: 10.0.0 version: 10.0.0(@babel/core@7.28.4)(webpack@5.102.1) @@ -307,7 +298,7 @@ importers: version: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) webpack-cli: specifier: 6.0.1 - version: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + version: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) webpack-dev-server: specifier: 5.2.2 version: 5.2.2(webpack-cli@6.0.1)(webpack@5.102.1) @@ -12005,7 +11996,7 @@ snapshots: '@babel/types': 7.28.4 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -12057,7 +12048,7 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.10 transitivePeerDependencies: @@ -12781,7 +12772,7 @@ snapshots: '@babel/parser': 7.28.4 '@babel/template': 7.27.2 '@babel/types': 7.28.4 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -13101,7 +13092,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.2 @@ -13249,13 +13240,13 @@ snapshots: '@guardian/eslint-config-typescript@12.0.0(eslint@8.57.1)(tslib@2.6.2)(typescript@5.5.3)': dependencies: - '@guardian/eslint-config': 9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)(tslib@2.6.2) + '@guardian/eslint-config': 9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)(tslib@2.6.2) '@stylistic/eslint-plugin': 2.6.2(eslint@8.57.1)(typescript@5.5.3) '@typescript-eslint/eslint-plugin': 8.1.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1)(typescript@5.5.3) '@typescript-eslint/parser': 8.1.0(eslint@8.57.1)(typescript@5.5.3) eslint: 8.57.1 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.1) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) tslib: 2.6.2 typescript: 5.5.3 transitivePeerDependencies: @@ -13284,12 +13275,12 @@ snapshots: - supports-color - typescript - '@guardian/eslint-config@9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1)(tslib@2.6.2)': + '@guardian/eslint-config@9.0.0(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1)(tslib@2.6.2)': dependencies: eslint: 8.57.1 eslint-config-prettier: 9.1.0(eslint@8.57.1) eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) tslib: 2.6.2 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -13447,7 +13438,7 @@ snapshots: '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -14745,7 +14736,7 @@ snapshots: '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.5.3)(webpack@5.102.1)': dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 endent: 2.1.0 find-cache-dir: 3.3.2 flat-cache: 3.2.0 @@ -15629,7 +15620,7 @@ snapshots: '@typescript-eslint/types': 8.1.0 '@typescript-eslint/typescript-estree': 8.1.0(typescript@5.5.3) '@typescript-eslint/visitor-keys': 8.1.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 eslint: 8.57.1 optionalDependencies: typescript: 5.5.3 @@ -15664,7 +15655,7 @@ snapshots: dependencies: '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.5.3) '@typescript-eslint/types': 8.46.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -15710,7 +15701,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 8.1.0(typescript@5.5.3) '@typescript-eslint/utils': 8.1.0(eslint@8.57.1)(typescript@5.5.3) - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: typescript: 5.5.3 @@ -15755,7 +15746,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.1.0 '@typescript-eslint/visitor-keys': 8.1.0 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -15800,7 +15791,7 @@ snapshots: '@typescript-eslint/tsconfig-utils': 8.46.2(typescript@5.5.3) '@typescript-eslint/types': 8.46.2 '@typescript-eslint/visitor-keys': 8.46.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -16018,17 +16009,17 @@ snapshots: '@webpack-cli/configtest@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: webpack: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + webpack-cli: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) '@webpack-cli/info@3.0.1(webpack-cli@6.0.1)(webpack@5.102.1)': dependencies: webpack: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + webpack-cli: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) '@webpack-cli/serve@3.0.1(webpack-cli@6.0.1)(webpack-dev-server@5.2.2)(webpack@5.102.1)': dependencies: webpack: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + webpack-cli: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) optionalDependencies: webpack-dev-server: 5.2.2(webpack-cli@6.0.1)(webpack@5.102.1) @@ -16158,7 +16149,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -16536,7 +16527,7 @@ snapshots: dependencies: bytes: 3.1.2 content-type: 1.0.5 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 http-errors: 2.0.0 iconv-lite: 0.6.3 on-finished: 2.4.1 @@ -17143,6 +17134,10 @@ snapshots: dependencies: ms: 2.1.3 + debug@4.4.3: + dependencies: + ms: 2.1.3 + debug@4.4.3(supports-color@8.1.1): dependencies: ms: 2.1.3 @@ -17488,7 +17483,7 @@ snapshots: esbuild-register@3.6.0(esbuild@0.25.5): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 esbuild: 0.25.5 transitivePeerDependencies: - supports-color @@ -17582,9 +17577,26 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1): + dependencies: + debug: 4.4.3 + enhanced-resolve: 5.18.3 + eslint: 8.57.1 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + fast-glob: 3.3.3 + get-tsconfig: 4.7.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1)(eslint@8.57.1): dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 enhanced-resolve: 5.18.3 eslint: 8.57.1 eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1) @@ -17598,6 +17610,7 @@ snapshots: - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color + optional: true eslint-import-resolver-typescript@3.7.0(eslint-plugin-import-x@4.6.1(eslint@9.39.1)(typescript@5.9.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.22.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1))(eslint@9.39.1): dependencies: @@ -17616,6 +17629,17 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 8.1.0(eslint@8.57.1)(typescript@5.5.3) + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1) + transitivePeerDependencies: + - supports-color + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1): dependencies: debug: 3.2.7 @@ -17668,6 +17692,33 @@ snapshots: - supports-color - typescript + eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + dependencies: + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.1.0(eslint@8.57.1)(typescript@5.5.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-import@2.29.1(@typescript-eslint/parser@8.1.0(eslint@8.57.1)(typescript@5.5.3))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.1): dependencies: array-includes: 3.1.9 @@ -17916,7 +17967,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -18256,7 +18307,7 @@ snapshots: finalhandler@2.1.0: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 on-finished: 2.4.1 @@ -18804,7 +18855,7 @@ snapshots: dependencies: '@tootallnate/once': 1.1.2 agent-base: 6.0.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -18812,7 +18863,7 @@ snapshots: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -18844,7 +18895,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -19167,7 +19218,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -21047,7 +21098,7 @@ snapshots: router@2.2.0: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 depd: 2.0.0 is-promise: 4.0.0 parseurl: 1.3.3 @@ -21181,7 +21232,7 @@ snapshots: send@1.2.0: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 encodeurl: 2.0.0 escape-html: 1.0.3 etag: 1.8.1 @@ -21396,7 +21447,7 @@ snapshots: spdy-transport@3.0.0: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -21407,7 +21458,7 @@ snapshots: spdy@4.0.2: dependencies: - debug: 4.4.3(supports-color@8.1.1) + debug: 4.4.3 handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -22428,6 +22479,25 @@ snapshots: webpack-bundle-analyzer: 4.10.2 webpack-dev-server: 5.2.2(webpack-cli@6.0.1)(webpack@5.102.1) + webpack-cli@6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1): + dependencies: + '@discoveryjs/json-ext': 0.6.3 + '@webpack-cli/configtest': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/info': 3.0.1(webpack-cli@6.0.1)(webpack@5.102.1) + '@webpack-cli/serve': 3.0.1(webpack-cli@6.0.1)(webpack-dev-server@5.2.2)(webpack@5.102.1) + colorette: 2.0.20 + commander: 12.1.0 + cross-spawn: 7.0.6 + envinfo: 7.14.0 + fastest-levenshtein: 1.0.16 + import-local: 3.2.0 + interpret: 3.1.1 + rechoir: 0.8.0 + webpack: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) + webpack-merge: 6.0.1 + optionalDependencies: + webpack-dev-server: 5.2.2(webpack-cli@6.0.1)(webpack@5.102.1) + webpack-dev-middleware@6.1.3(webpack@5.102.1): dependencies: colorette: 2.0.20 @@ -22492,7 +22562,7 @@ snapshots: ws: 8.18.3 optionalDependencies: webpack: 5.102.1(@swc/core@1.13.5)(esbuild@0.25.5)(webpack-cli@6.0.1) - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + webpack-cli: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) transitivePeerDependencies: - bufferutil - debug @@ -22575,7 +22645,7 @@ snapshots: watchpack: 2.4.4 webpack-sources: 3.3.3 optionalDependencies: - webpack-cli: 6.0.1(webpack-bundle-analyzer@4.10.2)(webpack-dev-server@5.2.2)(webpack@5.102.1) + webpack-cli: 6.0.1(webpack-dev-server@5.2.2)(webpack@5.102.1) transitivePeerDependencies: - '@swc/core' - esbuild