Skip to content

Commit 759924e

Browse files
notgitikagitikavj
andauthored
feat(migrate)!: add agentcore migrate (#2584)
agentcore migrate upgrades a v0 project to the v1 format without replacing any deployed resource. - One flow: every run computes the full read-only preview from scratch, shows a short summary on stdout (the full plan goes to agentcore/.cli/migrate/plan-<UTC>.md, which the git check ignores), then asks "Apply these changes?" on a terminal. --yes skips only the prompt; non-interactive and --json runs without --yes stop after the preview. There is no --dry-run. - Names: the converted agentcore.json sets migratedFrom: "v1", so the CDK library keeps every v0 physical name. - Stacks: logical IDs move to v1's with CloudFormation stack refactoring, one deployment target at a time (--target when several are deployed; others are recorded as pending and finished later with --target). Every step is recorded first in an atomic journal (agentcore/.cli/migration-state.json), so an interrupted run is finished or undone by running migrate again. - Deploying a target the journal still lists is refused, in the project manager's deploy (CLI, TUI, harness dev) and the v0 deploy delegation. - Any file added or changed in agentcore/cdk blocks, since migrating replaces it; files are compared with what each v0 release vended. - Only a 4xx from ExecuteStackRefactor counts as not started; other failures are unknown, keep the journal with the refactor ID, never put files back, and print the commands to check it. - Credential providers of a migrated project keep v0's bare names and are never deleted. - Migration is blocked until the CLI vends an @aws/agentcore-cdk release that honors migratedFrom (AGENTCORE_MIGRATE_CDK_LIBRARY overrides it for testing only). - Progress uses the shared runWithProgress task list on stderr, including the stack's resource events while a refactor executes. With the testing override, the summary and the next steps show the npm install command for the library the plan was made with. Co-authored-by: gitikavj <gitikavj@amazon.com>
1 parent 0c43c32 commit 759924e

101 files changed

Lines changed: 30168 additions & 220 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎bun.lock‎

Lines changed: 12 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"typescript": "^5"
6767
},
6868
"dependencies": {
69+
"@aws-cdk/cloudformation-diff": "2.187.4",
6970
"@aws-cdk/toolkit-lib": "1.38.2",
7071
"@aws-sdk/client-application-signals": "^3.1092.0",
7172
"@aws-sdk/client-bedrock-agent": "^3.1092.0",
@@ -74,6 +75,7 @@
7475
"@aws-sdk/client-cloudformation": "^3.1092.0",
7576
"@aws-sdk/client-cloudwatch-logs": "^3.1092.0",
7677
"@aws-sdk/client-iam": "^3.1080.0",
78+
"@aws-sdk/client-s3": "^3.1121.0",
7779
"@aws-sdk/client-sts": "^3.1092.0",
7880
"@aws-sdk/client-xray": "^3.1092.0",
7981
"@aws-sdk/util-endpoints": "^3.996.44",

‎scripts/build.ts‎

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ const ASSET_NAMING = "agentcore-assets/[dir]/[name].[ext]";
2424
// __dirname to the *build machine's* path, which resolves on the builder and
2525
// fails everywhere else. Binaries therefore have to hand the Toolkit an
2626
// explicit copy of anything it would otherwise read from its package.
27-
const EXTERNAL = ["@aws-cdk/toolkit-lib", "@napi-rs/keyring"];
27+
//
28+
// @aws-cdk/cloudformation-diff (migrate's replacement check) is external for the
29+
// same reason: it loads its resource database from a file inside its package.
30+
const EXTERNAL = ["@aws-cdk/toolkit-lib", "@napi-rs/keyring", "@aws-cdk/cloudformation-diff"];
2831

2932
const BOOTSTRAP_TEMPLATE = ["lib", "api", "bootstrap", "bootstrap-template.yaml"];
3033

34+
const SERVICE_SPEC_DATABASE = "db.json.gz";
35+
3136
// Shrink whitespace/syntax but keep identifiers: minified names make stack
3237
// traces unreadable and erase error names telemetry keys on.
3338
const MINIFY = { whitespace: true, syntax: true, identifiers: false } as const;
@@ -79,6 +84,50 @@ function assetLoaderPlugin(): Bun.BunPlugin {
7984
};
8085
}
8186

