-
Notifications
You must be signed in to change notification settings - Fork 52
fix(vpc): fix 3 bug-bash-found defects in create-harness VPC + backfill (follow-up to #1671) #1682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -411,10 +411,12 @@ export async function handleDeploy(options: ValidatedDeployOptions): Promise<Dep | |
| } | ||
|
|
||
| // Backfill vpcId for pre-existing Container+VPC configs written before vpcId was required. This | ||
| // resolves the VPC from the subnets (ec2:DescribeSubnets) and persists it to disk so the CDK | ||
| // synth process — which re-reads agentcore.json / harness.json — has the value it needs. Fresh | ||
| // creates already carry a vpcId, so this is a no-op for them. | ||
| const backfill = await backfillContainerVpcIds(configIO, context.projectSpec, target.region); | ||
| // resolves the VPC from the subnets (ec2:DescribeSubnets) and writes it to disk so the CDK synth | ||
| // process — which re-reads agentcore.json / harness.json — has the value it needs. Fresh creates | ||
| // already carry a vpcId, so this is a no-op for them. In preview modes (--dry-run / --diff) the | ||
| // write is reverted after synth via backfill.restore() so a preview leaves the working tree clean. | ||
| const isPreview = !!options.plan || !!options.diff; | ||
| const backfill = await backfillContainerVpcIds(configIO, context.projectSpec, target.region, !isPreview); | ||
| if (backfill.backfilled.length > 0) { | ||
| logger.log(`Resolved networkConfig.vpcId for Container+VPC build(s): ${backfill.backfilled.join(', ')}`, 'info'); | ||
| } | ||
|
|
@@ -477,8 +479,10 @@ export async function handleDeploy(options: ValidatedDeployOptions): Promise<Dep | |
| } | ||
| endStep('success'); | ||
|
|
||
| // Plan mode: stop after synth and checks, don't deploy | ||
| // Plan mode: stop after synth and checks, don't deploy. Revert any vpcId the backfill wrote to | ||
| // disk for synth — a preview must not dirty the working tree. | ||
| if (options.plan) { | ||
| await backfill.restore(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BUG-2's contract is "a preview must not dirty the working tree" — but the restore is only called on the happy-path exits of the plan/diff blocks (L485, L504). Between the backfill at L419 and those calls there are several failure paths where the file stays dirty on a
Since
Option 1 seems most robust and matches the pattern already used for |
||
| logger.finalize(true); | ||
| await toolkitWrapper.dispose(); | ||
| toolkitWrapper = null; | ||
|
|
@@ -490,12 +494,14 @@ export async function handleDeploy(options: ValidatedDeployOptions): Promise<Dep | |
| }; | ||
| } | ||
|
|
||
| // Diff mode: run cdk diff and exit without deploying | ||
| // Diff mode: run cdk diff and exit without deploying. Revert any vpcId the backfill wrote to disk | ||
| // for synth — like plan mode, a diff preview must not dirty the working tree. | ||
| if (options.diff) { | ||
| startStep('Run CDK diff'); | ||
| await runDiff(toolkitWrapper, stackName, switchableIoHost); | ||
| endStep('success'); | ||
|
|
||
| await backfill.restore(); | ||
| logger.finalize(true); | ||
| await toolkitWrapper.dispose(); | ||
| toolkitWrapper = null; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
backfill.restore()is only called on the two happy-path returns (plan at L485, diff at L504), but between the backfill call at L419 and those returns there are several ways the flow can bail out afteragentcore.json/harness.jsonhave already been rewritten to disk:synthesizeCdkat L427 can throw → caught by the outercatchat L982, no restore runs.try), no restore.runDiffat L501 can throw → outer catch, no restore.So a
--dry-runor--diffthat fails for any reason after the backfill will leave the working tree dirty — which is exactly the "preview must not dirty the working tree" contract this PR's BUG-2 fix is trying to establish. The newdry-run (persist=false) restoretest only covers the happy path.A few ways to fix:
restore()for thefinallyblock, e.g. capture it into apreviewRestore: (() => Promise<void>) | undefineddeclared before thetryand invoke it in the existingfinally(L986–L991) when set. Cheapest change and covers every exit path.await backfill.restore()calls out of the happy branches entirely and rely solely on option 1.try/finallythat always callsrestore()in preview mode.Any of these will do; option 1 is the smallest diff. Please also add a regression test that forces a throw between
backfillContainerVpcIdsand the plan/diff short-circuit (e.g. by makingsynthesizeCdkreject) and asserts the on-disk files are still reverted.