Skip to content
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

fix(cli): build assets before deploying any stacks #21513

Merged
merged 17 commits into from
Aug 19, 2022

Conversation

misterjoshua
Copy link
Contributor

@misterjoshua misterjoshua commented Aug 8, 2022

Changes the CDK CLI to build assets before deploying any stacks. This allows the CDK CLI to catch docker build errors, such as from rate limiting, before any stacks are deployed. Moving asset builds this early prevents these build failures from interrupting multi-stack deployments part way through.

Fixes #21511


All Submissions:

Adding new Unconventional Dependencies:

  • This PR adds new unconventional dependencies following the process described here

New Features

  • Have you added the new feature to an integration test?
    • Did you use yarn integ to deploy the infrastructure and generate the snapshot (i.e. yarn integ without --dry-run)?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

@gitpod-io
Copy link

gitpod-io bot commented Aug 8, 2022

@github-actions github-actions bot added feature-request A feature should be added or improved. p2 labels Aug 8, 2022
@aws-cdk-automation aws-cdk-automation requested a review from a team August 8, 2022 22:29
@misterjoshua
Copy link
Contributor Author

misterjoshua commented Aug 8, 2022

Here's a demonstration of how this looks on a local test project:

prebuild2.mp4

@misterjoshua misterjoshua changed the title feat(aws-cdk): add asset prepublishing feat(cli): add asset prepublishing Aug 8, 2022
@misterjoshua
Copy link
Contributor Author

misterjoshua commented Aug 8, 2022

I'm unsure whether I should be updating a README for this one - should I rename this to a fix so the PR linter doesn't complain?

Edit: I've changed it to a fix for now. We can change it later if needed.

@misterjoshua misterjoshua changed the title feat(cli): add asset prepublishing feat(cli): publish assets before deploying any stacks Aug 8, 2022
@niebloomj
Copy link

Would this update Lambda code also before deploying stacks?

@misterjoshua
Copy link
Contributor Author

misterjoshua commented Aug 8, 2022

Would this update Lambda code also before deploying stacks?

@niebloomj Nope. Same as before, it puts the assets in a bucket or ECR repository during publishing, but no changes are made to the lambda functions until the CLI deploys the stacks.

Edit: I was re-reading this thread and wondering if I misinterpreted your question the first time. If the question was whether this initial publishing phase works for Lambda .zips as well as Docker images, the answer is yes. Technically, even the synthesized CloudFormation templates are included in this phase. But as with above, changes to the infrastructure don't take effect until after CDK signals to deploy the stacks.

const shouldPublish = !disableAssetPublishing && !isImporting;

if (shouldPublish) {
await this._publishStackAssets(options.stack, toolkitInfo);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this is to maintain deployStack()'s backwards compatibility, but I wonder whether publishing assets via deployStack() is even necessary. Given that cdk import is the only other place deployStack() is used and that we're not publishing assets there, I can't think of any good reasons to keep the old behaviour. But, I wanted to discuss this first before making that change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CloudFormationDeployments is not exposed in v2 (though it was in v1). See #18211

I'd want someone else to confirm this, but from what I can tell it's up for changes.

@misterjoshua misterjoshua changed the title feat(cli): publish assets before deploying any stacks fix(cli): publish assets before deploying any stacks Aug 10, 2022
@mrgrain
Copy link
Contributor

mrgrain commented Aug 11, 2022

@misterjoshua I'm a concerned this PR reverts recent gains made by #19378
Specifically it looks like asset publishing is now a synchronous operation for all stacks.

@misterjoshua
Copy link
Contributor Author

@misterjoshua I'm a concerned this PR reverts recent gains made by #19378 Specifically it looks like asset publishing is now a synchronous operation for all stacks.

@mrgrain It should be possible to parallelize this build process at the given level of concurrency. I'll see what I can do about that.

@mrgrain
Copy link
Contributor

mrgrain commented Aug 11, 2022

Does this respect --exclusively ?

@misterjoshua
Copy link
Contributor Author

Does this respect --exclusively ?

@mrgrain Yes, it does. The stack collection we're drawing from is provided by CdkTooklit.selectStacksForDeploy which handles the --exclusively flag for us. When --exclusively is requested, the stack collection will contain just one stack.

const stackCollection = await this.selectStacksForDeploy(options.selector, options.exclusively, options.cacheCloudAssembly);

private async selectStacksForDeploy(selector: StackSelector, exclusively?: boolean, cacheCloudAssembly?: boolean): Promise<StackCollection> {

@misterjoshua
Copy link
Contributor Author

@misterjoshua I'm a concerned this PR reverts recent gains made by #19378 Specifically it looks like asset publishing is now a synchronous operation for all stacks.

@mrgrain I've added concurrency to the publishing step. Does this alleviate your concern?

@mrgrain
Copy link
Contributor

mrgrain commented Aug 12, 2022

@mrgrain I've added concurrency to the publishing step. Does this alleviate your concern?

Yes, it does address the speed improvements.


In the PR and issue you seem to imply that your motivation of always failing ALL stack deployments when there is an issue with assets in ANY of the stacks is a desirable or even expected behavior. I can see this very much being the case for App with coupled stacks. The current functionality however is that any stacks before the failure will deploy successfully. Admittedly --concurrency is brand-new, but with this flag I believe all other stacks would deploy successfully.

This begs the question to me: Can the change in this PR be the unchangeable default behavior? Should it be an optional flag or even pulled out into separate command?

Copy link
Contributor

@mrgrain mrgrain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies forgot to post these pending comments.

@@ -488,3 +510,27 @@ export class CloudFormationDeployments {
}
}
}

