From 90da730244513f9614604f6be3a77adbb6b17f79 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Mon, 8 Nov 2021 10:52:28 +0100 Subject: [PATCH] feat(lambda-nodejs): custom asset hash (#16412) By default the asset hash for a `NodejsFunction` is based on the bundling output, the result of the `esbuild` bundling. Add a `assetHash` prop to customize the asset hash and allow users to implement their own logic. This can be useful if users want to invalidate the asset based on specific (input) file contents or logic. Closes #16157 ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- packages/@aws-cdk/aws-lambda-nodejs/README.md | 17 +++++++++++++++++ .../@aws-cdk/aws-lambda-nodejs/lib/bundling.ts | 3 ++- .../@aws-cdk/aws-lambda-nodejs/lib/types.ts | 15 +++++++++++++++ .../aws-lambda-nodejs/test/bundling.test.ts | 18 ++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-lambda-nodejs/README.md b/packages/@aws-cdk/aws-lambda-nodejs/README.md index 1d3eaa66a2a4a..ae6f6014fa9a1 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/README.md +++ b/packages/@aws-cdk/aws-lambda-nodejs/README.md @@ -284,3 +284,20 @@ should also have `npm`, `yarn` or `pnpm` depending on the lock file you're using Use the [default image provided by `@aws-cdk/aws-lambda-nodejs`](https://github.com/aws/aws-cdk/blob/master/packages/%40aws-cdk/aws-lambda-nodejs/lib/Dockerfile) as a source of inspiration. + +## Asset hash + +By default the asset hash will be calculated based on the bundled output (`AssetHashType.OUTPUT`). + +Use the `assetHash` prop to pass a custom hash: + +```ts +new lambda.NodejsFunction(this, 'my-handler', { + bundling: { + assetHash: 'my-custom-hash', + }, +}); +``` + +If you chose to customize the hash, you will need to make sure it is updated every time the asset +changes, or otherwise it is possible that some deployments will not be invalidated. diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index 5b7c6ce416b2c..31fedbafc6e3d 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -54,7 +54,8 @@ export class Bundling implements cdk.BundlingOptions { */ public static bundle(options: BundlingProps): AssetCode { return Code.fromAsset(options.projectRoot, { - assetHashType: cdk.AssetHashType.OUTPUT, + assetHash: options.assetHash, + assetHashType: options.assetHash ? cdk.AssetHashType.CUSTOM : cdk.AssetHashType.OUTPUT, bundling: new Bundling(options), }); } diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index 87d3de0eec1fc..b21d7a5fee5c2 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -248,6 +248,21 @@ export interface BundlingOptions { * @default - do not run additional commands */ readonly commandHooks?: ICommandHooks; + + /** + * Specify a custom hash for this asset. For consistency, this custom hash will + * be SHA256 hashed and encoded as hex. The resulting hash will be the asset + * hash. + * + * NOTE: the hash is used in order to identify a specific revision of the asset, and + * used for optimizing and caching deployment activities related to this asset such as + * packaging, uploading to Amazon S3, etc. If you chose to customize the hash, you will + * need to make sure it is updated every time the asset changes, or otherwise it is + * possible that some deployments will not be invalidated. + * + * @default - asset hash is calculated based on the bundled output + */ + readonly assetHash?: string; } /** diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index e79ddc2aca150..9ef40545baf31 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -658,3 +658,21 @@ test('esbuild bundling with pre compilations and undefined tsconfig ( Should thr }).toThrow('Cannot find a tsconfig.json, please specify the prop: tsconfig'); }); + +test('with custom hash', () => { + Bundling.bundle({ + entry, + projectRoot, + depsLockFilePath, + runtime: Runtime.NODEJS_14_X, + forceDockerBundling: true, + assetHash: 'custom', + architecture: Architecture.X86_64, + }); + + // Correctly passes asset hash options + expect(Code.fromAsset).toHaveBeenCalledWith(path.dirname(depsLockFilePath), expect.objectContaining({ + assetHash: 'custom', + assetHashType: AssetHashType.CUSTOM, + })); +});