Skip to content

fix(lambda-nodejs): prevent pnpm store and workspace state timestamps from changing asset hash (#39550) - #39557

Open
wasim-builds wants to merge 1 commit into
aws:mainfrom
wasim-builds:fix/lambda-nodejs-pnpm-store-hash
Open

wasim-builds wants to merge 1 commit into
aws:mainfrom
wasim-builds:fix/lambda-nodejs-pnpm-store-hash

Conversation

@wasim-builds

Copy link
Copy Markdown
Contributor

Issue # (if applicable)

Closes #39550.

Reason for this change

When using NodejsFunction with Docker bundling and pnpm, the synthesized asset contains the pnpm store directory (.pnpm-store/). Because the store contains files with timestamps (*-index.json with checkedAt in pnpm 7 and 10, index.db in pnpm 11+), the asset hash (AssetHashType.OUTPUT) changes on every synth even when neither source code nor dependencies have changed. Every deploy uploads a new asset and updates the function, and doubles the asset archive size.

Root cause:

  1. The bundling Dockerfile previously ran pnpm config --global set store-dir /tmp/pnpm-cache. This wrote to root's config (/root/.config/pnpm/rc or /root/.config/pnpm/config.yaml). When the container runs as a non-root host user (-u <uid>:<gid> with HOME=/), that user cannot read root's config. With no store directory configured, pnpm defaults to placing the store on the same device as the project, which is the bind-mounted /asset-output directory.
  2. Under pnpm 10+, pnpm additionally creates node_modules/.pnpm-workspace-state-v1.json with a lastValidatedTimestamp property on every install. While CDK already cleaned up node_modules/.modules.yaml, this file was left in the output, changing the asset hash on every synth for both Docker and local bundling.

Description of changes

  1. Dockerfile: Replaced root-only pnpm config --global set store-dir /tmp/pnpm-cache with universal environment variables:
    ENV npm_config_store_dir=/tmp/pnpm-cache
    ENV pnpm_config_store_dir=/tmp/pnpm-cache
    All container users (including non-root host users) inherit these environment variables, directing the pnpm store into /tmp/pnpm-cache instead of /asset-output.
  2. Bundling: Clean up node_modules/.pnpm-workspace-state-v1.json alongside node_modules/.modules.yaml in both Docker bundling (dockerFileOps) and local bundling (localFileOps).

Description of how you validated changes

  • Updated unit tests in packages/aws-cdk-lib/aws-lambda-nodejs/test/bundling.test.ts:
    • Verified Docker shell command chain includes removal of /asset-output/node_modules/.pnpm-workspace-state-v1.json.
    • Verified local bundling cleanup cleans up /outdir/node_modules/.pnpm-workspace-state-v1.json.

Checklist


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license.

Copilot AI balanced review requested due to automatic review settings October 29, 2026 16:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@github-actions github-actions Bot added bug This issue is a bug. p2 labels Oct 29, 2026
@github-actions github-actions Bot added the beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK label Oct 29, 2026

@aws-cdk-automation aws-cdk-automation left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pull request linter fails with the following errors:

❌ Fixes must contain a change to an integration test file and the resulting snapshot.

If you believe this pull request should receive an exemption, please comment and provide a justification. A comment requesting an exemption should contain the text Exemption Request. Additionally, if clarification is needed, add Clarification Request to a comment.

@maintainer-for-aws

Copy link
Copy Markdown

Automated review

A maintainer will still review this — treat the notes below as a starting point.

📌 Commit e4253da

This PR fixes non-deterministic NodejsFunction asset hashes under pnpm in the aws-lambda-nodejs bundling pipeline. It swaps the root-only pnpm config --global set store-dir in the bundling Dockerfile for ENV npm_config_store_dir / pnpm_config_store_dir (inherited by the host-uid runtime user, covering pnpm 7/10 and 11+), stopping pnpm's content-addressable store from leaking timestamped files into /asset-output, and adds .pnpm-workspace-state-v1.json cleanup in both the Docker (dockerFileOps) and local (localFileOps) paths alongside the existing .modules.yaml handling.

The change is narrowly scoped and pnpm-guarded; the two cleanup paths are mirrored correctly and their unit assertions track both. The one gap is that the Dockerfile store-redirect — the primary root cause — is exercised by no test in this PR. Otherwise the change is clean, with the acknowledged one-time asset-hash churn being the fix's intended effect rather than a regression.

🔴 0 blocking · 🟡 1 recommended · ⚪ 0 optional

Files with findings (1)
File Findings
packages/aws-cdk-lib/aws-lambda-nodejs/lib/docker/Dockerfile 🟡 1

Generated automatically. React 👍 or 👎 to tell us whether this review helped, so we can improve these reviews.

@maintainer-for-aws maintainer-for-aws Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review summary comment for the overview; the notes below are inline.

Comment on lines +36 to +37
chmod -R 777 /tmp/pnpm-cache
ENV npm_config_store_dir=/tmp/pnpm-cache

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Recommended — The load-bearing half of this fix — redirecting pnpm's content-addressable store out of the bind-mounted /asset-output via build-image ENV npm_config_store_dir / pnpm_config_store_dir — has no test that would fail if it regressed. The unit tests only assert the emitted shell command for the .pnpm-workspace-state-v1.json cleanup; none reference the Dockerfile or store-dir, and a Dockerfile ENV change is not observable in a synthesized-template assertion. The module's existing integ.dependencies-pnpm.ts (pnpm + nodeModules + forceDockerBundling) exercises exactly this path, but its committed AssetHashType.OUTPUT snapshot was not regenerated, so nothing proves the store no longer leaks into the asset or that the hash is now deterministic (INTEGRATION_TESTS.md#when-are-integration-tests-required).

Suggested change: Regenerate integ.dependencies-pnpm.js.snapshot via a real deploy (yarn integ --update-on-failed integ.dependencies-pnpm.js) so the asset hash reflects the de-leaked output and the pnpm Docker path is re-validated end-to-end; or, if maintainers judge regeneration unnecessary, apply the integ-test exemption label with a note explaining why.

@blacksoxx blacksoxx left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the diff and the issue; I could not build the package here, so these are reading notes.

The analysis in #39550 matches the Dockerfile: pnpm config --global set only wrote root's rc file, and the bundling container runs as the host uid with HOME=/, so the store silently fell back next to the project under /asset-output. Moving the setting to ENV makes it reach every user, pnpm has read npm_config_* for as long as the pinned 7.33.7 has existed, and the pnpm_config_* twin covers the newer prefix. Removing .pnpm-workspace-state-v1.json next to the existing .modules.yaml cleanup, on both the Docker and the local path with the two tests extended, closes the second timestamp source from the issue.

One thing worth a sentence in the description: with the store back in /tmp/pnpm-cache, existing pnpm users lose the duplicated store directory from their asset, so they will see one asset hash change on the next deploy, after which it stays stable. That is the intended effect, but it reads as a surprise if nobody says it. Nothing blocking from my side.

This branch was previously deployed

1 inactive deployment
automation — e4253dae Deployed Oct 29, 2026 by wasim-builds via validate-pr #375520
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

beginning-contributor [Pilot] contributed between 0-2 PRs to the CDK bug This issue is a bug. p2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

(aws-lambda-nodejs): asset hash changes on every synth with pnpm (pnpm store and timestamp file in the asset)

4 participants