From cb9dba674963bc22a921885eefdaa0ce8fae2ca4 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 10:15:20 +0100 Subject: [PATCH 01/20] feat(core): custom archive with bundling --- packages/@aws-cdk/aws-s3-assets/lib/asset.ts | 30 +--------- packages/@aws-cdk/core/lib/asset-staging.ts | 60 +++++++++++++++++++- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/packages/@aws-cdk/aws-s3-assets/lib/asset.ts b/packages/@aws-cdk/aws-s3-assets/lib/asset.ts index 938778d1381f4..510834a61c634 100644 --- a/packages/@aws-cdk/aws-s3-assets/lib/asset.ts +++ b/packages/@aws-cdk/aws-s3-assets/lib/asset.ts @@ -1,4 +1,3 @@ -import * as fs from 'fs'; import * as path from 'path'; import * as assets from '@aws-cdk/assets'; import * as iam from '@aws-cdk/aws-iam'; @@ -13,8 +12,6 @@ import { toSymlinkFollow } from './compat'; // eslint-disable-next-line no-duplicate-imports, import/order import { Construct as CoreConstruct } from '@aws-cdk/core'; -const ARCHIVE_EXTENSIONS = ['.zip', '.jar']; - export interface AssetOptions extends assets.CopyOptions, cdk.AssetOptions { /** * A list of principals that should be able to read this asset from S3. @@ -139,17 +136,12 @@ export class Asset extends CoreConstruct implements cdk.IAsset { this.assetPath = staging.relativeStagedPath(stack); - const packaging = determinePackaging(staging.sourcePath); - - this.isFile = packaging === cdk.FileAssetPackaging.FILE; + this.isFile = staging.packaging === cdk.FileAssetPackaging.FILE; - // sets isZipArchive based on the type of packaging and file extension - this.isZipArchive = packaging === cdk.FileAssetPackaging.ZIP_DIRECTORY - ? true - : ARCHIVE_EXTENSIONS.some(ext => staging.sourcePath.toLowerCase().endsWith(ext)); + this.isZipArchive = staging.isArchive; const location = stack.synthesizer.addFileAsset({ - packaging, + packaging: staging.packaging, sourceHash: this.sourceHash, fileName: this.assetPath, }); @@ -210,19 +202,3 @@ export class Asset extends CoreConstruct implements cdk.IAsset { this.bucket.grantRead(grantee); } } - -function determinePackaging(assetPath: string): cdk.FileAssetPackaging { - if (!fs.existsSync(assetPath)) { - throw new Error(`Cannot find asset at ${assetPath}`); - } - - if (fs.statSync(assetPath).isDirectory()) { - return cdk.FileAssetPackaging.ZIP_DIRECTORY; - } - - if (fs.statSync(assetPath).isFile()) { - return cdk.FileAssetPackaging.FILE; - } - - throw new Error(`Asset ${assetPath} is expected to be either a directory or a regular file`); -} diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 66c65e3d14864..99dd4db8de00d 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -5,7 +5,7 @@ import * as cxapi from '@aws-cdk/cx-api'; import { Construct } from 'constructs'; import * as fs from 'fs-extra'; import * as minimatch from 'minimatch'; -import { AssetHashType, AssetOptions } from './assets'; +import { AssetHashType, AssetOptions, FileAssetPackaging } from './assets'; import { BundlingOptions } from './bundling'; import { FileSystem, FingerprintOptions } from './fs'; import { Names } from './names'; @@ -17,6 +17,8 @@ import { Stage } from './stage'; // eslint-disable-next-line import { Construct as CoreConstruct } from './construct-compat'; +const ARCHIVE_EXTENSIONS = ['.zip', '.jar']; + /** * A previously staged asset */ @@ -138,6 +140,9 @@ export class AssetStaging extends CoreConstruct { private readonly cacheKey: string; + private _packaging = FileAssetPackaging.ZIP_DIRECTORY; + private _isArchive = true; + constructor(scope: Construct, id: string, props: AssetStagingProps) { super(scope, id); @@ -203,6 +208,20 @@ export class AssetStaging extends CoreConstruct { return this.assetHash; } + /** + * How this asset should be packaged. + */ + public get packaging(): FileAssetPackaging { + return this._packaging; + } + + /** + * Whether this asset is an archvie (zip or jar). + */ + public get isArchive(): boolean { + return this._isArchive; + } + /** * Return the path to the staged asset, relative to the Cloud Assembly (manifest) directory of the given stack * @@ -281,11 +300,25 @@ export class AssetStaging extends CoreConstruct { const bundleDir = this.determineBundleDir(this.assetOutdir, assetHash); this.bundle(bundling, bundleDir); + let sourcePath = bundleDir; + let extension: string | undefined; + + // Check whether bundling resulted in a single archive file (zip, jar) + const bundledFile = singleFile(bundleDir); + if (bundledFile) { + const bundledExtension = path.extname(bundledFile).toLowerCase(); + if (ARCHIVE_EXTENSIONS.includes(bundledExtension)) { + sourcePath = bundledFile; + extension = bundledExtension; + this._packaging = FileAssetPackaging.FILE; + } + } + // Calculate assetHash afterwards if we still must assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, bundleDir); - const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash)); + const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, extension)); - this.stageAsset(bundleDir, stagedPath, 'move'); + this.stageAsset(sourcePath, stagedPath, 'move'); return { assetHash, stagedPath }; } @@ -323,6 +356,8 @@ export class AssetStaging extends CoreConstruct { const stat = fs.statSync(sourcePath); if (stat.isFile()) { fs.copyFileSync(sourcePath, targetPath); + this._packaging = FileAssetPackaging.FILE; + this._isArchive = ARCHIVE_EXTENSIONS.includes(path.extname(sourcePath).toLowerCase()); } else if (stat.isDirectory()) { fs.mkdirSync(targetPath); FileSystem.copyDirectory(sourcePath, targetPath, this.fingerprintOptions); @@ -502,3 +537,22 @@ function sortObject(object: { [key: string]: any }): { [key: string]: any } { } return ret; } + +/** + * Returns the single file of a directory or undefined + */ +function singleFile(directory: string): string | undefined { + if (!fs.statSync(directory).isDirectory()) { + return undefined; + } + + const content = fs.readdirSync(directory); + if (content.length === 1) { + const file = path.join(directory, content[0]); + if (fs.statSync(file).isFile()) { + return file; + } + } + + return undefined; +} From 0f451276bf6136047f6e46368f9f3c53aea96f09 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 14:30:10 +0100 Subject: [PATCH 02/20] BundlePackaging --- packages/@aws-cdk/core/lib/asset-staging.ts | 26 ++++++++++------- packages/@aws-cdk/core/lib/bundling.ts | 31 +++++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 99dd4db8de00d..026838b61b9ce 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -6,7 +6,7 @@ import { Construct } from 'constructs'; import * as fs from 'fs-extra'; import * as minimatch from 'minimatch'; import { AssetHashType, AssetOptions, FileAssetPackaging } from './assets'; -import { BundlingOptions } from './bundling'; +import { BundlingOptions, BundlePackaging } from './bundling'; import { FileSystem, FingerprintOptions } from './fs'; import { Names } from './names'; import { Cache } from './private/cache'; @@ -216,7 +216,7 @@ export class AssetStaging extends CoreConstruct { } /** - * Whether this asset is an archvie (zip or jar). + * Whether this asset is an archive (zip or jar). */ public get isArchive(): boolean { return this._isArchive; @@ -303,14 +303,20 @@ export class AssetStaging extends CoreConstruct { let sourcePath = bundleDir; let extension: string | undefined; - // Check whether bundling resulted in a single archive file (zip, jar) - const bundledFile = singleFile(bundleDir); - if (bundledFile) { - const bundledExtension = path.extname(bundledFile).toLowerCase(); - if (ARCHIVE_EXTENSIONS.includes(bundledExtension)) { - sourcePath = bundledFile; - extension = bundledExtension; - this._packaging = FileAssetPackaging.FILE; + const packaging = bundling.packaging ?? BundlePackaging.AUTO; + if (packaging !== BundlePackaging.ALWAYS_ZIP) { + // Check whether bundling resulted in a single archive file (zip, jar) + const bundledFile = singleFile(bundleDir); + if (bundledFile) { + const bundledExtension = path.extname(bundledFile).toLowerCase(); + const isArchive = ARCHIVE_EXTENSIONS.includes(bundledExtension); + if (packaging === BundlePackaging.NEVER_ZIP && !isArchive) { + throw new Error('Packaging was set to `NEVER_ZIP` but the bundling output did not produce an archive file.'); + } + if (packaging === BundlePackaging.AUTO && isArchive) { + sourcePath = bundledFile; + extension = bundledExtension; + } } } diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index b1247fd913ea0..923d04d601a58 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -79,6 +79,37 @@ export interface BundlingOptions { * @experimental */ readonly local?: ILocalBundling; + + /** + * The type of packaging to apply on the bundled asset. + * + * @default BundlePackaging.AUTO + * + * @experimental + */ + readonly packaging?: BundlePackaging; +} + +/** + * The type of packaging to apply on the bundled asset. + */ +export enum BundlePackaging { + /** + * The bundling output will be zipped and uploaded to S3. + */ + ALWAYS_ZIP = 'zip', + + /** + * The bundling output will not be zipped. Bundling will fail if the bundling + * output doesn't contain a single archive (zip or jar) file. + */ + NEVER_ZIP = 'no-zip', + + /** + * If the bundling output contains a single archive file (zip or jar) it will + * no be zipped. Otherwise it will be zipped. + */ + AUTO = 'auto' } /** From 7f25960dd77990ab09ca9c14f0e3f793c2df5489 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 15:22:37 +0100 Subject: [PATCH 03/20] tests --- packages/@aws-cdk/core/lib/asset-staging.ts | 23 +-- packages/@aws-cdk/core/lib/bundling.ts | 6 +- .../@aws-cdk/core/test/archive/archive.zip | 0 packages/@aws-cdk/core/test/docker-stub.sh | 15 +- packages/@aws-cdk/core/test/staging.test.ts | 149 +++++++++++++++++- 5 files changed, 178 insertions(+), 15 deletions(-) create mode 100644 packages/@aws-cdk/core/test/archive/archive.zip diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 026838b61b9ce..0787595d1ed08 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -300,31 +300,34 @@ export class AssetStaging extends CoreConstruct { const bundleDir = this.determineBundleDir(this.assetOutdir, assetHash); this.bundle(bundling, bundleDir); - let sourcePath = bundleDir; + let assetPath = bundleDir; let extension: string | undefined; const packaging = bundling.packaging ?? BundlePackaging.AUTO; if (packaging !== BundlePackaging.ALWAYS_ZIP) { - // Check whether bundling resulted in a single archive file (zip, jar) + // Check whether bundling resulted in a single file const bundledFile = singleFile(bundleDir); + if (packaging === BundlePackaging.NEVER_ZIP && !bundledFile) { + throw new Error('Packaging was set to `NEVER_ZIP` but the bundling output did not produce a single file.'); + } + if (bundledFile) { const bundledExtension = path.extname(bundledFile).toLowerCase(); - const isArchive = ARCHIVE_EXTENSIONS.includes(bundledExtension); - if (packaging === BundlePackaging.NEVER_ZIP && !isArchive) { - throw new Error('Packaging was set to `NEVER_ZIP` but the bundling output did not produce an archive file.'); - } - if (packaging === BundlePackaging.AUTO && isArchive) { - sourcePath = bundledFile; + const isSingleArchive = ARCHIVE_EXTENSIONS.includes(bundledExtension); + if (packaging === BundlePackaging.NEVER_ZIP ||(packaging === BundlePackaging.AUTO && isSingleArchive)) { + this._packaging = FileAssetPackaging.FILE; + this._isArchive = isSingleArchive; + assetPath = bundledFile; extension = bundledExtension; } } } // Calculate assetHash afterwards if we still must - assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, bundleDir); + assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, assetPath); const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, extension)); - this.stageAsset(sourcePath, stagedPath, 'move'); + this.stageAsset(assetPath, stagedPath, 'move'); return { assetHash, stagedPath }; } diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 923d04d601a58..7e7dac88adfc3 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -81,7 +81,7 @@ export interface BundlingOptions { readonly local?: ILocalBundling; /** - * The type of packaging to apply on the bundled asset. + * The type of packaging to apply on the bundling output. * * @default BundlePackaging.AUTO * @@ -92,6 +92,8 @@ export interface BundlingOptions { /** * The type of packaging to apply on the bundled asset. + * + * @experimental */ export enum BundlePackaging { /** @@ -107,7 +109,7 @@ export enum BundlePackaging { /** * If the bundling output contains a single archive file (zip or jar) it will - * no be zipped. Otherwise it will be zipped. + * not be zipped. Otherwise it will be zipped. */ AUTO = 'auto' } diff --git a/packages/@aws-cdk/core/test/archive/archive.zip b/packages/@aws-cdk/core/test/archive/archive.zip new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk/core/test/docker-stub.sh b/packages/@aws-cdk/core/test/docker-stub.sh index fe48e93d4a207..94f806f69a120 100755 --- a/packages/@aws-cdk/core/test/docker-stub.sh +++ b/packages/@aws-cdk/core/test/docker-stub.sh @@ -24,5 +24,18 @@ if echo "$@" | grep "DOCKER_STUB_SUCCESS"; then exit 0 fi -echo "Docker mock only supports one of the following commands: DOCKER_STUB_SUCCESS_NO_OUTPUT,DOCKER_STUB_FAIL,DOCKER_STUB_SUCCESS" +if echo "$@" | grep "DOCKER_STUB_MULTIPLE_FILES"; then + outdir=$(echo "$@" | xargs -n1 | grep "/asset-output" | head -n1 | cut -d":" -f1) + touch ${outdir}/test1.txt + touch ${outdir}/test2.txt + exit 0 +fi + +if echo "$@" | grep "DOCKER_STUB_SINGLE_ARCHIVE"; then + outdir=$(echo "$@" | xargs -n1 | grep "/asset-output" | head -n1 | cut -d":" -f1) + touch ${outdir}/test.zip + exit 0 +fi + +echo "Docker mock only supports one of the following commands: DOCKER_STUB_SUCCESS_NO_OUTPUT,DOCKER_STUB_FAIL,DOCKER_STUB_SUCCESS,DOCKER_STUB_MULTIPLE_FILES,DOCKER_SINGLE_ARCHIVE" exit 1 diff --git a/packages/@aws-cdk/core/test/staging.test.ts b/packages/@aws-cdk/core/test/staging.test.ts index 347c5fcea3b63..9f108391c4657 100644 --- a/packages/@aws-cdk/core/test/staging.test.ts +++ b/packages/@aws-cdk/core/test/staging.test.ts @@ -1,10 +1,11 @@ import * as os from 'os'; import * as path from 'path'; +import { FileAssetPackaging } from '@aws-cdk/cloud-assembly-schema'; import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; import { nodeunitShim, Test } from 'nodeunit-shim'; import * as sinon from 'sinon'; -import { App, AssetHashType, AssetStaging, BundlingDockerImage, BundlingOptions, FileSystem, Stack, Stage } from '../lib'; +import { App, AssetHashType, AssetStaging, BundlePackaging, BundlingDockerImage, BundlingOptions, FileSystem, Stack, Stage } from '../lib'; const STUB_INPUT_FILE = '/tmp/docker-stub.input'; const STUB_INPUT_CONCAT_FILE = '/tmp/docker-stub.input.concat'; @@ -12,7 +13,9 @@ const STUB_INPUT_CONCAT_FILE = '/tmp/docker-stub.input.concat'; enum DockerStubCommand { SUCCESS = 'DOCKER_STUB_SUCCESS', FAIL = 'DOCKER_STUB_FAIL', - SUCCESS_NO_OUTPUT = 'DOCKER_STUB_SUCCESS_NO_OUTPUT' + SUCCESS_NO_OUTPUT = 'DOCKER_STUB_SUCCESS_NO_OUTPUT', + MULTIPLE_FILES = 'DOCKER_STUB_MULTIPLE_FILES', + SINGLE_ARCHIVE = 'DOCKER_STUB_SINGLE_ARCHIVE', } const FIXTURE_TEST1_DIR = path.join(__dirname, 'fs', 'fixtures', 'test1'); @@ -50,6 +53,34 @@ nodeunitShim({ test.deepEqual(staging.sourcePath, sourcePath); test.deepEqual(path.basename(staging.stagedPath), 'asset.2f37f937c51e2c191af66acf9b09f548926008ec68c575bd2ee54b6e997c0e00'); test.deepEqual(path.basename(staging.relativeStagedPath(stack)), 'asset.2f37f937c51e2c191af66acf9b09f548926008ec68c575bd2ee54b6e997c0e00'); + test.deepEqual(staging.packaging, FileAssetPackaging.ZIP_DIRECTORY); + test.deepEqual(staging.isArchive, true); + test.done(); + }, + + 'staging of an archive file correctly sets packaging and isArchive'(test: Test) { + // GIVEN + const stack = new Stack(); + const sourcePath = path.join(__dirname, 'archive', 'archive.zip'); + + // WHEN + const staging = new AssetStaging(stack, 's1', { sourcePath }); + + test.deepEqual(staging.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging.isArchive, true); + test.done(); + }, + + 'staging of a non-archive file correctly sets packaging and isArchive'(test: Test) { + // GIVEN + const stack = new Stack(); + const sourcePath = __filename; + + // WHEN + const staging = new AssetStaging(stack, 's1', { sourcePath }); + + test.deepEqual(staging.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging.isArchive, false); test.done(); }, @@ -785,6 +816,120 @@ nodeunitShim({ ); test.equal(asset.assetHash, '33cbf2cae5432438e0f046bc45ba8c3cef7b6afcf47b59d1c183775c1918fb1f'); // hash of MyStack/Asset + test.done(); + }, + + 'bundling that produces a single archive file'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack'); + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); + + // WHEN + const staging = new AssetStaging(stack, 'Asset', { + sourcePath: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_ARCHIVE], + }, + }); + + // THEN + const assembly = app.synth(); + test.deepEqual(fs.readdirSync(assembly.directory), [ + 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48', // this is the bundle dir but it's empty + 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48.zip', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + test.deepEqual(staging.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging.isArchive, true); + + test.done(); + }, + + 'bundling that produces a single archive file with ALWAYS_ZIP'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack'); + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); + + // WHEN + const staging = new AssetStaging(stack, 'Asset', { + sourcePath: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_ARCHIVE], + packaging: BundlePackaging.ALWAYS_ZIP, + }, + }); + + // THEN + const assembly = app.synth(); + test.deepEqual(fs.readdirSync(assembly.directory), [ + 'asset.d6ed33ece892ac6be1b5f8151f83361aa8c044587d5431c4803cc9cadbc657cf', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + test.deepEqual(staging.packaging, FileAssetPackaging.ZIP_DIRECTORY); + test.deepEqual(staging.isArchive, true); + + test.done(); + }, + + 'bundling that produces a single non-archive file with NEVER_ZIP'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack'); + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); + + // WHEN + const staging = new AssetStaging(stack, 'Asset', { + sourcePath: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SUCCESS], + packaging: BundlePackaging.NEVER_ZIP, + }, + }); + + // THEN + const assembly = app.synth(); + test.deepEqual(fs.readdirSync(assembly.directory), [ + 'asset.08c328a7f9f7689be3c1c582577e74fb44deb70b200a5d3f2de168b2981f2a61', + 'asset.08c328a7f9f7689be3c1c582577e74fb44deb70b200a5d3f2de168b2981f2a61.txt', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + test.deepEqual(staging.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging.isArchive, false); + + test.done(); + }, + + 'throws with NEVER_ZIP and bundling that does not produce a single file'(test: Test) { + // GIVEN + const app = new App(); + const stack = new Stack(app, 'stack'); + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); + + // WHEN + test.throws(() => new AssetStaging(stack, 'Asset', { + sourcePath: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.MULTIPLE_FILES], + packaging: BundlePackaging.NEVER_ZIP, + }, + }), /Packaging was set to `NEVER_ZIP` but the bundling output did not produce a single file./); + + test.done(); }, }); From b445941b29289d6cf7f530a77e01a1d8f26b7cd4 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 16:32:05 +0100 Subject: [PATCH 04/20] README --- packages/@aws-cdk/aws-s3-assets/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index aab4c46d9c44d..d867acce2e04e 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -124,6 +124,26 @@ new assets.Asset(this, 'BundledAsset', { Although optional, it's recommended to provide a local bundling method which can greatly improve performance. +If the bundling output contains a single archive file (zip or jar) it will be uploaded +to S3 as-is and will not be zipped. Otherwise it will be zipped. + +This behavior can be changed by setting the `bundling.packaging` option: + +```ts +const asset = new assets.Asset(this, 'BundledAsset', { + path: '/path/to/asset', + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: ['command-that-produces-an-archive.sh'], + ], + packaging: BundlePackaging.ALWAYS_ZIP, // Bundling output will be zipped even though it produces a single archive file. + }, +}); +``` + +Use `BundlePackaging.NEVER_ZIP` if the bundling output contains a single file and you don't +want it to be zippped. + ## CloudFormation Resource Metadata > NOTE: This section is relevant for authors of AWS Resource Constructs. From a504e8b917f53e09ee7cbb7b52448e9266d46beb Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 16:37:50 +0100 Subject: [PATCH 05/20] JSDoc --- packages/@aws-cdk/core/lib/bundling.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 7e7dac88adfc3..17f1f7d7564b5 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -97,13 +97,14 @@ export interface BundlingOptions { */ export enum BundlePackaging { /** - * The bundling output will be zipped and uploaded to S3. + * The bundling output will always be zipped and uploaded to S3, regardless + * of its content. */ ALWAYS_ZIP = 'zip', /** * The bundling output will not be zipped. Bundling will fail if the bundling - * output doesn't contain a single archive (zip or jar) file. + * output doesn't contain a single file. */ NEVER_ZIP = 'no-zip', From 2b0a1fea5074a3560dd58d30f0a783cdd42d7b99 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 16 Feb 2021 16:41:02 +0100 Subject: [PATCH 06/20] minor --- packages/@aws-cdk/core/lib/asset-staging.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 0787595d1ed08..339c56f22ef8c 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -311,10 +311,10 @@ export class AssetStaging extends CoreConstruct { throw new Error('Packaging was set to `NEVER_ZIP` but the bundling output did not produce a single file.'); } - if (bundledFile) { + if (bundledFile) { // It's a single file const bundledExtension = path.extname(bundledFile).toLowerCase(); const isSingleArchive = ARCHIVE_EXTENSIONS.includes(bundledExtension); - if (packaging === BundlePackaging.NEVER_ZIP ||(packaging === BundlePackaging.AUTO && isSingleArchive)) { + if (packaging === BundlePackaging.NEVER_ZIP || (packaging === BundlePackaging.AUTO && isSingleArchive)) { this._packaging = FileAssetPackaging.FILE; this._isArchive = isSingleArchive; assetPath = bundledFile; From 10e43540c016a8feb296f098ba77d69a8f9fb088 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 09:50:41 +0100 Subject: [PATCH 07/20] Update packages/@aws-cdk/aws-s3-assets/README.md Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/aws-s3-assets/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index d867acce2e04e..9f3bd5171d04c 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -125,7 +125,7 @@ Although optional, it's recommended to provide a local bundling method which can greatly improve performance. If the bundling output contains a single archive file (zip or jar) it will be uploaded -to S3 as-is and will not be zipped. Otherwise it will be zipped. +to S3 as-is and will not be zipped. Otherwise the contents of the output directory will be zipped and the zip file will be uploaded to S3. This behavior can be changed by setting the `bundling.packaging` option: From 6586cbc20b560c0e4768f096f9bc6d6ac5972ca0 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 09:52:07 +0100 Subject: [PATCH 08/20] Update packages/@aws-cdk/aws-s3-assets/README.md Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/aws-s3-assets/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index 9f3bd5171d04c..57086a25dd170 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -135,7 +135,6 @@ const asset = new assets.Asset(this, 'BundledAsset', { bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: ['command-that-produces-an-archive.sh'], - ], packaging: BundlePackaging.ALWAYS_ZIP, // Bundling output will be zipped even though it produces a single archive file. }, }); From 777a405923609b3af6c91f32c007528c66996650 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 14:28:38 +0100 Subject: [PATCH 09/20] BundlingOutput --- packages/@aws-cdk/aws-s3-assets/README.md | 9 +-- packages/@aws-cdk/core/lib/asset-staging.ts | 74 ++++++++++++--------- packages/@aws-cdk/core/lib/bundling.ts | 25 ++++--- packages/@aws-cdk/core/test/staging.test.ts | 49 +++----------- 4 files changed, 70 insertions(+), 87 deletions(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index 57086a25dd170..4179096b84b22 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -125,9 +125,10 @@ Although optional, it's recommended to provide a local bundling method which can greatly improve performance. If the bundling output contains a single archive file (zip or jar) it will be uploaded -to S3 as-is and will not be zipped. Otherwise the contents of the output directory will be zipped and the zip file will be uploaded to S3. +to S3 as-is and will not be zipped. Otherwise the contents of the output directory will +be zipped and the zip file will be uploaded to S3. -This behavior can be changed by setting the `bundling.packaging` option: +This behavior can be changed by setting the `bundling.output` option: ```ts const asset = new assets.Asset(this, 'BundledAsset', { @@ -135,12 +136,12 @@ const asset = new assets.Asset(this, 'BundledAsset', { bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: ['command-that-produces-an-archive.sh'], - packaging: BundlePackaging.ALWAYS_ZIP, // Bundling output will be zipped even though it produces a single archive file. + packaging: BundlingOutput.NOT_ARCHIVED, // Bundling output will be zipped even though it produces a single archive file. }, }); ``` -Use `BundlePackaging.NEVER_ZIP` if the bundling output contains a single file and you don't +Use `BundlingOutput.ARCHIVED` if the bundling output contains a single file and you don't want it to be zippped. ## CloudFormation Resource Metadata diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 339c56f22ef8c..7cd8466c32db9 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -6,7 +6,7 @@ import { Construct } from 'constructs'; import * as fs from 'fs-extra'; import * as minimatch from 'minimatch'; import { AssetHashType, AssetOptions, FileAssetPackaging } from './assets'; -import { BundlingOptions, BundlePackaging } from './bundling'; +import { BundlingOptions, BundlingOutput } from './bundling'; import { FileSystem, FingerprintOptions } from './fs'; import { Names } from './names'; import { Cache } from './private/cache'; @@ -300,34 +300,16 @@ export class AssetStaging extends CoreConstruct { const bundleDir = this.determineBundleDir(this.assetOutdir, assetHash); this.bundle(bundling, bundleDir); - let assetPath = bundleDir; - let extension: string | undefined; - - const packaging = bundling.packaging ?? BundlePackaging.AUTO; - if (packaging !== BundlePackaging.ALWAYS_ZIP) { - // Check whether bundling resulted in a single file - const bundledFile = singleFile(bundleDir); - if (packaging === BundlePackaging.NEVER_ZIP && !bundledFile) { - throw new Error('Packaging was set to `NEVER_ZIP` but the bundling output did not produce a single file.'); - } - - if (bundledFile) { // It's a single file - const bundledExtension = path.extname(bundledFile).toLowerCase(); - const isSingleArchive = ARCHIVE_EXTENSIONS.includes(bundledExtension); - if (packaging === BundlePackaging.NEVER_ZIP || (packaging === BundlePackaging.AUTO && isSingleArchive)) { - this._packaging = FileAssetPackaging.FILE; - this._isArchive = isSingleArchive; - assetPath = bundledFile; - extension = bundledExtension; - } - } - } + // Check bundling output content and determine if we will need to archive + const bundlingOutput = bundling.output ?? BundlingOutput.AUTO_DISCOVER; + const bundledAsset = this.determineBundledAsset(bundlingOutput, bundleDir); + this._packaging = bundledAsset.packaging; // Calculate assetHash afterwards if we still must - assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, assetPath); - const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, extension)); + assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, bundledAsset.path); + const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, bundledAsset.extension)); - this.stageAsset(assetPath, stagedPath, 'move'); + this.stageAsset(bundledAsset.path, stagedPath, 'move'); return { assetHash, stagedPath }; } @@ -497,6 +479,33 @@ export class AssetStaging extends CoreConstruct { throw new Error('Unknown asset hash type.'); } } + + private determineBundledAsset(bundlingOutput: BundlingOutput, bundleDir: string): BundledAsset { + let archiveFile: string | undefined; + + switch (bundlingOutput) { + case BundlingOutput.NOT_ARCHIVED: + return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; + case BundlingOutput.ARCHIVED: + archiveFile = singleArchiveFile(bundleDir); + if (!archiveFile) { + throw new Error('Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`'); + } + return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; + case BundlingOutput.AUTO_DISCOVER: + archiveFile = singleArchiveFile(bundleDir); + if (archiveFile) { + return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; + } + return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; + } + } +} + +interface BundledAsset { + path: string, + packaging: FileAssetPackaging, + extension?: string } function renderAssetFilename(assetHash: string, extension = '') { @@ -548,17 +557,22 @@ function sortObject(object: { [key: string]: any }): { [key: string]: any } { } /** - * Returns the single file of a directory or undefined + * Returns the single archive file of a directory or undefined */ -function singleFile(directory: string): string | undefined { +function singleArchiveFile(directory: string): string | undefined { + if (!fs.existsSync(directory)) { + throw new Error(`Directory ${directory} does not exist.`); + } + if (!fs.statSync(directory).isDirectory()) { - return undefined; + throw new Error(`${directory} is not a directory.`); } const content = fs.readdirSync(directory); if (content.length === 1) { const file = path.join(directory, content[0]); - if (fs.statSync(file).isFile()) { + const extension = path.extname(content[0]).toLowerCase(); + if (fs.statSync(file).isFile() && ARCHIVE_EXTENSIONS.includes(extension)) { return file; } } diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 17f1f7d7564b5..fce1a4db2dd02 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -81,38 +81,37 @@ export interface BundlingOptions { readonly local?: ILocalBundling; /** - * The type of packaging to apply on the bundling output. + * The type of output that this bundling operation is producing. * - * @default BundlePackaging.AUTO + * @default BundlingOutput.AUTO_DISCOVER * * @experimental */ - readonly packaging?: BundlePackaging; + readonly output?: BundlingOutput; } /** - * The type of packaging to apply on the bundled asset. + * The type of output that a bundling operation is producing. * * @experimental */ -export enum BundlePackaging { +export enum BundlingOutput { /** - * The bundling output will always be zipped and uploaded to S3, regardless - * of its content. + * The bundling output is aready archived. It will be uploaded to S3 as-is. */ - ALWAYS_ZIP = 'zip', + ARCHIVED = 'archived', /** - * The bundling output will not be zipped. Bundling will fail if the bundling - * output doesn't contain a single file. + * The bundling output is not archived. It will be archived and then uploaded + * to S3. */ - NEVER_ZIP = 'no-zip', + NOT_ARCHIVED = 'not-archived', /** * If the bundling output contains a single archive file (zip or jar) it will - * not be zipped. Otherwise it will be zipped. + * not be zipped. Otherwise the bundling output will be zipped. */ - AUTO = 'auto' + AUTO_DISCOVER = 'auto-discover', } /** diff --git a/packages/@aws-cdk/core/test/staging.test.ts b/packages/@aws-cdk/core/test/staging.test.ts index 9f108391c4657..4cb97acfd4353 100644 --- a/packages/@aws-cdk/core/test/staging.test.ts +++ b/packages/@aws-cdk/core/test/staging.test.ts @@ -5,7 +5,7 @@ import * as cxapi from '@aws-cdk/cx-api'; import * as fs from 'fs-extra'; import { nodeunitShim, Test } from 'nodeunit-shim'; import * as sinon from 'sinon'; -import { App, AssetHashType, AssetStaging, BundlePackaging, BundlingDockerImage, BundlingOptions, FileSystem, Stack, Stage } from '../lib'; +import { App, AssetHashType, AssetStaging, BundlingDockerImage, BundlingOptions, BundlingOutput, FileSystem, Stack, Stage } from '../lib'; const STUB_INPUT_FILE = '/tmp/docker-stub.input'; const STUB_INPUT_CONCAT_FILE = '/tmp/docker-stub.input.concat'; @@ -819,7 +819,7 @@ nodeunitShim({ test.done(); }, - 'bundling that produces a single archive file'(test: Test) { + 'bundling that produces a single archive file is autodiscovered'(test: Test) { // GIVEN const app = new App(); const stack = new Stack(app, 'stack'); @@ -844,13 +844,14 @@ nodeunitShim({ 'stack.template.json', 'tree.json', ]); + test.equal(fs.readdirSync(path.join(assembly.directory, 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48')).length, 0); // empty bundle dir test.deepEqual(staging.packaging, FileAssetPackaging.FILE); test.deepEqual(staging.isArchive, true); test.done(); }, - 'bundling that produces a single archive file with ALWAYS_ZIP'(test: Test) { + 'bundling that produces a single archive file with NOT_ARCHIVED'(test: Test) { // GIVEN const app = new App(); const stack = new Stack(app, 'stack'); @@ -862,14 +863,14 @@ nodeunitShim({ bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: [DockerStubCommand.SINGLE_ARCHIVE], - packaging: BundlePackaging.ALWAYS_ZIP, + output: BundlingOutput.NOT_ARCHIVED, }, }); // THEN const assembly = app.synth(); test.deepEqual(fs.readdirSync(assembly.directory), [ - 'asset.d6ed33ece892ac6be1b5f8151f83361aa8c044587d5431c4803cc9cadbc657cf', + 'asset.d68f7bac29656de963ed259858f3063991e0632c2ebca437fe03e96e955a6b49', 'cdk.out', 'manifest.json', 'stack.template.json', @@ -881,39 +882,7 @@ nodeunitShim({ test.done(); }, - 'bundling that produces a single non-archive file with NEVER_ZIP'(test: Test) { - // GIVEN - const app = new App(); - const stack = new Stack(app, 'stack'); - const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); - - // WHEN - const staging = new AssetStaging(stack, 'Asset', { - sourcePath: directory, - bundling: { - image: BundlingDockerImage.fromRegistry('alpine'), - command: [DockerStubCommand.SUCCESS], - packaging: BundlePackaging.NEVER_ZIP, - }, - }); - - // THEN - const assembly = app.synth(); - test.deepEqual(fs.readdirSync(assembly.directory), [ - 'asset.08c328a7f9f7689be3c1c582577e74fb44deb70b200a5d3f2de168b2981f2a61', - 'asset.08c328a7f9f7689be3c1c582577e74fb44deb70b200a5d3f2de168b2981f2a61.txt', - 'cdk.out', - 'manifest.json', - 'stack.template.json', - 'tree.json', - ]); - test.deepEqual(staging.packaging, FileAssetPackaging.FILE); - test.deepEqual(staging.isArchive, false); - - test.done(); - }, - - 'throws with NEVER_ZIP and bundling that does not produce a single file'(test: Test) { + 'throws with ARCHIVED and bundling that does not produce a single archive file'(test: Test) { // GIVEN const app = new App(); const stack = new Stack(app, 'stack'); @@ -925,9 +894,9 @@ nodeunitShim({ bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: [DockerStubCommand.MULTIPLE_FILES], - packaging: BundlePackaging.NEVER_ZIP, + output: BundlingOutput.ARCHIVED, }, - }), /Packaging was set to `NEVER_ZIP` but the bundling output did not produce a single file./); + }), /Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`/); test.done(); From 63f2ff879d9e5180938dd0c669a0d6ef9592e954 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 14:33:37 +0100 Subject: [PATCH 10/20] move to function --- packages/@aws-cdk/core/lib/asset-staging.ts | 60 +++++++++++---------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 7cd8466c32db9..831e1c7288f94 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -302,7 +302,7 @@ export class AssetStaging extends CoreConstruct { // Check bundling output content and determine if we will need to archive const bundlingOutput = bundling.output ?? BundlingOutput.AUTO_DISCOVER; - const bundledAsset = this.determineBundledAsset(bundlingOutput, bundleDir); + const bundledAsset = determineBundledAsset(bundleDir, bundlingOutput); this._packaging = bundledAsset.packaging; // Calculate assetHash afterwards if we still must @@ -479,33 +479,6 @@ export class AssetStaging extends CoreConstruct { throw new Error('Unknown asset hash type.'); } } - - private determineBundledAsset(bundlingOutput: BundlingOutput, bundleDir: string): BundledAsset { - let archiveFile: string | undefined; - - switch (bundlingOutput) { - case BundlingOutput.NOT_ARCHIVED: - return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; - case BundlingOutput.ARCHIVED: - archiveFile = singleArchiveFile(bundleDir); - if (!archiveFile) { - throw new Error('Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`'); - } - return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; - case BundlingOutput.AUTO_DISCOVER: - archiveFile = singleArchiveFile(bundleDir); - if (archiveFile) { - return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; - } - return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; - } - } -} - -interface BundledAsset { - path: string, - packaging: FileAssetPackaging, - extension?: string } function renderAssetFilename(assetHash: string, extension = '') { @@ -579,3 +552,34 @@ function singleArchiveFile(directory: string): string | undefined { return undefined; } + +interface BundledAsset { + path: string, + packaging: FileAssetPackaging, + extension?: string +} + +/** + * Returns the bundled asset to use based on the content of the bundle directory + * and the type of output. + */ +function determineBundledAsset(bundleDir: string, bundlingOutput: BundlingOutput): BundledAsset { + let archiveFile: string | undefined; + + switch (bundlingOutput) { + case BundlingOutput.NOT_ARCHIVED: + return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; + case BundlingOutput.ARCHIVED: + archiveFile = singleArchiveFile(bundleDir); + if (!archiveFile) { + throw new Error('Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`'); + } + return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; + case BundlingOutput.AUTO_DISCOVER: + archiveFile = singleArchiveFile(bundleDir); + if (archiveFile) { + return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; + } + return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; + } +} From 823f417fb589fc827628097b641fee9d06aba5ee Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 16:27:43 +0100 Subject: [PATCH 11/20] Update packages/@aws-cdk/aws-s3-assets/README.md Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/aws-s3-assets/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index 4179096b84b22..0db0406a940e4 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -136,7 +136,7 @@ const asset = new assets.Asset(this, 'BundledAsset', { bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: ['command-that-produces-an-archive.sh'], - packaging: BundlingOutput.NOT_ARCHIVED, // Bundling output will be zipped even though it produces a single archive file. + output: BundlingOutput.NOT_ARCHIVED, // Bundling output will be zipped even though it produces a single archive file. }, }); ``` From e6c60d1d97970c0ad9c50419c0f65d195affd4bd Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 16:29:08 +0100 Subject: [PATCH 12/20] Update packages/@aws-cdk/core/lib/bundling.ts Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/core/lib/bundling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index fce1a4db2dd02..24ab837b2613c 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -97,7 +97,7 @@ export interface BundlingOptions { */ export enum BundlingOutput { /** - * The bundling output is aready archived. It will be uploaded to S3 as-is. + * The bundling output directory includes a single .zip or .jar file which will be used as the final bundle. If the output directory does not include exactly a single archive, bundling will fail. */ ARCHIVED = 'archived', From 576d76fe9e20e1bac3b10e80aad95bd8e7a3a891 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 16:29:38 +0100 Subject: [PATCH 13/20] Update packages/@aws-cdk/core/lib/bundling.ts Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/core/lib/bundling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 24ab837b2613c..6def74c6e1aa5 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -102,7 +102,7 @@ export enum BundlingOutput { ARCHIVED = 'archived', /** - * The bundling output is not archived. It will be archived and then uploaded + * The bundling output directory contains one or more files which will be archived and uploaded as a .zip file * to S3. */ NOT_ARCHIVED = 'not-archived', From 617f4dcd8ef4d4635c9c2f33921d27eb9efdf8a8 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 16:29:47 +0100 Subject: [PATCH 14/20] Update packages/@aws-cdk/core/lib/bundling.ts Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/core/lib/bundling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 6def74c6e1aa5..9da957dcca10f 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -108,7 +108,7 @@ export enum BundlingOutput { NOT_ARCHIVED = 'not-archived', /** - * If the bundling output contains a single archive file (zip or jar) it will + * If the bundling output directory contains a single archive file (zip or jar) it will * not be zipped. Otherwise the bundling output will be zipped. */ AUTO_DISCOVER = 'auto-discover', From e0828b2187c7b408132350e0bfa2686b10367e40 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 16:44:47 +0100 Subject: [PATCH 15/20] refactor determineBundledAsset --- packages/@aws-cdk/core/lib/asset-staging.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 831e1c7288f94..04ef8f70be096 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -564,22 +564,20 @@ interface BundledAsset { * and the type of output. */ function determineBundledAsset(bundleDir: string, bundlingOutput: BundlingOutput): BundledAsset { - let archiveFile: string | undefined; + const archiveFile = singleArchiveFile(bundleDir); + // auto-discover means that if there is an archive file, we take it as the + // bundle, otherwise, we will archive here. + if (bundlingOutput === BundlingOutput.AUTO_DISCOVER) { + bundlingOutput = archiveFile ? BundlingOutput.ARCHIVED : BundlingOutput.NOT_ARCHIVED; + } switch (bundlingOutput) { case BundlingOutput.NOT_ARCHIVED: return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; case BundlingOutput.ARCHIVED: - archiveFile = singleArchiveFile(bundleDir); if (!archiveFile) { throw new Error('Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`'); } return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; - case BundlingOutput.AUTO_DISCOVER: - archiveFile = singleArchiveFile(bundleDir); - if (archiveFile) { - return { path: archiveFile, packaging: FileAssetPackaging.FILE, extension: path.extname(archiveFile) }; - } - return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; } } From 65d4abb76f14164a46ce5c61fb56b44f21bcefdd Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 17:03:39 +0100 Subject: [PATCH 16/20] JSDoc and README --- packages/@aws-cdk/aws-s3-assets/README.md | 13 +++++++------ packages/@aws-cdk/core/lib/asset-staging.ts | 1 + packages/@aws-cdk/core/lib/bundling.ts | 12 +++++++----- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index 0db0406a940e4..2b2ab1bda8dad 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -124,11 +124,12 @@ new assets.Asset(this, 'BundledAsset', { Although optional, it's recommended to provide a local bundling method which can greatly improve performance. -If the bundling output contains a single archive file (zip or jar) it will be uploaded -to S3 as-is and will not be zipped. Otherwise the contents of the output directory will -be zipped and the zip file will be uploaded to S3. +If the bundling output contains a single archive file (zip or jar) it will be +uploaded to S3 as-is and will not be zipped. Otherwise the contents of the +output directory will be zipped and the zip file will be uploaded to S3. This +is the default behavior for `bundling.output` (`BundlingOutput.AUTO_DISCOVER`). -This behavior can be changed by setting the `bundling.output` option: +Use `BundlingOutput.NOT_ARCHIVED` if the bundling output must always be zipped: ```ts const asset = new assets.Asset(this, 'BundledAsset', { @@ -141,8 +142,8 @@ const asset = new assets.Asset(this, 'BundledAsset', { }); ``` -Use `BundlingOutput.ARCHIVED` if the bundling output contains a single file and you don't -want it to be zippped. +Use `BundlingOutput.ARCHIVED` if the bundling output contains a single archive file and +you don't want it to be zippped. ## CloudFormation Resource Metadata diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 04ef8f70be096..88734e8ae58b2 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -565,6 +565,7 @@ interface BundledAsset { */ function determineBundledAsset(bundleDir: string, bundlingOutput: BundlingOutput): BundledAsset { const archiveFile = singleArchiveFile(bundleDir); + // auto-discover means that if there is an archive file, we take it as the // bundle, otherwise, we will archive here. if (bundlingOutput === BundlingOutput.AUTO_DISCOVER) { diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 9da957dcca10f..794a9f3ee9500 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -97,19 +97,21 @@ export interface BundlingOptions { */ export enum BundlingOutput { /** - * The bundling output directory includes a single .zip or .jar file which will be used as the final bundle. If the output directory does not include exactly a single archive, bundling will fail. + * The bundling output directory includes a single .zip or .jar file which + * will be used as the final bundle. If the output directory does not + * include exactly a single archive, bundling will fail. */ ARCHIVED = 'archived', /** - * The bundling output directory contains one or more files which will be archived and uploaded as a .zip file - * to S3. + * The bundling output directory contains one or more files which will be + * archived and uploaded as a .zip file to S3. */ NOT_ARCHIVED = 'not-archived', /** - * If the bundling output directory contains a single archive file (zip or jar) it will - * not be zipped. Otherwise the bundling output will be zipped. + * If the bundling output directory contains a single archive file (zip or jar) + * it will not be zipped. Otherwise the bundling output will be zipped. */ AUTO_DISCOVER = 'auto-discover', } From e9fb679eb15d83df30f9f5b855c305bba16bf7ee Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 17 Feb 2021 17:25:14 +0100 Subject: [PATCH 17/20] outputType --- packages/@aws-cdk/aws-s3-assets/README.md | 4 ++-- packages/@aws-cdk/core/lib/asset-staging.ts | 12 ++++++------ packages/@aws-cdk/core/lib/bundling.ts | 2 +- packages/@aws-cdk/core/test/staging.test.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/@aws-cdk/aws-s3-assets/README.md b/packages/@aws-cdk/aws-s3-assets/README.md index 2b2ab1bda8dad..f2583b7c10a24 100644 --- a/packages/@aws-cdk/aws-s3-assets/README.md +++ b/packages/@aws-cdk/aws-s3-assets/README.md @@ -127,7 +127,7 @@ greatly improve performance. If the bundling output contains a single archive file (zip or jar) it will be uploaded to S3 as-is and will not be zipped. Otherwise the contents of the output directory will be zipped and the zip file will be uploaded to S3. This -is the default behavior for `bundling.output` (`BundlingOutput.AUTO_DISCOVER`). +is the default behavior for `bundling.outputType` (`BundlingOutput.AUTO_DISCOVER`). Use `BundlingOutput.NOT_ARCHIVED` if the bundling output must always be zipped: @@ -137,7 +137,7 @@ const asset = new assets.Asset(this, 'BundledAsset', { bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: ['command-that-produces-an-archive.sh'], - output: BundlingOutput.NOT_ARCHIVED, // Bundling output will be zipped even though it produces a single archive file. + outputType: BundlingOutput.NOT_ARCHIVED, // Bundling output will be zipped even though it produces a single archive file. }, }); ``` diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 88734e8ae58b2..17fd89781004a 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -301,8 +301,8 @@ export class AssetStaging extends CoreConstruct { this.bundle(bundling, bundleDir); // Check bundling output content and determine if we will need to archive - const bundlingOutput = bundling.output ?? BundlingOutput.AUTO_DISCOVER; - const bundledAsset = determineBundledAsset(bundleDir, bundlingOutput); + const bundlingOutputType = bundling.outputType ?? BundlingOutput.AUTO_DISCOVER; + const bundledAsset = determineBundledAsset(bundleDir, bundlingOutputType); this._packaging = bundledAsset.packaging; // Calculate assetHash afterwards if we still must @@ -563,16 +563,16 @@ interface BundledAsset { * Returns the bundled asset to use based on the content of the bundle directory * and the type of output. */ -function determineBundledAsset(bundleDir: string, bundlingOutput: BundlingOutput): BundledAsset { +function determineBundledAsset(bundleDir: string, outputType: BundlingOutput): BundledAsset { const archiveFile = singleArchiveFile(bundleDir); // auto-discover means that if there is an archive file, we take it as the // bundle, otherwise, we will archive here. - if (bundlingOutput === BundlingOutput.AUTO_DISCOVER) { - bundlingOutput = archiveFile ? BundlingOutput.ARCHIVED : BundlingOutput.NOT_ARCHIVED; + if (outputType === BundlingOutput.AUTO_DISCOVER) { + outputType = archiveFile ? BundlingOutput.ARCHIVED : BundlingOutput.NOT_ARCHIVED; } - switch (bundlingOutput) { + switch (outputType) { case BundlingOutput.NOT_ARCHIVED: return { path: bundleDir, packaging: FileAssetPackaging.ZIP_DIRECTORY }; case BundlingOutput.ARCHIVED: diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 794a9f3ee9500..57885ceeca05c 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -87,7 +87,7 @@ export interface BundlingOptions { * * @experimental */ - readonly output?: BundlingOutput; + readonly outputType?: BundlingOutput; } /** diff --git a/packages/@aws-cdk/core/test/staging.test.ts b/packages/@aws-cdk/core/test/staging.test.ts index 4cb97acfd4353..76bf74f9cffd7 100644 --- a/packages/@aws-cdk/core/test/staging.test.ts +++ b/packages/@aws-cdk/core/test/staging.test.ts @@ -863,14 +863,14 @@ nodeunitShim({ bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: [DockerStubCommand.SINGLE_ARCHIVE], - output: BundlingOutput.NOT_ARCHIVED, + outputType: BundlingOutput.NOT_ARCHIVED, }, }); // THEN const assembly = app.synth(); test.deepEqual(fs.readdirSync(assembly.directory), [ - 'asset.d68f7bac29656de963ed259858f3063991e0632c2ebca437fe03e96e955a6b49', + 'asset.86ec07746e1d859290cfd8b9c648e581555649c75f51f741f11e22cab6775abc', 'cdk.out', 'manifest.json', 'stack.template.json', @@ -894,7 +894,7 @@ nodeunitShim({ bundling: { image: BundlingDockerImage.fromRegistry('alpine'), command: [DockerStubCommand.MULTIPLE_FILES], - output: BundlingOutput.ARCHIVED, + outputType: BundlingOutput.ARCHIVED, }, }), /Bundling output directory is expected to include only a single .zip or .jar file when `output` is set to `ARCHIVED`/); From 7b3d829b3db6aacbc0372855128c3e5a8187d78d Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Fri, 19 Feb 2021 11:53:10 +0100 Subject: [PATCH 18/20] correctly cache packaging type --- packages/@aws-cdk/core/lib/asset-staging.ts | 78 ++++++++++++++------- packages/@aws-cdk/core/test/staging.test.ts | 50 +++++++++++++ 2 files changed, 104 insertions(+), 24 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 17fd89781004a..6a34bd9b4b1ac 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -32,6 +32,16 @@ interface StagedAsset { * The hash we used previously */ readonly assetHash: string; + + /** + * The packaging of the asset + */ + readonly packaging: FileAssetPackaging, + + /** + * Whether this asset is an archive + */ + readonly isArchive: boolean; } /** @@ -126,6 +136,16 @@ export class AssetStaging extends CoreConstruct { */ public readonly assetHash: string; + /** + * How this asset should be packaged. + */ + public readonly packaging: FileAssetPackaging; + + /** + * Whether this asset is an archive (zip or jar). + */ + public readonly isArchive: boolean; + private readonly fingerprintOptions: FingerprintOptions; private readonly hashType: AssetHashType; @@ -140,8 +160,7 @@ export class AssetStaging extends CoreConstruct { private readonly cacheKey: string; - private _packaging = FileAssetPackaging.ZIP_DIRECTORY; - private _isArchive = true; + private readonly sourceStats: fs.Stats; constructor(scope: Construct, id: string, props: AssetStagingProps) { super(scope, id); @@ -149,6 +168,12 @@ export class AssetStaging extends CoreConstruct { this.sourcePath = path.resolve(props.sourcePath); this.fingerprintOptions = props; + if (!fs.existsSync(this.sourcePath)) { + throw new Error(`Cannot find asset at ${this.sourcePath}`); + } + + this.sourceStats = fs.statSync(this.sourcePath); + const outdir = Stage.of(this)?.assetOutdir; if (!outdir) { throw new Error('unable to determine cloud assembly asset output directory. Assets must be defined indirectly within a "Stage" or an "App" scope'); @@ -197,6 +222,8 @@ export class AssetStaging extends CoreConstruct { this.stagedPath = staged.stagedPath; this.absoluteStagedPath = staged.stagedPath; this.assetHash = staged.assetHash; + this.packaging = staged.packaging; + this.isArchive = staged.isArchive; } /** @@ -208,20 +235,6 @@ export class AssetStaging extends CoreConstruct { return this.assetHash; } - /** - * How this asset should be packaged. - */ - public get packaging(): FileAssetPackaging { - return this._packaging; - } - - /** - * Whether this asset is an archive (zip or jar). - */ - public get isArchive(): boolean { - return this._isArchive; - } - /** * Return the path to the staged asset, relative to the Cloud Assembly (manifest) directory of the given stack * @@ -267,8 +280,18 @@ export class AssetStaging extends CoreConstruct { ? this.sourcePath : path.resolve(this.assetOutdir, renderAssetFilename(assetHash, path.extname(this.sourcePath))); + if (!this.sourceStats.isDirectory() && !this.sourceStats.isFile()) { + throw new Error(`Asset ${this.sourcePath} is expected to be either a directory or a regular file`); + } + this.stageAsset(this.sourcePath, stagedPath, 'copy'); - return { assetHash, stagedPath }; + + return { + assetHash, + stagedPath, + packaging: this.sourceStats.isDirectory() ? FileAssetPackaging.ZIP_DIRECTORY : FileAssetPackaging.FILE, + isArchive: this.sourceStats.isDirectory() || ARCHIVE_EXTENSIONS.includes(path.extname(this.sourcePath).toLowerCase()), + }; } /** @@ -277,6 +300,10 @@ export class AssetStaging extends CoreConstruct { * Optionally skip, in which case we pretend we did something but we don't really. */ private stageByBundling(bundling: BundlingOptions, skip: boolean): StagedAsset { + if (!this.sourceStats.isDirectory()) { + throw new Error(`Asset ${this.sourcePath} is expected to be a directory when bundling`); + } + if (skip) { // We should have bundled, but didn't to save time. Still pretend to have a hash. // If the asset uses OUTPUT or BUNDLE, we use a CUSTOM hash to avoid fingerprinting @@ -289,6 +316,8 @@ export class AssetStaging extends CoreConstruct { return { assetHash: this.calculateHash(hashType, bundling), stagedPath: this.sourcePath, + packaging: FileAssetPackaging.ZIP_DIRECTORY, + isArchive: true, }; } @@ -303,14 +332,18 @@ export class AssetStaging extends CoreConstruct { // Check bundling output content and determine if we will need to archive const bundlingOutputType = bundling.outputType ?? BundlingOutput.AUTO_DISCOVER; const bundledAsset = determineBundledAsset(bundleDir, bundlingOutputType); - this._packaging = bundledAsset.packaging; // Calculate assetHash afterwards if we still must assetHash = assetHash ?? this.calculateHash(this.hashType, bundling, bundledAsset.path); const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, bundledAsset.extension)); this.stageAsset(bundledAsset.path, stagedPath, 'move'); - return { assetHash, stagedPath }; + return { + assetHash, + stagedPath, + packaging: bundledAsset.packaging, + isArchive: true, // bundling always produces an archive + }; } /** @@ -344,12 +377,9 @@ export class AssetStaging extends CoreConstruct { } // Copy file/directory to staging directory - const stat = fs.statSync(sourcePath); - if (stat.isFile()) { + if (this.sourceStats.isFile()) { fs.copyFileSync(sourcePath, targetPath); - this._packaging = FileAssetPackaging.FILE; - this._isArchive = ARCHIVE_EXTENSIONS.includes(path.extname(sourcePath).toLowerCase()); - } else if (stat.isDirectory()) { + } else if (this.sourceStats.isDirectory()) { fs.mkdirSync(targetPath); FileSystem.copyDirectory(sourcePath, targetPath, this.fingerprintOptions); } else { diff --git a/packages/@aws-cdk/core/test/staging.test.ts b/packages/@aws-cdk/core/test/staging.test.ts index 76bf74f9cffd7..ee87780a0957e 100644 --- a/packages/@aws-cdk/core/test/staging.test.ts +++ b/packages/@aws-cdk/core/test/staging.test.ts @@ -71,6 +71,56 @@ nodeunitShim({ test.done(); }, + 'asset packaging type is correct when staging is skipped because of memory cache'(test: Test) { + // GIVEN + const stack = new Stack(); + const sourcePath = path.join(__dirname, 'archive', 'archive.zip'); + + // WHEN + const staging1 = new AssetStaging(stack, 's1', { sourcePath }); + const staging2 = new AssetStaging(stack, 's2', { sourcePath }); + + test.deepEqual(staging1.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging1.isArchive, true); + test.deepEqual(staging2.packaging, staging1.packaging); + test.deepEqual(staging2.isArchive, staging1.isArchive); + test.done(); + }, + + 'asset packaging type is correct when staging is skipped because of disk cache'(test: Test) { + // GIVEN + const TEST_OUTDIR = path.join(__dirname, 'cdk.out'); + if (fs.existsSync(TEST_OUTDIR)) { + fs.removeSync(TEST_OUTDIR); + } + + const sourcePath = path.join(__dirname, 'archive', 'archive.zip'); + + const app1 = new App({ outdir: TEST_OUTDIR }); + const stack1 = new Stack(app1, 'Stack'); + + const app2 = new App({ outdir: TEST_OUTDIR }); // same OUTDIR + const stack2 = new Stack(app2, 'stack'); + + // WHEN + const staging1 = new AssetStaging(stack1, 'Asset', { sourcePath }); + + // Now clear asset hash cache to show that during the second staging + // even though the asset is already available on disk it will correctly + // be considered as a FileAssetPackaging.FILE. + AssetStaging.clearAssetHashCache(); + + const staging2 = new AssetStaging(stack2, 'Asset', { sourcePath }); + + // THEN + test.deepEqual(staging1.packaging, FileAssetPackaging.FILE); + test.deepEqual(staging1.isArchive, true); + test.deepEqual(staging2.packaging, staging1.packaging); + test.deepEqual(staging2.isArchive, staging1.isArchive); + + test.done(); + }, + 'staging of a non-archive file correctly sets packaging and isArchive'(test: Test) { // GIVEN const stack = new Stack(); From 91ff6908eb2e140e57fa75e712ab1b22e9371896 Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Fri, 19 Feb 2021 12:01:10 +0100 Subject: [PATCH 19/20] clean allowed-breaking-changes --- allowed-breaking-changes.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/allowed-breaking-changes.txt b/allowed-breaking-changes.txt index 964bb4d5c7712..2ca2ca5b6067f 100644 --- a/allowed-breaking-changes.txt +++ b/allowed-breaking-changes.txt @@ -56,10 +56,3 @@ incompatible-argument:@aws-cdk/aws-ecs.TaskDefinition.addVolume # We made properties optional and it's really fine but our differ doesn't think so. weakened:@aws-cdk/cloud-assembly-schema.DockerImageSource weakened:@aws-cdk/cloud-assembly-schema.FileSource - -# https://github.com/aws/aws-cdk/pull/13145 -removed:@aws-cdk/core.AssetStaging.isArchive -removed:@aws-cdk/core.AssetStaging.packaging -removed:@aws-cdk/core.BundlingOutput -removed:@aws-cdk/core.BundlingOptions.outputType - From 435a6a6e21aff5057b94375515e8f21ea278bcde Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Wed, 24 Feb 2021 11:26:02 +0100 Subject: [PATCH 20/20] Update packages/@aws-cdk/core/lib/bundling.ts Co-authored-by: Elad Ben-Israel --- packages/@aws-cdk/core/lib/bundling.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index 57885ceeca05c..fab6abf000cf0 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -111,7 +111,7 @@ export enum BundlingOutput { /** * If the bundling output directory contains a single archive file (zip or jar) - * it will not be zipped. Otherwise the bundling output will be zipped. + * it will be used as the bundle output as-is. Otherwise all the files in the bundling output directory will be zipped. */ AUTO_DISCOVER = 'auto-discover', }