/**
* Options for publishing stack assets.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Options for publishing stack assets.
* Options for publishing stack assets

@@ -451,10 +463,20 @@ export class CloudFormationDeployments {
};
}

/**
* Publish a stack's assets.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Publish a stack's assets.
* Publish a stack's assets

Comment on lines 240 to 245
/**
* Disable asset publishing
*
* @default false
*/
readonly disableAssetPublishing?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking out loud here, would this be easier to understand if it were this?

Suggested change
/**
* Disable asset publishing
*
* @default false
*/
readonly disableAssetPublishing?: boolean;
/**
* Whether to publish Assets as part of a Stack deployment
*
* @default true
*/
readonly publishAssets?: boolean;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes please! Negative arguments break my brains.

* @default 'CDKToolkit'
*/
readonly toolkitStackName?: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
}

continue;
}

print('🏭 Pre-building and publishing assets for %s\n', stack.displayName);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print('🏭 Pre-building and publishing assets for %s\n', stack.displayName);
print('🏭 Building and publishing assets for %s\n', stack.displayName);

Open to suggestions here, but it feels like it's only "pre" because we know it used to be later in the process. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reading this - Building usually occurs at synth time. This might be confusing.

@rix0rrr
Copy link
Contributor

rix0rrr commented Aug 12, 2022

Hi @misterjoshua, thanks for the good idea. I see how this would definitely help with common pain points.

Unfortunately, this change is going to interfere with future changes I would like to make. Those being:

  • treating asset deployments as "just any other type of artifact that can be orchestrated"; as well as
  • giving them inputs and outputs.

Doing so would make it possible to do things like: stack 1 creates a bucket, the assets for stack 2 are published into that bucket, then stack 2 gets deployed -- and it all gets cleaned up on deletion.

I'm pretty sure many people would probably much prefer this (it makes it so that the bootstrap stack doesn't need to pre-create S3 buckets and ECR repositories), but that requires that assets are not "special" and just get sequenced like any other deployment.

Treating assets specially and pulling their publishing to the front would not be compatible with that model.


In the hypothetical future situation, we can achieve the current behavior in 2 ways:

  • Scan the list of assets, build them first, then proceed with deploying as normal; or
  • Separate out the building and publishing of assets as 2 different types of actions orchestrated by the CLI, in which case we can push all builds to the front and sequence the deploys as usual.

I think the second solution would have my preference, but I can live with the first.


With respect to this PR, in the short term you can try one of these:

  • Help work towards our utopia maybe? (😅 -- but it will be a large lift)
  • Do the short-circuit solution, in which we pre-build assets (but publish at the normal time)
  • Solve the issue locally for yourself, by running cdk-assets before running cdk deploy. Short-circuiting will make sure no duplicate work is done (However, the cdk-assets CLI doesn't have the auth flexibility that the CDK CLI itself has, and depending on your auth setup may or may not work)

Copy link
Contributor

@rix0rrr rix0rrr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my previous post

@misterjoshua misterjoshua changed the title fix(cli): publish assets before deploying any stacks fix(cli): build assets before deploying any stacks Aug 14, 2022
@github-actions github-actions bot added the effort/small Small work item – less than a day of effort label Aug 14, 2022
@misterjoshua
Copy link
Contributor Author

@Mergifyio update

@mergify
Copy link
Contributor

mergify bot commented Aug 14, 2022

update

✅ Branch has been successfully updated

@misterjoshua
Copy link
Contributor Author

@rix0rrr I've adjusted this PR to separate asset builds from publishing. Is this closer to what you had in mind?

@misterjoshua
Copy link
Contributor Author

I've fixed a few small oversights and recorded another video to show how this looks for three stacks.

ice_video_20220814-115842.mp4

@github-actions github-actions bot added p1 and removed p2 labels Aug 15, 2022
@mrgrain
Copy link
Contributor

mrgrain commented Aug 16, 2022

@misterjoshua That looks like the right direction, but let's wait for @rix0rrr 's feedback first.

@misterjoshua
Copy link
Contributor Author

@misterjoshua That looks like the right direction, but let's wait for @rix0rrr 's feedback first.

Sounds good. I'll keep an eye out for comments. :)

buildStackAssets: (stack: cxapi.CloudFormationStackArtifact) => Promise<void>;
};

export async function buildAllStackAssets(stacks: cxapi.CloudFormationStackArtifact[], options: Options): Promise<void> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function used to handle --concurrency, but after #21661 reverted --concurrency, we have to build sequentially. As-is, this logic could arguably be moved into CdkToolkit. But, I wanted to wait until I get more feedback on whether this PR is going in the right direction before I make too many changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--concurrency is being re-rolled, but I'm honestly not quite sure if building in parallel makes sense. The logs will probably intersperse in unreadable ways if we do that.

@mergify
Copy link
Contributor

mergify bot commented Aug 19, 2022

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildv2Project1C6BFA3F-wQm2hXv2jqQv
  • Commit ID: 9a18370
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify mergify bot merged commit 5cc0d35 into aws:main Aug 19, 2022
@mergify
Copy link
Contributor

mergify bot commented Aug 19, 2022

Thank you for contributing! Your pull request will be updated from main and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

josephedward pushed a commit to josephedward/aws-cdk that referenced this pull request Aug 30, 2022
Changes the CDK CLI to build assets before deploying any stacks. This allows the CDK CLI to catch docker build errors, such as from rate limiting, before any stacks are deployed. Moving asset builds this early prevents these build failures from interrupting multi-stack deployments part way through. 

Fixes aws#21511

----

### All Submissions:

* [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [ ] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [ ] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@rabbittsoup
Copy link
Contributor

Opened issue #21965 due to this behavior change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort/small Small work item – less than a day of effort feature-request A feature should be added or improved. p1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

(cli): build+publish all assets used for all selected stacks before deploying any stacks
6 participants