From 9449634a468b37106c4388a885d7cd81fd4466ab Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Thu, 20 Jun 2024 21:40:34 +0900 Subject: [PATCH 1/5] fix: upload assets with no extension --- ...efaultTestDeployAssertE3E7D2A4.assets.json | 2 +- .../main | 0 ...111e9aa20db0d42e929187a1b592a593ea713noext | 1 + .../cdk-integ-assets-bundling.assets.json | 19 +++++- .../cdk.out | 2 +- .../integ.json | 2 +- .../manifest.json | 4 +- .../tree.json | 31 ++++++++- .../test/integ.assets.file-bundling.lit.ts | 11 ++++ .../aws-cdk-lib/core/lib/asset-staging.ts | 19 +++++- .../asset-manifest-builder.ts | 15 ++++- .../aws-cdk-lib/core/test/docker-stub-cp.sh | 11 ++++ packages/aws-cdk-lib/core/test/docker-stub.sh | 6 ++ .../aws-cdk-lib/core/test/staging.test.ts | 63 +++++++++++++++++++ 14 files changed, 171 insertions(+), 15 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713/main create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713noext diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json index 2220abb680bef..87dfbae32bf67 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/IntegTestDefaultTestDeployAssertE3E7D2A4.assets.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713/main b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713/main new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713noext b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713noext new file mode 100644 index 0000000000000..9daeafb9864cf --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713noext @@ -0,0 +1 @@ +test diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk-integ-assets-bundling.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk-integ-assets-bundling.assets.json index ba0dc94f29d00..a0cfc7c0e297a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk-integ-assets-bundling.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk-integ-assets-bundling.assets.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "files": { "68c2f55451f9566ae0c08664249d08921ab032b2aea797bd8ba293885bf00d64": { "source": { @@ -14,7 +14,20 @@ } } }, - "b189049465db589ff992e6ed7347f54d2edf36f0c48c6277ea280abe864b031a": { + "eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713": { + "source": { + "path": "asset.eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713noext", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "eb4b352e81f47c1880938665c15111e9aa20db0d42e929187a1b592a593ea713", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "90c0edfc12d01dfffaee94d9f09e061a7db55c839a6105e5a94f9d96dc51e4fd": { "source": { "path": "cdk-integ-assets-bundling.template.json", "packaging": "file" @@ -22,7 +35,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b189049465db589ff992e6ed7347f54d2edf36f0c48c6277ea280abe864b031a.json", + "objectKey": "90c0edfc12d01dfffaee94d9f09e061a7db55c839a6105e5a94f9d96dc51e4fd.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk.out index 2313ab5436501..1f0068d32659a 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"34.0.0"} \ No newline at end of file +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/integ.json index e7ed476e08c94..db0feb0706bc8 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "testCases": { "IntegTest/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/manifest.json index 4c5021f128fe3..a3d452104bce1 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "34.0.0", + "version": "36.0.0", "artifacts": { "cdk-integ-assets-bundling.assets": { "type": "cdk:asset-manifest", @@ -18,7 +18,7 @@ "validateOnSynth": false, "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b189049465db589ff992e6ed7347f54d2edf36f0c48c6277ea280abe864b031a.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/90c0edfc12d01dfffaee94d9f09e061a7db55c839a6105e5a94f9d96dc51e4fd.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/tree.json index 0550d8f1bdbde..766cc3f80d496 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.js.snapshot/tree.json @@ -66,7 +66,6 @@ "Action": [ "s3:GetBucket*", "s3:GetObject*", - "s3:HeadObject", "s3:List*" ], "Effect": "Allow", @@ -132,6 +131,32 @@ "version": "0.0.0" } }, + "BundledAssetWithoutExtension": { + "id": "BundledAssetWithoutExtension", + "path": "cdk-integ-assets-bundling/BundledAssetWithoutExtension", + "children": { + "Stage": { + "id": "Stage", + "path": "cdk-integ-assets-bundling/BundledAssetWithoutExtension/Stage", + "constructInfo": { + "fqn": "aws-cdk-lib.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "cdk-integ-assets-bundling/BundledAssetWithoutExtension/AssetBucket", + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3_assets.Asset", + "version": "0.0.0" + } + }, "BootstrapVersion": { "id": "BootstrapVersion", "path": "cdk-integ-assets-bundling/BootstrapVersion", @@ -167,7 +192,7 @@ "path": "IntegTest/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } }, "DeployAssert": { @@ -213,7 +238,7 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.2.70" + "version": "10.3.0" } } }, diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.ts index ec89949ca6fa5..a1cc1732141d2 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-assets/test/integ.assets.file-bundling.lit.ts @@ -26,6 +26,17 @@ class TestStack extends Stack { const user = new iam.User(this, 'MyUser'); asset.grantRead(user); + + new assets.Asset(this, 'BundledAssetWithoutExtension', { + path: path.join(__dirname, 'markdown-asset'), + bundling: { + image: DockerImage.fromBuild(path.join(__dirname, 'alpine-markdown')), + outputType: BundlingOutput.SINGLE_FILE, + command: [ + 'sh', '-c', 'echo 123 > /asset-output/main', + ], + }, + }); } } diff --git a/packages/aws-cdk-lib/core/lib/asset-staging.ts b/packages/aws-cdk-lib/core/lib/asset-staging.ts index 11d8e648ab8f9..873f92d993435 100644 --- a/packages/aws-cdk-lib/core/lib/asset-staging.ts +++ b/packages/aws-cdk-lib/core/lib/asset-staging.ts @@ -278,9 +278,10 @@ export class AssetStaging extends Construct { */ private stageByCopying(): StagedAsset { const assetHash = this.calculateHash(this.hashType); - const stagedPath = this.stagingDisabled + const targetPath = this.stagingDisabled ? this.sourcePath : path.resolve(this.assetOutdir, renderAssetFilename(assetHash, getExtension(this.sourcePath))); + const stagedPath = this.renderStagedPath(this.sourcePath, targetPath); if (!this.sourceStats.isDirectory() && !this.sourceStats.isFile()) { throw new Error(`Asset ${this.sourcePath} is expected to be either a directory or a regular file`); @@ -338,7 +339,10 @@ export class AssetStaging extends Construct { // 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)); + const stagedPath = this.renderStagedPath( + bundledAsset.path, + path.resolve(this.assetOutdir, renderAssetFilename(assetHash, bundledAsset.extension)), + ); this.stageAsset(bundledAsset.path, stagedPath, 'move'); @@ -388,7 +392,7 @@ export class AssetStaging extends Construct { } // Moving can be done quickly - if (style == 'move') { + if (style === 'move') { fs.renameSync(sourcePath, targetPath); return; } @@ -511,6 +515,15 @@ export class AssetStaging extends Construct { throw new Error('Unknown asset hash type.'); } } + + private renderStagedPath(sourcePath: string, targetPath: string): string { + // Add a suffix to the asset file name + // because when a file without extension is specified, the source directory name is the same as the staged asset file name. + if (this.hashType === AssetHashType.SOURCE && path.dirname(sourcePath) === targetPath) { + targetPath = targetPath + 'noext'; + } + return targetPath; + } } function renderAssetFilename(assetHash: string, extension = '') { diff --git a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts index 3cd3924872995..0f777e02d93c7 100644 --- a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts +++ b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts @@ -24,8 +24,11 @@ export class AssetManifestBuilder { public defaultAddFileAsset(stack: Stack, asset: FileAssetSource, target: AssetManifestFileDestination) { validateFileAssetSource(asset); + // If the fileName begins with 'asset.', remove it here + // because when a file without extension is added to the manifest, the path.extension() will return an file hash. + // ex) path.extension('asset.dc5ce447844') => 'dc5ce447844' const extension = - asset.fileName != undefined ? path.extname(asset.fileName) : ''; + asset.fileName != undefined ? path.extname(removeAssetPrefix(asset.fileName)) : ''; const objectKey = (target.bucketPrefix ?? '') + asset.sourceHash + @@ -259,3 +262,13 @@ function validateDockerImageAssetSource(asset: DockerImageAssetSource) { } } } + +function removeAssetPrefix(str: string): string { + const prefix = 'asset.'; + + if (str.startsWith(prefix)) { + return str.slice(prefix.length); + } + + return str; +} diff --git a/packages/aws-cdk-lib/core/test/docker-stub-cp.sh b/packages/aws-cdk-lib/core/test/docker-stub-cp.sh index fec4009896d63..47f29ff36854c 100755 --- a/packages/aws-cdk-lib/core/test/docker-stub-cp.sh +++ b/packages/aws-cdk-lib/core/test/docker-stub-cp.sh @@ -6,6 +6,17 @@ set -euo pipefail echo "$@" >> /tmp/docker-stub-cp.input.concat echo "$@" > /tmp/docker-stub-cp.input +# create a file without extension to emulate created files, fetch the target path from the "docker cp" command +if cat /tmp/docker-stub-cp.input.concat | grep "DOCKER_STUB_SINGLE_FILE_WITHOUT_EXT"; then + if echo "$@" | grep "cp"| grep "/asset-output"; then + outdir=$(echo "$@" | grep cp | grep "/asset-output" | xargs -n1 | grep "cdk.out" | head -n1 | cut -d":" -f1) + if [ -n "$outdir" ]; then + touch "${outdir}/test" # create a file witout extension + exit 0 + fi + fi +fi + # create a fake zip to emulate created files, fetch the target path from the "docker cp" command if echo "$@" | grep "cp"| grep "/asset-output"; then outdir=$(echo "$@" | grep cp | grep "/asset-output" | xargs -n1 | grep "cdk.out" | head -n1 | cut -d":" -f1) diff --git a/packages/aws-cdk-lib/core/test/docker-stub.sh b/packages/aws-cdk-lib/core/test/docker-stub.sh index f3bc37d187136..2bb0934e7d304 100755 --- a/packages/aws-cdk-lib/core/test/docker-stub.sh +++ b/packages/aws-cdk-lib/core/test/docker-stub.sh @@ -37,6 +37,12 @@ if echo "$@" | grep "DOCKER_STUB_SINGLE_ARCHIVE"; then exit 0 fi +if echo "$@" | grep "DOCKER_STUB_SINGLE_FILE_WITHOUT_EXT"; then + outdir=$(echo "$@" | xargs -n1 | grep "/asset-output" | head -n1 | cut -d":" -f1) + touch ${outdir}/test # create a file witout extension + exit 0 +fi + if echo "$@" | grep "DOCKER_STUB_SINGLE_FILE"; then outdir=$(echo "$@" | xargs -n1 | grep "/asset-output" | head -n1 | cut -d":" -f1) touch ${outdir}/test.txt diff --git a/packages/aws-cdk-lib/core/test/staging.test.ts b/packages/aws-cdk-lib/core/test/staging.test.ts index dff63c09a76f8..bfeddcf7daea8 100644 --- a/packages/aws-cdk-lib/core/test/staging.test.ts +++ b/packages/aws-cdk-lib/core/test/staging.test.ts @@ -20,6 +20,7 @@ enum DockerStubCommand { MULTIPLE_FILES = 'DOCKER_STUB_MULTIPLE_FILES', SINGLE_ARCHIVE = 'DOCKER_STUB_SINGLE_ARCHIVE', SINGLE_FILE = 'DOCKER_STUB_SINGLE_FILE', + SINGLE_FILE_WITHOUT_EXT = 'DOCKER_STUB_SINGLE_FILE_WITHOUT_EXT', VOLUME_SINGLE_ARCHIVE = 'DOCKER_STUB_VOLUME_SINGLE_ARCHIVE', } @@ -1450,6 +1451,36 @@ describe('staging', () => { expect(staging.isArchive).toEqual(false); }); + test('bundling that produces a single file with SINGLE_FILE_WITHOUT_EXT and hash type SOURCE', () => { + // GIVEN + const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + 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: DockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_FILE_WITHOUT_EXT], + outputType: BundlingOutput.SINGLE_FILE, + }, + assetHashType: AssetHashType.SOURCE, // default + }); + + // THEN + const assembly = app.synth(); + expect(fs.readdirSync(assembly.directory)).toEqual([ + 'asset.ef734136dc22840a94140575a2f98cbc061074e09535589d1cd2c11a4ac2fd75', + 'asset.ef734136dc22840a94140575a2f98cbc061074e09535589d1cd2c11a4ac2fd75noext', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + expect(staging.packaging).toEqual(FileAssetPackaging.FILE); + expect(staging.isArchive).toEqual(false); + }); }); describe('staging with docker cp', () => { @@ -1517,6 +1548,38 @@ describe('staging with docker cp', () => { expect.stringContaining('volume rm assetOutput'), ])); }); + + test('bundling that produces a single file with docker image copy variant', () => { + // GIVEN + const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + 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: DockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_FILE_WITHOUT_EXT], + outputType: BundlingOutput.SINGLE_FILE, + bundlingFileAccess: BundlingFileAccess.VOLUME_COPY, + }, + assetHashType: AssetHashType.SOURCE, // default + }); + + // THEN + const assembly = app.synth(); + expect(fs.readdirSync(assembly.directory)).toEqual([ + 'asset.93bd4079bff7440a725991ecf249416ae9ad73cb639f4a8d9e8f3ad8d491e89f', + 'asset.93bd4079bff7440a725991ecf249416ae9ad73cb639f4a8d9e8f3ad8d491e89fnoext', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + expect(staging.packaging).toEqual(FileAssetPackaging.FILE); + expect(staging.isArchive).toEqual(false); + }); }); // Reads a docker stub and cleans the volume paths out of the stub. From 98a03717a599962d3fc2763df32f64a754fd43ea Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Thu, 20 Jun 2024 22:40:22 +0900 Subject: [PATCH 2/5] delete func --- .../lib/stack-synthesizers/asset-manifest-builder.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts index 0f777e02d93c7..3a7af3f8d632f 100644 --- a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts +++ b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts @@ -28,7 +28,7 @@ export class AssetManifestBuilder { // because when a file without extension is added to the manifest, the path.extension() will return an file hash. // ex) path.extension('asset.dc5ce447844') => 'dc5ce447844' const extension = - asset.fileName != undefined ? path.extname(removeAssetPrefix(asset.fileName)) : ''; + asset.fileName != undefined ? path.extname(asset.fileName) : ''; const objectKey = (target.bucketPrefix ?? '') + asset.sourceHash + @@ -262,13 +262,3 @@ function validateDockerImageAssetSource(asset: DockerImageAssetSource) { } } } - -function removeAssetPrefix(str: string): string { - const prefix = 'asset.'; - - if (str.startsWith(prefix)) { - return str.slice(prefix.length); - } - - return str; -} From 69889ecb5b76d922fc86eee23326738db72369dd Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Sat, 5 Oct 2024 00:14:38 +0900 Subject: [PATCH 3/5] remove comment --- .../core/lib/stack-synthesizers/asset-manifest-builder.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts index d270d1125f0e3..fc743591cfb9c 100644 --- a/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts +++ b/packages/aws-cdk-lib/core/lib/stack-synthesizers/asset-manifest-builder.ts @@ -24,9 +24,6 @@ export class AssetManifestBuilder { public defaultAddFileAsset(stack: Stack, asset: FileAssetSource, target: AssetManifestFileDestination) { validateFileAssetSource(asset); - // If the fileName begins with 'asset.', remove it here - // because when a file without extension is added to the manifest, the path.extension() will return an file hash. - // ex) path.extension('asset.dc5ce447844') => 'dc5ce447844' const extension = asset.fileName != undefined ? path.extname(asset.fileName) : ''; const objectKey = From ecee1697c2ae8baf82baf7f2d6e5815dd95d0665 Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Sat, 5 Oct 2024 00:18:28 +0900 Subject: [PATCH 4/5] change suffix --- packages/aws-cdk-lib/core/lib/asset-staging.ts | 2 +- packages/aws-cdk-lib/core/test/staging.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/asset-staging.ts b/packages/aws-cdk-lib/core/lib/asset-staging.ts index 873f92d993435..c1ea769c1da10 100644 --- a/packages/aws-cdk-lib/core/lib/asset-staging.ts +++ b/packages/aws-cdk-lib/core/lib/asset-staging.ts @@ -520,7 +520,7 @@ export class AssetStaging extends Construct { // Add a suffix to the asset file name // because when a file without extension is specified, the source directory name is the same as the staged asset file name. if (this.hashType === AssetHashType.SOURCE && path.dirname(sourcePath) === targetPath) { - targetPath = targetPath + 'noext'; + targetPath = targetPath + '_noext'; } return targetPath; } diff --git a/packages/aws-cdk-lib/core/test/staging.test.ts b/packages/aws-cdk-lib/core/test/staging.test.ts index bfeddcf7daea8..0ebb322004faf 100644 --- a/packages/aws-cdk-lib/core/test/staging.test.ts +++ b/packages/aws-cdk-lib/core/test/staging.test.ts @@ -1472,7 +1472,7 @@ describe('staging', () => { const assembly = app.synth(); expect(fs.readdirSync(assembly.directory)).toEqual([ 'asset.ef734136dc22840a94140575a2f98cbc061074e09535589d1cd2c11a4ac2fd75', - 'asset.ef734136dc22840a94140575a2f98cbc061074e09535589d1cd2c11a4ac2fd75noext', + 'asset.ef734136dc22840a94140575a2f98cbc061074e09535589d1cd2c11a4ac2fd75_noext', 'cdk.out', 'manifest.json', 'stack.template.json', @@ -1571,7 +1571,7 @@ describe('staging with docker cp', () => { const assembly = app.synth(); expect(fs.readdirSync(assembly.directory)).toEqual([ 'asset.93bd4079bff7440a725991ecf249416ae9ad73cb639f4a8d9e8f3ad8d491e89f', - 'asset.93bd4079bff7440a725991ecf249416ae9ad73cb639f4a8d9e8f3ad8d491e89fnoext', + 'asset.93bd4079bff7440a725991ecf249416ae9ad73cb639f4a8d9e8f3ad8d491e89f_noext', 'cdk.out', 'manifest.json', 'stack.template.json', From 9f5adb574f11baa269764e866956df05f3c5ae8d Mon Sep 17 00:00:00 2001 From: sakurai-ryo Date: Sat, 5 Oct 2024 00:18:45 +0900 Subject: [PATCH 5/5] update renderStagedPath --- .../aws-cdk-lib/core/lib/asset-staging.ts | 4 +- .../aws-cdk-lib/core/test/staging.test.ts | 67 ++++++++++++++++++- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/packages/aws-cdk-lib/core/lib/asset-staging.ts b/packages/aws-cdk-lib/core/lib/asset-staging.ts index c1ea769c1da10..49e8c292805dd 100644 --- a/packages/aws-cdk-lib/core/lib/asset-staging.ts +++ b/packages/aws-cdk-lib/core/lib/asset-staging.ts @@ -519,7 +519,9 @@ export class AssetStaging extends Construct { private renderStagedPath(sourcePath: string, targetPath: string): string { // Add a suffix to the asset file name // because when a file without extension is specified, the source directory name is the same as the staged asset file name. - if (this.hashType === AssetHashType.SOURCE && path.dirname(sourcePath) === targetPath) { + // But when the hashType is `AssetHashType.OUTPUT`, the source directory name begins with `bundling-temp-` and the staged asset file name is different. + // We only need to add a suffix when the hashType is not `AssetHashType.OUTPUT`. + if (this.hashType !== AssetHashType.OUTPUT && path.dirname(sourcePath) === targetPath) { targetPath = targetPath + '_noext'; } return targetPath; diff --git a/packages/aws-cdk-lib/core/test/staging.test.ts b/packages/aws-cdk-lib/core/test/staging.test.ts index 0ebb322004faf..e7fae0974a940 100644 --- a/packages/aws-cdk-lib/core/test/staging.test.ts +++ b/packages/aws-cdk-lib/core/test/staging.test.ts @@ -1481,6 +1481,38 @@ describe('staging', () => { expect(staging.packaging).toEqual(FileAssetPackaging.FILE); expect(staging.isArchive).toEqual(false); }); + + test('bundling that produces a single file with SINGLE_FILE_WITHOUT_EXT and hash type CUSTOM', () => { + // GIVEN + const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + 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: DockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_FILE_WITHOUT_EXT], + outputType: BundlingOutput.SINGLE_FILE, + }, + assetHashType: AssetHashType.CUSTOM, + assetHash: 'custom', + }); + + // THEN + const assembly = app.synth(); + expect(fs.readdirSync(assembly.directory)).toEqual([ + 'asset.f81c5ba9e81eebb202881a8e61a83ab4b69f6bee261989eb93625c9cf5d35335', + 'asset.f81c5ba9e81eebb202881a8e61a83ab4b69f6bee261989eb93625c9cf5d35335_noext', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + expect(staging.packaging).toEqual(FileAssetPackaging.FILE); + expect(staging.isArchive).toEqual(false); + }); }); describe('staging with docker cp', () => { @@ -1549,7 +1581,7 @@ describe('staging with docker cp', () => { ])); }); - test('bundling that produces a single file with docker image copy variant', () => { + test('bundling that produces a single file with docker image copy variant and hash type SOURCE', () => { // GIVEN const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); const stack = new Stack(app, 'stack'); @@ -1580,6 +1612,39 @@ describe('staging with docker cp', () => { expect(staging.packaging).toEqual(FileAssetPackaging.FILE); expect(staging.isArchive).toEqual(false); }); + + test('bundling that produces a single file with docker image copy variant and hash type CUSTOM', () => { + // GIVEN + const app = new App({ context: { [cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT]: false } }); + 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: DockerImage.fromRegistry('alpine'), + command: [DockerStubCommand.SINGLE_FILE_WITHOUT_EXT], + outputType: BundlingOutput.SINGLE_FILE, + bundlingFileAccess: BundlingFileAccess.VOLUME_COPY, + }, + assetHashType: AssetHashType.CUSTOM, + assetHash: 'custom', + }); + + // THEN + const assembly = app.synth(); + expect(fs.readdirSync(assembly.directory)).toEqual([ + 'asset.53a51b4c68874a8e831e24e8982120be2a608f50b2e05edb8501143b3305baa8', + 'asset.53a51b4c68874a8e831e24e8982120be2a608f50b2e05edb8501143b3305baa8_noext', + 'cdk.out', + 'manifest.json', + 'stack.template.json', + 'tree.json', + ]); + expect(staging.packaging).toEqual(FileAssetPackaging.FILE); + expect(staging.isArchive).toEqual(false); + }); }); // Reads a docker stub and cleans the volume paths out of the stub.