Skip to content

Commit 05c244e

Browse files
committed
feat(project): dispatch build on the project's managedBy backend
agentcore.json already records `managedBy` (CDK is the only value today), but nothing read it: build() hardcoded the CDK path, so adding a terraform or no-IaC backend later would have meant editing that path instead of adding alongside it. Carry managedBy on Project and switch on it in build(), delegating the CDK work to a private buildWithCdk(). The default arm assigns to `never`, so a new ManagedBySchema member fails to compile until it has an arm here.
1 parent f2b5390 commit 05c244e

3 files changed

Lines changed: 41 additions & 1 deletion

File tree

src/core/project/manager.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,18 @@ describe("FsProjectManager.build", () => {
273273
expect(commands).toEqual([]);
274274
});
275275

276+
test("refuses a project managed by a backend it cannot build", async () => {
277+
const directory = await inTempDirectory();
278+
const { manager: subject, commands } = manager();
279+
const project = await scaffolded(subject, directory);
280+
commands.length = 0;
281+
282+
// CDK is the only backend today; the cast stands in for a future one.
283+
const foreign = { ...project, managedBy: "Terraform" as Project["managedBy"] };
284+
await expect(drain(subject.build(foreign))).rejects.toThrow(/unsupported backend: Terraform/);
285+
expect(commands).toEqual([]);
286+
});
287+
276288
test("propagates a synthesis failure", async () => {
277289
const directory = await inTempDirectory();
278290
const { manager: subject } = manager();
@@ -300,6 +312,7 @@ describe("FsProjectManager.resolve", () => {
300312

301313
expect(resolved?.name).toBe("example");
302314
expect(resolved?.rootPath).toBe(join(root, "example"));
315+
expect(resolved?.managedBy).toBe("CDK");
303316
expect(resolved?.runtimes).toHaveLength(1);
304317
});
305318

src/core/project/manager.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ export class FsProjectManager implements ProjectManager {
5454
const configPath = join(rootPath, "agentcore", "agentcore.json");
5555
try {
5656
const spec = await this.json.read(configPath, ProjectSpecSchema);
57-
return { name: spec.name, rootPath, runtimes: spec.runtimes };
57+
return {
58+
name: spec.name,
59+
rootPath,
60+
managedBy: spec.managedBy,
61+
runtimes: spec.runtimes,
62+
};
5863
} catch (error) {
5964
// A malformed agentcore.json is a user-correctable problem, not a crash.
6065
if (error instanceof DeserializationError) {
@@ -119,6 +124,25 @@ export class FsProjectManager implements ProjectManager {
119124
}
120125

121126
public async *build(project: Project): AsyncGenerator<ProjectEvent, void> {
127+
// agentcore.json records which backend owns the project's artifacts. CDK is the
128+
// only one today; a terraform or no-IaC backend adds an arm here rather than
129+
// editing the CDK path.
130+
switch (project.managedBy) {
131+
case "CDK":
132+
yield* this.buildWithCdk(project);
133+
break;
134+
default: {
135+
// Exhaustiveness: a new ManagedBy member fails to compile until it is handled.
136+
const unsupported: never = project.managedBy;
137+
throw new ProjectStateError(
138+
`project '${project.name}' declares an unsupported backend: ${String(unsupported)}`,
139+
);
140+
}
141+
}
142+
}
143+
144+
// Compiles the generated CDK app and synthesizes its CloudFormation templates.
145+
private async *buildWithCdk(project: Project): AsyncGenerator<ProjectEvent, void> {
122146
const cdkDir = join(project.rootPath, "agentcore", "cdk");
123147

124148
// The generated CDK app is built from its own node_modules; without them the

src/handlers/project/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { ManagedBy } from "../../projectSchemas/project";
12
import type { ProjectRuntime } from "../../projectSchemas/runtime";
23

34
/** Available project templates for scaffolding new AgentCore projects. */
@@ -33,6 +34,8 @@ export type Project = {
3334
name: string;
3435
/** Absolute path to the project root (the parent of agentcore/). */
3536
rootPath: string;
37+
/** The infrastructure backend that owns the project's deployable artifacts. */
38+
managedBy: ManagedBy;
3639
/** The runtimes registered in agentcore.json. */
3740
runtimes: ProjectRuntime[];
3841
};

0 commit comments

Comments
 (0)