From 86b4859589239573ee3b2db9f71b56ea13482774 Mon Sep 17 00:00:00 2001 From: Adam Moussa <166072409+amoussa1229@users.noreply.github.com> Date: Mon, 29 Jun 2026 00:51:16 -0400 Subject: [PATCH] fix: env-scope the EC2 launch template name (unblocks prod deploy) (#51) requireImdsv2:true makes CDK auto-create a launch template named from the construct id ('Instance' -> 'InstanceLaunchTemplate') with no env qualifier, so OpenSweDevStack and OpenSweProdStack both render LaunchTemplateName: InstanceLaunchTemplate. dev created it first (the live dev box runs on it); the prod first-deploy then failed with InvalidLaunchTemplateName.AlreadyExistsException and the whole stack rolled back. Force a per-env LT name (open-swe--lt) via an aspect (the LT is created at synth time by the requireImdsv2 handling, not in the constructor), and rename the instance's launch-template REFERENCE in lockstep so CFN still resolves it. synth-verified: dev=open-swe-dev-lt, prod=open-swe-prod-lt on both the LT resource and the instance reference; version GetAtt preserved. NOTE: deploying this renames dev's LT -> one-time dev box replacement (stateless; boots from the baked AMI + pulls releases/latest). prod then creates open-swe-prod-lt cleanly. --- infra/lib/constructs/app-service.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/infra/lib/constructs/app-service.ts b/infra/lib/constructs/app-service.ts index fd724dbe..48607575 100644 --- a/infra/lib/constructs/app-service.ts +++ b/infra/lib/constructs/app-service.ts @@ -8,7 +8,7 @@ import * as logs from "aws-cdk-lib/aws-logs"; import * as route53 from "aws-cdk-lib/aws-route53"; import * as iam from "aws-cdk-lib/aws-iam"; import * as ssm from "aws-cdk-lib/aws-ssm"; -import { Construct } from "constructs"; +import { Construct, IConstruct } from "constructs"; import { EnvName, prefix } from "../config"; import { bakedOpenSweArm64 } from "./ami-cache"; @@ -230,6 +230,27 @@ export class AppService extends Construct { ], }); + // `requireImdsv2: true` makes CDK auto-create a launch template, and it names + // that LT from the construct id ("Instance" -> "InstanceLaunchTemplate") with NO + // env qualifier — so OpenSweDevStack and OpenSweProdStack both want the identical + // LT name and the second env to deploy fails with + // InvalidLaunchTemplateName.AlreadyExistsException (prod rollback, 2026-06-29). + // Force a per-env LT name. Done via an aspect because the LT is created at synth + // time by the requireImdsv2 handling, not in this constructor. + cdk.Aspects.of(this.instance).add({ + visit(node: IConstruct) { + if (node instanceof ec2.CfnLaunchTemplate) { + node.launchTemplateName = `${p}-lt`; + } + // The instance references the LT BY NAME, so the reference must be renamed in + // lockstep (preserve the GetAtt version) or CFN can't find the template. + if (node instanceof ec2.CfnInstance && node.launchTemplate) { + const spec = node.launchTemplate as ec2.CfnInstance.LaunchTemplateSpecificationProperty; + node.launchTemplate = { ...spec, launchTemplateName: `${p}-lt` }; + } + }, + }); + // SSM deploy document (open-swe--deploy): runs the baked // /opt/open-swe/bin/deploy.sh to pull the latest release + restart. CI fires it // (tag-scoped to project=open-swe,env=) after uploading a release, so the