From 343279451b452c25a82f60eb95549676b955d0ff Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Tue, 10 Nov 2026 04:32:35 +0000 Subject: [PATCH 1/3] [Changed] CloudFormation mappings grouped by concern (placeholder changelog, #435) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68a6d157..bd9d5dac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,6 +95,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release - Moved startup configuration and endpoint wiring from the BuildBot host into testable feature libraries - #429 - Bring README in line with the readme documentation rule (required section order, reference-style links) - #432 - SDK - Updated DotNet SDK to 11.0.100-rc.3.26522.148 +- CloudFormation template Mappings are grouped by concern under Mappings.Deployment (Network, Task, Service, Settings, LoadBalancer, ApiGateway, Dns) to match funfair-treasury-reporting; resolved values are unchanged (#435) ### Deprecated ### Removed - Removed NuGet audit suppressions for Scriban 6.2.0 vulnerabilities now that the transitive dependency has been dropped From e93847e04934cdf2eee1d984724e3da37a66c6e1 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Tue, 10 Nov 2026 05:50:00 +0000 Subject: [PATCH 2/3] refactor(cloudformation): group template Mappings under Deployment (#435) Groups the CloudFormation template Mappings by concern under a single Deployment mapping (Network, Task, Service, Settings, LoadBalancer, ApiGateway, Dns), and uses the security group and subnet lists directly. Resolved values are unchanged, and README.md is updated to describe the new layout. --- README.md | 15 +++ cloudformation.json | 238 ++++++++++++++++++++++---------------------- 2 files changed, 136 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 8ba2a5be..2379ceb2 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,20 @@ Example requests for the health check, GitHub and CloudFormation routes are in [ BuildBot runs behind the internal load balancer. Webhooks (GitHub, Watchtower and CloudFormation SNS notifications) arrive through an API Gateway HTTP API, which forwards them over a VPC Link to the internal load balancer. The CloudFormation stack owns the API Gateway custom domain and the Route 53 `A` alias record for the API host name. +### Template settings + +Fixed deployment values live in the [`cloudformation.json`][cloudformation-template] `Deployment` mapping, grouped by area, and are read with `Fn::FindInMap` as `["Deployment", "", ""]`. `SecurityGroupIds` and `SubnetIds` are string lists, so they are used directly without `Fn::Split`. + +| Group | Keys | +|----------------|------------------------------------------------------------------------------------------| +| `Network` | `ClusterName`, `SecurityGroupIds`, `SubnetIds`, `VpcId`, `VpcLinkEgressCidr` | +| `Task` | `Cpu`, `Memory`, `ExecutionRole`, `ContainerOwner`, `SecretsManagerArn`, `ContainerPort` | +| `Service` | `DesiredCount`, `MinimumHealthPercent`, `MaximumHealthPercent` | +| `Settings` | `LogRetentionInDays` | +| `LoadBalancer` | `ListenerArn`, `InternalAlbServerName` | +| `ApiGateway` | `CertificateArn`, `ThrottlingBurstLimit`, `ThrottlingRateLimit` | +| `Dns` | `HostedZoneName` | + ### Request handling through API Gateway - Only these routes are exposed: `GET /ping`, `POST /github/ping`, `POST /github/push`, `POST /github/status`, `POST /watchtower/deploy` and `POST /cloudformation/deploy`. Any other route gets API Gateway's own 404 and never reaches BuildBot. @@ -111,6 +125,7 @@ View the [changelog][changelog]. BuildBot is released under the MIT licence; see [LICENSE][licence]. [changelog]: CHANGELOG.md +[cloudformation-template]: cloudformation.json [discord-webhook-http]: src/BuildBot/DiscordWebhook.http [dockerfile]: Dockerfile [licence]: LICENSE diff --git a/cloudformation.json b/cloudformation.json index 59b8821a..9182c41d 100644 --- a/cloudformation.json +++ b/cloudformation.json @@ -26,29 +26,48 @@ } }, "Mappings": { - "Settings": { - "Values": { - "TaskDefinitionCPU": "512", - "TaskDefinitionMemory": "1024", + "Deployment": { + "Network": { + "ClusterName": "DiscordBots", + "SecurityGroupIds": [ + "sg-e3e65a9a", + "sg-0272027302777cb4d" + ], + "SubnetIds": [ + "subnet-fabb50b3", + "subnet-d5ea03b2", + "subnet-c68aa09e" + ], + "VpcId": "vpc-ad3bd9ca", + "VpcLinkEgressCidr": "172.31.0.0/16" + }, + "Task": { + "Cpu": "512", + "Memory": "1024", + "ExecutionRole": "arn:aws:iam::117769150821:role/ecsTaskExecutionRole", + "ContainerOwner": "funfair", + "SecretsManagerArn": "arn:aws:secretsmanager:eu-west-1:117769150821:secret:BuildBot-ph1YIJ", + "ContainerPort": "8080" + }, + "Service": { "DesiredCount": "1", "MinimumHealthPercent": "100", - "MaximumHealthPercent": "200", - "SecretsManagerArn": "arn:aws:secretsmanager:eu-west-1:117769150821:secret:BuildBot-ph1YIJ", - "ContainerPort": "8080", - "ECSClusterName": "DiscordBots", - "ApplicationContainerOwner": "funfair", - "TaskExecutionRoleArn": "arn:aws:iam::117769150821:role/ecsTaskExecutionRole", - "SecurityGroupIDs": "sg-e3e65a9a,sg-0272027302777cb4d", - "SubnetIDs": "subnet-fabb50b3,subnet-d5ea03b2,subnet-c68aa09e", - "VpcID": "vpc-ad3bd9ca", - "LoadBalancerListenerArn": "arn:aws:elasticloadbalancing:eu-west-1:117769150821:listener/app/internal/fbd77c1a39a60f7f/e01c11e315c3ff6e", - "HostedZoneName": "funfair.io.", - "ApiCertificateArn": "arn:aws:acm:eu-west-1:117769150821:certificate/d9405a08-95c9-4924-acde-d86cda5f29e8", - "VpcLinkEgressCidr": "172.31.0.0/16", - "InternalAlbServerName": "buildbot.funfair.io", - "ApiThrottlingBurstLimit": "20", - "ApiThrottlingRateLimit": "10", + "MaximumHealthPercent": "200" + }, + "Settings": { "LogRetentionInDays": "30" + }, + "LoadBalancer": { + "ListenerArn": "arn:aws:elasticloadbalancing:eu-west-1:117769150821:listener/app/internal/fbd77c1a39a60f7f/e01c11e315c3ff6e", + "InternalAlbServerName": "buildbot.funfair.io" + }, + "ApiGateway": { + "CertificateArn": "arn:aws:acm:eu-west-1:117769150821:certificate/d9405a08-95c9-4924-acde-d86cda5f29e8", + "ThrottlingBurstLimit": "20", + "ThrottlingRateLimit": "10" + }, + "Dns": { + "HostedZoneName": "funfair.io." } } }, @@ -73,9 +92,9 @@ { "Owner": { "Fn::FindInMap": [ - "Settings", - "Values", - "ApplicationContainerOwner" + "Deployment", + "Task", + "ContainerOwner" ] } } @@ -101,8 +120,8 @@ { "SecretsManagerArn": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "SecretsManagerArn" ] } @@ -118,8 +137,8 @@ { "SecretsManagerArn": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "SecretsManagerArn" ] } @@ -135,8 +154,8 @@ { "SecretsManagerArn": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "SecretsManagerArn" ] } @@ -152,8 +171,8 @@ { "SecretsManagerArn": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "SecretsManagerArn" ] } @@ -169,8 +188,8 @@ { "SecretsManagerArn": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "SecretsManagerArn" ] } @@ -195,15 +214,15 @@ { "ContainerPort": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "ContainerPort" ] }, "HostPort": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "ContainerPort" ] }, @@ -231,23 +250,23 @@ }, "Cpu": { "Fn::FindInMap": [ - "Settings", - "Values", - "TaskDefinitionCPU" + "Deployment", + "Task", + "Cpu" ] }, "Memory": { "Fn::FindInMap": [ - "Settings", - "Values", - "TaskDefinitionMemory" + "Deployment", + "Task", + "Memory" ] }, "ExecutionRoleArn": { "Fn::FindInMap": [ - "Settings", - "Values", - "TaskExecutionRoleArn" + "Deployment", + "Task", + "ExecutionRole" ] }, "RequiresCompatibilities": [ @@ -270,8 +289,8 @@ }, "RetentionInDays": { "Fn::FindInMap": [ + "Deployment", "Settings", - "Values", "LogRetentionInDays" ] } @@ -285,9 +304,9 @@ }, "Cluster": { "Fn::FindInMap": [ - "Settings", - "Values", - "ECSClusterName" + "Deployment", + "Network", + "ClusterName" ] }, "TaskDefinition": { @@ -295,8 +314,8 @@ }, "DesiredCount": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Service", "DesiredCount" ] }, @@ -306,27 +325,17 @@ "AwsvpcConfiguration": { "AssignPublicIp": "ENABLED", "SecurityGroups": { - "Fn::Split": [ - ",", - { - "Fn::FindInMap": [ - "Settings", - "Values", - "SecurityGroupIDs" - ] - } + "Fn::FindInMap": [ + "Deployment", + "Network", + "SecurityGroupIds" ] }, "Subnets": { - "Fn::Split": [ - ",", - { - "Fn::FindInMap": [ - "Settings", - "Values", - "SubnetIDs" - ] - } + "Fn::FindInMap": [ + "Deployment", + "Network", + "SubnetIds" ] } } @@ -334,15 +343,15 @@ "DeploymentConfiguration": { "MaximumPercent": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Service", "MaximumHealthPercent" ] }, "MinimumHealthyPercent": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Service", "MinimumHealthPercent" ] }, @@ -358,8 +367,8 @@ }, "ContainerPort": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "ContainerPort" ] }, @@ -379,8 +388,8 @@ "HealthCheckPath": "/ping?source=target-group", "Port": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "ContainerPort" ] }, @@ -390,8 +399,8 @@ "HealthCheckProtocol": "HTTP", "HealthCheckPort": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Task", "ContainerPort" ] }, @@ -400,9 +409,9 @@ "HealthCheckIntervalSeconds": 5, "VpcId": { "Fn::FindInMap": [ - "Settings", - "Values", - "VpcID" + "Deployment", + "Network", + "VpcId" ] }, "TargetGroupAttributes": [ @@ -446,9 +455,9 @@ ], "ListenerArn": { "Fn::FindInMap": [ - "Settings", - "Values", - "LoadBalancerListenerArn" + "Deployment", + "LoadBalancer", + "ListenerArn" ] }, "Priority": { @@ -464,9 +473,9 @@ }, "VpcId": { "Fn::FindInMap": [ - "Settings", - "Values", - "VpcID" + "Deployment", + "Network", + "VpcId" ] }, "SecurityGroupEgress": [ @@ -477,8 +486,8 @@ "ToPort": 443, "CidrIp": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Network", "VpcLinkEgressCidr" ] } @@ -493,15 +502,10 @@ "Ref": "ApplicationName" }, "SubnetIds": { - "Fn::Split": [ - ",", - { - "Fn::FindInMap": [ - "Settings", - "Values", - "SubnetIDs" - ] - } + "Fn::FindInMap": [ + "Deployment", + "Network", + "SubnetIds" ] }, "SecurityGroupIds": [ @@ -534,9 +538,9 @@ }, "IntegrationUri": { "Fn::FindInMap": [ - "Settings", - "Values", - "LoadBalancerListenerArn" + "Deployment", + "LoadBalancer", + "ListenerArn" ] }, "PayloadFormatVersion": "1.0", @@ -549,8 +553,8 @@ "TlsConfig": { "ServerNameToVerify": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "LoadBalancer", "InternalAlbServerName" ] } @@ -640,16 +644,16 @@ "DefaultRouteSettings": { "ThrottlingBurstLimit": { "Fn::FindInMap": [ - "Settings", - "Values", - "ApiThrottlingBurstLimit" + "Deployment", + "ApiGateway", + "ThrottlingBurstLimit" ] }, "ThrottlingRateLimit": { "Fn::FindInMap": [ - "Settings", - "Values", - "ApiThrottlingRateLimit" + "Deployment", + "ApiGateway", + "ThrottlingRateLimit" ] } }, @@ -674,8 +678,8 @@ }, "RetentionInDays": { "Fn::FindInMap": [ + "Deployment", "Settings", - "Values", "LogRetentionInDays" ] } @@ -691,9 +695,9 @@ { "CertificateArn": { "Fn::FindInMap": [ - "Settings", - "Values", - "ApiCertificateArn" + "Deployment", + "ApiGateway", + "CertificateArn" ] }, "EndpointType": "REGIONAL", @@ -723,8 +727,8 @@ "Properties": { "HostedZoneName": { "Fn::FindInMap": [ - "Settings", - "Values", + "Deployment", + "Dns", "HostedZoneName" ] }, From d07d4afcece592bb81cbaf582447d0ce11e0a8d5 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Tue, 10 Nov 2026 05:50:18 +0000 Subject: [PATCH 3/3] docs(changelog): describe CloudFormation Mappings grouping (#435) Updates the unreleased CloudFormation entry to describe the grouping of deployment settings under a single Deployment mapping. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9d5dac..6d4cb297 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -95,7 +95,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release - Moved startup configuration and endpoint wiring from the BuildBot host into testable feature libraries - #429 - Bring README in line with the readme documentation rule (required section order, reference-style links) - #432 - SDK - Updated DotNet SDK to 11.0.100-rc.3.26522.148 -- CloudFormation template Mappings are grouped by concern under Mappings.Deployment (Network, Task, Service, Settings, LoadBalancer, ApiGateway, Dns) to match funfair-treasury-reporting; resolved values are unchanged (#435) +- CloudFormation deployment settings are grouped by area under a single Deployment mapping (Network, Task, Service, Settings, LoadBalancer, ApiGateway, Dns), with the security group and subnet lists used directly, so each value is easier to find and change; deployed values are unchanged (#435) ### Deprecated ### Removed - Removed NuGet audit suppressions for Scriban 6.2.0 vulnerabilities now that the transitive dependency has been dropped