From 7c752db4aa83b242098483fc006c1100d1be11a9 Mon Sep 17 00:00:00 2001 From: Chinedum Echeta <60179183+cecheta@users.noreply.github.com> Date: Wed, 28 Dec 2022 20:21:04 +0000 Subject: [PATCH] fix(lambda-nodejs): unable to use `nodeModules` with pnpm (#21911) Fixes #21910 By default, pnpm uses symlinks when installing dependencies, and modules only have access to dependencies in their `package.json`. This means when trying to bundle, dependencies of depedencies are not installed. This PR fixes this by using the ` --config.node_linker=hoisted` flag to create a flat `node_modules` structure. [Docs](https://pnpm.io/npmrc#node-linker). The second problem this PR fixes is when using pnpm workspaces. With workspaces, modules are installed within the workspace the command is run in. This means that when installing as part of bundling in a nested directory, no `node_modules` directory is produced at all. By creating a new `pnpm-workspace.yaml` file locally before installing, this essentially creates a new (nested) workspace, and `node_modules` is installed here. An empty file is enough for this to suffice. The PR also removes a `.modules.yaml` file from the `node_modules` after installing. This file contains a datetime of the last install, therefore it would cause the lambda code to change on each deployment if it was included in the bundle. I have tested this fix locally on both Mac and Windows. I have also included an integration test which failed before these changes, however I am not sure if it should be included due to the `node_modules` in the assets. ---- ### All Submissions: * [X] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) ### Adding new Unconventional Dependencies: * [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies) ### New Features * [X] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)? * [X] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)? *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../@aws-cdk/aws-lambda-nodejs/lib/Dockerfile | 5 + .../aws-lambda-nodejs/lib/bundling.ts | 29 +- .../aws-lambda-nodejs/lib/function.ts | 6 +- .../aws-lambda-nodejs/lib/package-manager.ts | 4 +- .../@aws-cdk/aws-lambda-nodejs/lib/types.ts | 2 +- .../@aws-cdk/aws-lambda-nodejs/package.json | 1 + .../aws-lambda-nodejs/test/bundling.test.ts | 2 +- .../aws-lambda-nodejs/test/docker.test.ts | 1 + .../integ-handlers/pnpm/dependencies-pnpm.ts | 6 + .../test/integ-handlers/pnpm/pnpm-lock.yaml | 70 ++++ ...efaultTestDeployAssert397EDF83.assets.json | 19 ++ ...aultTestDeployAssert397EDF83.template.json | 36 ++ .../TestStack.assets.json | 45 +++ .../TestStack.template.json | 200 +++++++++++ .../cdk.out | 1 + .../integ.json | 13 + .../manifest.json | 141 ++++++++ .../tree.json | 314 ++++++++++++++++++ .../test/integ.dependencies-pnpm.ts | 35 ++ .../test/package-manager.test.ts | 4 +- 20 files changed, 921 insertions(+), 13 deletions(-) create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/dependencies-pnpm.ts create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/pnpm-lock.yaml create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.assets.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.template.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.assets.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.template.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/integ.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/tree.json create mode 100644 packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.ts diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile b/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile index 54969bb5fde2c..f84c7fbfe5794 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/Dockerfile @@ -27,6 +27,11 @@ RUN mkdir /tmp/yarn-cache && \ chmod -R 777 /tmp/yarn-cache && \ yarn config set cache-folder /tmp/yarn-cache +# Ensure all users can write to pnpm cache +RUN mkdir /tmp/pnpm-cache && \ + chmod -R 777 /tmp/pnpm-cache && \ + pnpm config --global set store-dir /tmp/pnpm-cache + # Disable npm update notifications RUN npm config --global set update-notifier false diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts index 8809166a6e57b..fd0c17a3be465 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/bundling.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import { Architecture, AssetCode, Code, Runtime } from '@aws-cdk/aws-lambda'; import * as cdk from '@aws-cdk/core'; import { PackageInstallation } from './package-installation'; -import { PackageManager } from './package-manager'; +import { LockFile, PackageManager } from './package-manager'; import { BundlingOptions, OutputFormat, SourceMapMode } from './types'; import { exec, extractDependencies, findUp, getTsconfigCompilerOptions } from './util'; @@ -229,12 +229,16 @@ export class Bundling implements cdk.BundlingOptions { const lockFilePath = pathJoin(options.inputDir, this.relativeDepsLockFilePath ?? this.packageManager.lockFile); + const isPnpm = this.packageManager.lockFile === LockFile.PNPM; + // Create dummy package.json, copy lock file if any and then install depsCommand = chain([ + isPnpm ? osCommand.write(pathJoin(options.outputDir, 'pnpm-workspace.yaml'), ''): '', // Ensure node_modules directory is installed locally by creating local 'pnpm-workspace.yaml' file osCommand.writeJson(pathJoin(options.outputDir, 'package.json'), { dependencies }), osCommand.copy(lockFilePath, pathJoin(options.outputDir, this.packageManager.lockFile)), osCommand.changeDirectory(options.outputDir), this.packageManager.installCommand.join(' '), + isPnpm ? osCommand.remove(pathJoin(options.outputDir, 'node_modules', '.modules.yaml')) : '', // Remove '.modules.yaml' file which changes on each deployment ]); } @@ -310,13 +314,20 @@ interface BundlingCommandOptions { class OsCommand { constructor(private readonly osPlatform: NodeJS.Platform) {} - public writeJson(filePath: string, data: any): string { - const stringifiedData = JSON.stringify(data); + public write(filePath: string, data: string): string { if (this.osPlatform === 'win32') { - return `echo ^${stringifiedData}^ > "${filePath}"`; + if (!data) { // if `data` is empty, echo a blank line, otherwise the file will contain a `^` character + return `echo. > "${filePath}"`; + } + return `echo ^${data}^ > "${filePath}"`; } - return `echo '${stringifiedData}' > "${filePath}"`; + return `echo '${data}' > "${filePath}"`; + } + + public writeJson(filePath: string, data: any): string { + const stringifiedData = JSON.stringify(data); + return this.write(filePath, stringifiedData); } public copy(src: string, dest: string): string { @@ -330,6 +341,14 @@ class OsCommand { public changeDirectory(dir: string): string { return `cd "${dir}"`; } + + public remove(filePath: string): string { + if (this.osPlatform === 'win32') { + return `del "${filePath}"`; + } + + return `rm "${filePath}"`; + } } /** diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts index ea3b1f9b6f005..202be464b16da 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/function.ts @@ -51,16 +51,16 @@ export interface NodejsFunctionProps extends lambda.FunctionOptions { readonly awsSdkConnectionReuse?: boolean; /** - * The path to the dependencies lock file (`yarn.lock` or `package-lock.json`). + * The path to the dependencies lock file (`yarn.lock`, `pnpm-lock.yaml` or `package-lock.json`). * * This will be used as the source for the volume mounted in the Docker * container. * * Modules specified in `nodeModules` will be installed using the right - * installer (`npm` or `yarn`) along with this lock file. + * installer (`yarn`, `pnpm` or `npm`) along with this lock file. * * @default - the path is found by walking up parent directories searching for - * a `yarn.lock` or `package-lock.json` file + * a `yarn.lock`, `pnpm-lock.yaml` or `package-lock.json` file */ readonly depsLockFilePath?: string; diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts index 05ef109993460..5d68f20347840 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/package-manager.ts @@ -39,7 +39,9 @@ export class PackageManager { case LockFile.PNPM: return new PackageManager({ lockFile: LockFile.PNPM, - installCommand: logLevel && logLevel !== LogLevel.INFO ? ['pnpm', 'install', '--reporter', 'silent'] : ['pnpm', 'install'], + installCommand: logLevel && logLevel !== LogLevel.INFO ? ['pnpm', 'install', '--reporter', 'silent', '--config.node-linker=hoisted', '--config.package-import-method=clone-or-copy'] : ['pnpm', 'install', '--config.node-linker=hoisted', '--config.package-import-method=clone-or-copy'], + // --config.node-linker=hoisted to create flat node_modules without symlinks + // --config.package-import-method=clone-or-copy to avoid hardlinking packages from the store runCommand: ['pnpm', 'exec'], argsSeparator: '--', }); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts index bb3c0c8559742..0ca72b4149b1f 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/lib/types.ts @@ -247,7 +247,7 @@ export interface BundlingOptions extends DockerRunOptions { * A custom bundling Docker image. * * This image should have esbuild installed globally. If you plan to use `nodeModules` - * it should also have `npm` or `yarn` depending on the lock file you're using. + * it should also have `npm`, `yarn` or `pnpm` depending on the lock file you're using. * * See https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/aws-lambda-nodejs/lib/Dockerfile * for the default image provided by @aws-cdk/aws-lambda-nodejs. diff --git a/packages/@aws-cdk/aws-lambda-nodejs/package.json b/packages/@aws-cdk/aws-lambda-nodejs/package.json index 5f483e81d1cc4..cf3cf09fc65fe 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/package.json +++ b/packages/@aws-cdk/aws-lambda-nodejs/package.json @@ -78,6 +78,7 @@ "@aws-cdk/integ-runner": "0.0.0", "@aws-cdk/integ-tests": "0.0.0", "@aws-cdk/pkglint": "0.0.0", + "@aws-cdk/triggers": "0.0.0", "@types/jest": "^27.5.2", "delay": "5.0.0", "esbuild": "^0.16.6" diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts index 83029ec601590..9679530a01189 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/bundling.test.ts @@ -408,7 +408,7 @@ test('Detects pnpm-lock.yaml', () => { assetHashType: AssetHashType.OUTPUT, bundling: expect.objectContaining({ command: expect.arrayContaining([ - expect.stringMatching(/pnpm-lock\.yaml.+pnpm install/), + expect.stringMatching(/echo '' > "\/asset-output\/pnpm-workspace.yaml\".+pnpm-lock\.yaml.+pnpm install --config.node-linker=hoisted --config.package-import-method=clone-or-copy && rm "\/asset-output\/node_modules\/.modules.yaml"/), ]), }), }); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/docker.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/docker.test.ts index d1b85dfcca2b8..f347fac6a7565 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/docker.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/docker.test.ts @@ -58,6 +58,7 @@ test('cache folders have the right permissions', () => { 'bash', '-c', [ 'stat -c \'%a\' /tmp/npm-cache', 'stat -c \'%a\' /tmp/yarn-cache', + 'stat -c \'%a\' /tmp/pnpm-cache', ].join(' && '), ]); expect(proc.stdout.toString()).toMatch('777\n777'); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/dependencies-pnpm.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/dependencies-pnpm.ts new file mode 100644 index 0000000000000..81022e2b9e00f --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/dependencies-pnpm.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import axios from 'axios'; + +export async function handler() { + await axios.get('https://www.google.com'); +} diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/pnpm-lock.yaml b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/pnpm-lock.yaml new file mode 100644 index 0000000000000..899ba52e99ec2 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ-handlers/pnpm/pnpm-lock.yaml @@ -0,0 +1,70 @@ +lockfileVersion: 5.4 + +specifiers: + axios: ^1.2.1 + +dependencies: + axios: 1.2.1 + +packages: + + /asynckit/0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /axios/1.2.1: + resolution: {integrity: sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==} + dependencies: + follow-redirects: 1.15.2 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /combined-stream/1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /delayed-stream/1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /follow-redirects/1.15.2: + resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /form-data/4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /mime-db/1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types/2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /proxy-from-env/1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.assets.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.assets.json new file mode 100644 index 0000000000000..f2f1759f8e85a --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.assets.json @@ -0,0 +1,19 @@ +{ + "version": "22.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "PnpmTestDefaultTestDeployAssert397EDF83.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.template.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/PnpmTestDefaultTestDeployAssert397EDF83.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.assets.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.assets.json new file mode 100644 index 0000000000000..30c2cc5969fcb --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.assets.json @@ -0,0 +1,45 @@ +{ + "version": "22.0.0", + "files": { + "58d2406e0a74fd42ac31e584a098bb581709c3de7bff389451c2a08db50c4383": { + "source": { + "path": "asset.58d2406e0a74fd42ac31e584a098bb581709c3de7bff389451c2a08db50c4383", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "58d2406e0a74fd42ac31e584a098bb581709c3de7bff389451c2a08db50c4383.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "44fdff138ed916c94d14f276217febea5c4a2e1746518f7f620c37b22a6675b8": { + "source": { + "path": "asset.44fdff138ed916c94d14f276217febea5c4a2e1746518f7f620c37b22a6675b8", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "44fdff138ed916c94d14f276217febea5c4a2e1746518f7f620c37b22a6675b8.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "c51cd09452e746f11796192b2e9025f8c82de145d16aeb2e2c66c2197ecbae26": { + "source": { + "path": "TestStack.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "c51cd09452e746f11796192b2e9025f8c82de145d16aeb2e2c66c2197ecbae26.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.template.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.template.json new file mode 100644 index 0000000000000..8b95fc6ae04df --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/TestStack.template.json @@ -0,0 +1,200 @@ +{ + "Resources": { + "FunctionServiceRole675BB04A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "Function76856677": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "58d2406e0a74fd42ac31e584a098bb581709c3de7bff389451c2a08db50c4383.zip" + }, + "Role": { + "Fn::GetAtt": [ + "FunctionServiceRole675BB04A", + "Arn" + ] + }, + "Environment": { + "Variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "Handler": "index.handler", + "Runtime": "nodejs18.x" + }, + "DependsOn": [ + "FunctionServiceRole675BB04A" + ] + }, + "FunctionCurrentVersion4E2B22618dd26ccb3af7b577163fa65856572807": { + "Type": "AWS::Lambda::Version", + "Properties": { + "FunctionName": { + "Ref": "Function76856677" + } + } + }, + "Trigger": { + "Type": "Custom::Trigger", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderHandler97BECD91", + "Arn" + ] + }, + "HandlerArn": { + "Ref": "FunctionCurrentVersion4E2B22618dd26ccb3af7b577163fa65856572807" + }, + "InvocationType": "RequestResponse", + "Timeout": 120000 + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ] + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + } + ], + "Policies": [ + { + "PolicyName": "Inline", + "PolicyDocument": { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "lambda:InvokeFunction" + ], + "Resource": [ + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "Function76856677", + "Arn" + ] + }, + ":*" + ] + ] + } + ] + } + ] + } + } + ] + } + }, + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderHandler97BECD91": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "44fdff138ed916c94d14f276217febea5c4a2e1746518f7f620c37b22a6675b8.zip" + }, + "Timeout": 900, + "MemorySize": 128, + "Handler": "__entrypoint__.handler", + "Role": { + "Fn::GetAtt": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A", + "Arn" + ] + }, + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/cdk.out new file mode 100644 index 0000000000000..145739f539580 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"22.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/integ.json new file mode 100644 index 0000000000000..368ae1d1b2566 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "22.0.0", + "testCases": { + "PnpmTest/DefaultTest": { + "stacks": [ + "TestStack" + ], + "stackUpdateWorkflow": false, + "assertionStack": "PnpmTest/DefaultTest/DeployAssert", + "assertionStackName": "PnpmTestDefaultTestDeployAssert397EDF83" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/manifest.json new file mode 100644 index 0000000000000..d6305be21c368 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/manifest.json @@ -0,0 +1,141 @@ +{ + "version": "22.0.0", + "artifacts": { + "TestStack.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "TestStack.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "TestStack": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "TestStack.template.json", + "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}/c51cd09452e746f11796192b2e9025f8c82de145d16aeb2e2c66c2197ecbae26.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "TestStack.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "TestStack.assets" + ], + "metadata": { + "/TestStack/Function/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FunctionServiceRole675BB04A" + } + ], + "/TestStack/Function/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Function76856677" + } + ], + "/TestStack/Function/CurrentVersion/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FunctionCurrentVersion4E2B22618dd26ccb3af7b577163fa65856572807" + } + ], + "/TestStack/Trigger/Default/Default": [ + { + "type": "aws:cdk:logicalId", + "data": "Trigger" + } + ], + "/TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider/Role": [ + { + "type": "aws:cdk:logicalId", + "data": "AWSCDKTriggerCustomResourceProviderCustomResourceProviderRoleE18FAF0A" + } + ], + "/TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider/Handler": [ + { + "type": "aws:cdk:logicalId", + "data": "AWSCDKTriggerCustomResourceProviderCustomResourceProviderHandler97BECD91" + } + ], + "/TestStack/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/TestStack/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "TestStack" + }, + "PnpmTestDefaultTestDeployAssert397EDF83.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "PnpmTestDefaultTestDeployAssert397EDF83.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "PnpmTestDefaultTestDeployAssert397EDF83": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "PnpmTestDefaultTestDeployAssert397EDF83.template.json", + "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}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "PnpmTestDefaultTestDeployAssert397EDF83.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "PnpmTestDefaultTestDeployAssert397EDF83.assets" + ], + "metadata": { + "/PnpmTest/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/PnpmTest/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "PnpmTest/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/tree.json new file mode 100644 index 0000000000000..1fa148c5c7342 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.js.snapshot/tree.json @@ -0,0 +1,314 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "TestStack": { + "id": "TestStack", + "path": "TestStack", + "children": { + "Function": { + "id": "Function", + "path": "TestStack/Function", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "TestStack/Function/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "TestStack/Function/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "TestStack/Function/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "TestStack/Function/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "TestStack/Function/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "TestStack/Function/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "TestStack/Function/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "58d2406e0a74fd42ac31e584a098bb581709c3de7bff389451c2a08db50c4383.zip" + }, + "role": { + "Fn::GetAtt": [ + "FunctionServiceRole675BB04A", + "Arn" + ] + }, + "environment": { + "variables": { + "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1" + } + }, + "handler": "index.handler", + "runtime": "nodejs18.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "CurrentVersion": { + "id": "CurrentVersion", + "path": "TestStack/Function/CurrentVersion", + "children": { + "Resource": { + "id": "Resource", + "path": "TestStack/Function/CurrentVersion/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Version", + "aws:cdk:cloudformation:props": { + "functionName": { + "Ref": "Function76856677" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnVersion", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Version", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda-nodejs.NodejsFunction", + "version": "0.0.0" + } + }, + "Trigger": { + "id": "Trigger", + "path": "TestStack/Trigger", + "children": { + "Default": { + "id": "Default", + "path": "TestStack/Trigger/Default", + "children": { + "Default": { + "id": "Default", + "path": "TestStack/Trigger/Default/Default", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/triggers.Trigger", + "version": "0.0.0" + } + }, + "AWSCDK.TriggerCustomResourceProviderCustomResourceProvider": { + "id": "AWSCDK.TriggerCustomResourceProviderCustomResourceProvider", + "path": "TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider", + "children": { + "Staging": { + "id": "Staging", + "path": "TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider/Staging", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "Role": { + "id": "Role", + "path": "TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider/Role", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + }, + "Handler": { + "id": "Handler", + "path": "TestStack/AWSCDK.TriggerCustomResourceProviderCustomResourceProvider/Handler", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.CustomResourceProvider", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "TestStack/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "TestStack/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "PnpmTest": { + "id": "PnpmTest", + "path": "PnpmTest", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "PnpmTest/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "PnpmTest/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "PnpmTest/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "PnpmTest/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "PnpmTest/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "@aws-cdk/core.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.189" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.ts new file mode 100644 index 0000000000000..6c4352ba8f57c --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/integ.dependencies-pnpm.ts @@ -0,0 +1,35 @@ +import * as path from 'path'; +import { Runtime } from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import * as triggers from '@aws-cdk/triggers'; +import * as lambda from '../lib'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'TestStack'); + +const handler = new lambda.NodejsFunction(stack, 'Function', { + entry: path.join(__dirname, 'integ-handlers/pnpm/dependencies-pnpm.ts'), + runtime: Runtime.NODEJS_18_X, + bundling: { + minify: true, + // Will be installed, not bundled + // (axios is a package with sub-dependencies, + // will be used to ensure pnpm bundling works as expected) + nodeModules: ['axios'], + forceDockerBundling: true, + }, + depsLockFilePath: path.join(__dirname, 'integ-handlers/pnpm/pnpm-lock.yaml'), +}); + +new triggers.Trigger(stack, 'Trigger', { + handler, +}); + +new integ.IntegTest(app, 'PnpmTest', { + testCases: [stack], + stackUpdateWorkflow: false, // this will tell the runner to not check in assets. +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts b/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts index 8bb0682c0d568..6be593f785eff 100644 --- a/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts +++ b/packages/@aws-cdk/aws-lambda-nodejs/test/package-manager.test.ts @@ -37,7 +37,7 @@ test('from a pnpm-lock.yaml', () => { const packageManager = PackageManager.fromLockFile('/path/to/pnpm-lock.yaml'); expect(packageManager.lockFile).toEqual(LockFile.PNPM); expect(packageManager.argsSeparator).toEqual('--'); - expect(packageManager.installCommand).toEqual(['pnpm', 'install']); + expect(packageManager.installCommand).toEqual(['pnpm', 'install', '--config.node-linker=hoisted', '--config.package-import-method=clone-or-copy']); expect(packageManager.runCommand).toEqual(['pnpm', 'exec']); expect(packageManager.runBinCommand('my-bin')).toBe('pnpm exec -- my-bin'); @@ -45,7 +45,7 @@ test('from a pnpm-lock.yaml', () => { test('from a pnpm-lock.yaml with LogLevel.ERROR', () => { const packageManager = PackageManager.fromLockFile('/path/to/pnpm-lock.yaml', LogLevel.ERROR); - expect(packageManager.installCommand).toEqual(['pnpm', 'install', '--reporter', 'silent']); + expect(packageManager.installCommand).toEqual(['pnpm', 'install', '--reporter', 'silent', '--config.node-linker=hoisted', '--config.package-import-method=clone-or-copy']); }); test('defaults to NPM', () => {