From 4b3cc60095f7c4fccf90837ce2265bad1063b79d Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Mon, 26 Apr 2021 10:50:43 +0200 Subject: [PATCH] fix(core): cannot determine packaging when bundling that produces an archive is skipped Bundling is skipped when the bundling directory already exists on disk (cache). If it previously produced a single archive file that has been moved to the staging directory the current logic either failed to determine the correct packaging type or threw because it expected the bundling directory to include a single archive file. Fix it by "touching" the archive file in the bundling directory after it has been moved to the staging directory. Fixes #14369 --- packages/@aws-cdk/core/lib/asset-staging.ts | 9 ++++ packages/@aws-cdk/core/test/staging.test.ts | 54 ++++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 09820293b63ec..44ab0de0bdd5d 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -336,6 +336,15 @@ export class AssetStaging extends CoreConstruct { const stagedPath = path.resolve(this.assetOutdir, renderAssetFilename(assetHash, bundledAsset.extension)); this.stageAsset(bundledAsset.path, stagedPath, 'move'); + + // If bundling produced a single archive file we "touch" this file in the bundling + // directory after it has been moved to the staging directory. This way if bundling + // is skipped because the bundling directory already exists we can still determine + // the correct packaging type. + if (bundledAsset.packaging === FileAssetPackaging.FILE) { + fs.closeSync(fs.openSync(bundledAsset.path, 'w')); + } + return { assetHash, stagedPath, diff --git a/packages/@aws-cdk/core/test/staging.test.ts b/packages/@aws-cdk/core/test/staging.test.ts index ee87780a0957e..e492f0a2dce88 100644 --- a/packages/@aws-cdk/core/test/staging.test.ts +++ b/packages/@aws-cdk/core/test/staging.test.ts @@ -887,20 +887,70 @@ nodeunitShim({ // THEN const assembly = app.synth(); test.deepEqual(fs.readdirSync(assembly.directory), [ - 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48', // this is the bundle dir but it's empty + 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48', // this is the bundle dir 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48.zip', 'cdk.out', 'manifest.json', 'stack.template.json', 'tree.json', ]); - test.equal(fs.readdirSync(path.join(assembly.directory, 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48')).length, 0); // empty bundle dir + test.deepEqual(fs.readdirSync(path.join(assembly.directory, 'asset.f43148c61174f444925231b5849b468f21e93b5d1469cd07c53625ffd039ef48')), [ + 'test.zip', // bundle dir with "touched" bundled output file + ]); test.deepEqual(staging.packaging, FileAssetPackaging.FILE); test.deepEqual(staging.isArchive, true); test.done(); }, + 'bundling that produces a single archive file with disk cache'(test: Test) { + // GIVEN + const TEST_OUTDIR = path.join(__dirname, 'cdk.out'); + if (fs.existsSync(TEST_OUTDIR)) { + fs.removeSync(TEST_OUTDIR); + } + + const directory = path.join(__dirname, 'fs', 'fixtures', 'test1'); + + 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: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_ARCHIVE], + outputType: BundlingOutput.ARCHIVED, + }, + }); + + // Now clear asset hash cache to show that during the second staging + // even though bundling is skipped it will correctly be considered + // as a FileAssetPackaging.FILE. + AssetStaging.clearAssetHashCache(); + + const staging2 = new AssetStaging(stack2, 'Asset', { + sourcePath: directory, + bundling: { + image: BundlingDockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_ARCHIVE], + outputType: BundlingOutput.ARCHIVED, + }, + }); + + // 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(); + }, + 'bundling that produces a single archive file with NOT_ARCHIVED'(test: Test) { // GIVEN const app = new App();