Skip to content

Commit 1e2d05c

Browse files
refactor(compute): gate ECS construct on compute_type context
Replace comment toggle with proper context gate. ECS resources only synthesize when compute_type=ecs is passed. Default (agentcore) behavior unchanged. Closes #164 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent f6e8b27 commit 1e2d05c

3 files changed

Lines changed: 36 additions & 41 deletions

File tree

cdk/src/bootstrap/preflight/.gitkeep

Lines changed: 0 additions & 1 deletion
This file was deleted.

cdk/src/stacks/agent.ts

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ import * as bedrock from '@aws-cdk/aws-bedrock-alpha';
2323
import * as agentcoremixins from '@aws-cdk/mixins-preview/aws-bedrockagentcore';
2424
import { ArnFormat, AspectPriority, Aspects, Stack, StackProps, RemovalPolicy, CfnOutput, CfnResource, Duration, Fn, Lazy } from 'aws-cdk-lib';
2525
import * as ec2 from 'aws-cdk-lib/aws-ec2';
26-
// ecr_assets import is only needed when the ECS block below is uncommented
27-
// import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
26+
import * as ecr_assets from 'aws-cdk-lib/aws-ecr-assets';
2827
import * as iam from 'aws-cdk-lib/aws-iam';
2928
import * as logs from 'aws-cdk-lib/aws-logs';
3029
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
@@ -40,7 +39,7 @@ import { Blueprint } from '../constructs/blueprint';
4039
import { CedarWasmLayer } from '../constructs/cedar-wasm-layer';
4140
import { ConcurrencyReconciler } from '../constructs/concurrency-reconciler';
4241
import { DnsFirewall } from '../constructs/dns-firewall';
43-
// import { EcsAgentCluster } from '../constructs/ecs-agent-cluster';
42+
import { EcsAgentCluster } from '../constructs/ecs-agent-cluster';
4443
import { FanOutConsumer } from '../constructs/fanout-consumer';
4544
import { LinearIntegration } from '../constructs/linear-integration';
4645
import { PendingUploadCleanup } from '../constructs/pending-upload-cleanup';
@@ -563,31 +562,27 @@ export class AgentStack extends Stack {
563562
description: 'Name of the S3 bucket storing --trace trajectory artifacts (design §10.1)',
564563
});
565564

566-
// --- ECS Fargate compute backend (optional) ---
567-
// To enable ECS as an alternative compute backend, uncomment the block below
568-
// and the EcsAgentCluster import at the top of this file. Repos can then use
569-
// compute_type: 'ecs' in their blueprint config to route tasks to ECS Fargate.
570-
//
571-
// const agentImageAsset = new ecr_assets.DockerImageAsset(this, 'AgentImage', {
572-
// directory: repoRoot,
573-
// file: 'agent/Dockerfile',
574-
// platform: ecr_assets.Platform.LINUX_ARM64,
575-
// });
576-
//
577-
// const ecsCluster = new EcsAgentCluster(this, 'EcsAgentCluster', {
578-
// vpc: agentVpc.vpc,
579-
// agentImageAsset,
580-
// taskTable: taskTable.table,
581-
// taskEventsTable: taskEventsTable.table,
582-
// userConcurrencyTable: userConcurrencyTable.table,
583-
// githubTokenSecret,
584-
// memoryId: agentMemory.memory.memoryId,
585-
// // Per-session IAM scoping (#209): the ECS task role assumes the same
586-
// // SessionRole as the AgentCore runtime for tenant-data access. The
587-
// // construct admits the task role to the trust and injects
588-
// // AGENT_SESSION_ROLE_ARN into the container.
589-
// agentSessionRole,
590-
// });
565+
// --- ECS Fargate compute backend (enabled when compute_type=ecs) ---
566+
const computeType = this.node.tryGetContext('compute_type') ?? 'agentcore';
567+
let ecsCluster: EcsAgentCluster | undefined;
568+
if (computeType === 'ecs') {
569+
const agentImageAsset = new ecr_assets.DockerImageAsset(this, 'AgentImage', {
570+
directory: repoRoot,
571+
file: 'agent/Dockerfile',
572+
platform: ecr_assets.Platform.LINUX_ARM64,
573+
});
574+
575+
ecsCluster = new EcsAgentCluster(this, 'EcsAgentCluster', {
576+
vpc: agentVpc.vpc,
577+
agentImageAsset,
578+
taskTable: taskTable.table,
579+
taskEventsTable: taskEventsTable.table,
580+
userConcurrencyTable: userConcurrencyTable.table,
581+
githubTokenSecret,
582+
memoryId: agentMemory.memory.memoryId,
583+
agentSessionRole,
584+
});
585+
}
591586

592587
// --- Task Orchestrator (durable Lambda function) ---
593588
const orchestrator = new TaskOrchestrator(this, 'TaskOrchestrator', {
@@ -601,16 +596,17 @@ export class AgentStack extends Stack {
601596
guardrailId: inputGuardrail.guardrailId,
602597
guardrailVersion: inputGuardrail.guardrailVersion,
603598
attachmentsBucket: attachmentsBucket.bucket,
604-
// To wire ECS, uncomment the ecsCluster block above and add:
605-
// ecsConfig: {
606-
// clusterArn: ecsCluster.cluster.clusterArn,
607-
// taskDefinitionArn: ecsCluster.taskDefinition.taskDefinitionArn,
608-
// subnets: agentVpc.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds.join(','),
609-
// securityGroup: ecsCluster.securityGroup.securityGroupId,
610-
// containerName: ecsCluster.containerName,
611-
// taskRoleArn: ecsCluster.taskRoleArn,
612-
// executionRoleArn: ecsCluster.executionRoleArn,
613-
// },
599+
...(ecsCluster && {
600+
ecsConfig: {
601+
clusterArn: ecsCluster.cluster.clusterArn,
602+
taskDefinitionArn: ecsCluster.taskDefinition.taskDefinitionArn,
603+
subnets: agentVpc.vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }).subnetIds.join(','),
604+
securityGroup: ecsCluster.securityGroup.securityGroupId,
605+
containerName: ecsCluster.containerName,
606+
taskRoleArn: ecsCluster.taskRoleArn,
607+
executionRoleArn: ecsCluster.executionRoleArn,
608+
},
609+
}),
614610
});
615611

616612
// Now that the orchestrator exists, resolve the Lazy used by TaskApi at synth.

cdk/test/stacks/github-tags.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,13 @@ describe('github:* resource tags', () => {
140140
});
141141

142142
test('compute_type tag reflects context value when provided', () => {
143-
const template = synthWithTags({ compute_type: 'ecs' });
143+
const template = synthWithTags({ compute_type: 'custom-compute' });
144144
const resources = template.findResources('AWS::DynamoDB::Table');
145145
const firstResource = Object.values(resources)[0];
146146
const tags: Array<{ Key: string; Value: string }> = firstResource?.Properties?.Tags ?? [];
147147

148148
const tag = tags.find(t => t.Key === 'compute_type');
149149
expect(tag).toBeDefined();
150-
expect(tag!.Value).toBe('ecs');
150+
expect(tag!.Value).toBe('custom-compute');
151151
});
152152
});

0 commit comments

Comments
 (0)