87+
/**
88+
* `agentcore migrate` checks for replacements with @aws-cdk/cloudformation-diff,
89+
* which reads the AWS resource specification from `db.json.gz` beside its
90+
* @aws-cdk/aws-service-spec dependency, at a path built from `__dirname`. In a
91+
* standalone binary that path is the build machine's, so this embeds the database
92+
* and points the loader at the embedded copy instead.
93+
*/
94+
function serviceSpecDatabase(): string {
95+
const diffManifest = Bun.resolveSync("@aws-cdk/cloudformation-diff/package.json", REPO_ROOT);
96+
const specManifest = Bun.resolveSync(
97+
"@aws-cdk/aws-service-spec/package.json",
98+
resolve(diffManifest, ".."),
99+
);
100+
const database = join(resolve(specManifest, ".."), SERVICE_SPEC_DATABASE);
101+
if (!existsSync(database)) {
102+
throw new Error(
103+
`@aws-cdk/aws-service-spec no longer ships ${SERVICE_SPEC_DATABASE}; looked in ${database}`,
104+
);
105+
}
106+
return database;
107+
}
108+
109+
function serviceSpecDatabasePlugin(database: string): Bun.BunPlugin {
110+
const loader = /@aws-cdk[/\\]aws-service-spec[/\\]lib[/\\]index\.js$/;
111+
const pathLine = "const DB_PATH = path.join(__dirname, '..', DB_COMPRESSED);";
112+
return {
113+
name: "aws-service-spec-database",
114+
setup(build) {
115+
build.onLoad({ filter: loader }, async ({ path }) => {
116+
const source = await Bun.file(path).text();
117+
if (!source.includes(pathLine)) {
118+
throw new Error(`${path} no longer builds its database path as expected: ${pathLine}`);
119+
}
120+
return {
121+
contents:
122+
`import EMBEDDED_DB_PATH from ${JSON.stringify(database)} with { type: "file" };\n` +
123+
source.replace(pathLine, "const DB_PATH = EMBEDDED_DB_PATH;"),
124+
loader: "js",
125+
};
126+
});
127+
},
128+
};
129+
}
130+
82131
function runtimeShellSdkPlugin(): Bun.BunPlugin {
83132
const runtimeEntry = Bun.resolveSync("bedrock-agentcore/runtime", REPO_ROOT);
84133
const runtimeDirectory = resolve(runtimeEntry, "..");
@@ -127,13 +176,13 @@ function bootstrapTemplate(): string {
127176
return template;
128177
}
129178

130-
async function assertTemplateIsEmbedded(outfile: string, template: string): Promise<void> {
179+
async function assertFileIsEmbedded(outfile: string, file: string, label: string): Promise<void> {
131180
const [executable, contents] = await Promise.all([
132181
Bun.file(outfile).bytes(),
133-
Bun.file(template).bytes(),
182+
Bun.file(file).bytes(),
134183
]);
135184
if (!Buffer.from(executable).includes(contents)) {
136-
throw new Error(`${outfile} does not contain ${BOOTSTRAP_TEMPLATE.join("/")}`);
185+
throw new Error(`${outfile} does not contain ${label}`);
137186
}
138187
}
139188

@@ -196,18 +245,25 @@ async function compile(target: string): Promise<void> {
196245
await $`mkdir -p ${join(DIST, "bin")}`;
197246

198247
const template = bootstrapTemplate();
248+
const database = serviceSpecDatabase();
199249
await Bun.build({
200250
entrypoints: [ENTRYPOINT, ...assets, template],
201251
compile: { target: target as Bun.Build.CompileTarget, outfile },
202252
minify: MINIFY,
203253
define: DEFINE,
204254
root: REPO_ROOT,
205255
naming: { asset: ASSET_NAMING },
206-
plugins: [assetLoaderPlugin(), runtimeShellSdkPlugin(), nativeKeyringPlugin(target)],
256+
plugins: [
257+
assetLoaderPlugin(),
258+
runtimeShellSdkPlugin(),
259+
nativeKeyringPlugin(target),
260+
serviceSpecDatabasePlugin(database),
261+
],
207262
});
208-
await assertTemplateIsEmbedded(outfile, template);
263+
await assertFileIsEmbedded(outfile, template, BOOTSTRAP_TEMPLATE.join("/"));
264+
await assertFileIsEmbedded(outfile, database, `aws-service-spec ${SERVICE_SPEC_DATABASE}`);
209265
console.log(
210-
`Compiled ${target} → ${outfile} (${assets.length} assets embedded, plus the bootstrap template)`,
266+
`Compiled ${target} → ${outfile} (${assets.length} assets embedded, plus the bootstrap template and the AWS resource specification)`,
211267
);
212268
}
213269

0 commit comments

Comments
 (0)