Skip to content

Conversation

@daniel-graham-amplitude
Copy link
Collaborator

@daniel-graham-amplitude daniel-graham-amplitude commented Jan 1, 2026

Summary

We're migrating from Yarn to PNPM to take advantage of performance and security enhancements that PNPM provides. And because Yarn v1 has been in maintenance mode for ~6 years

Made a test pre-release called @amplitude/analytics-browser@2.33.2-pnpm-migration.0 and tested it locally
Screenshot 2026-01-02 at 5 29 40 PM
Screenshot 2026-01-02 at 5 29 48 PM
Screenshot 2026-01-02 at 5 30 10 PM

Checklist

  • Does your PR title have the correct title format?
  • Does your PR have a breaking change?: No

Note

Monorepo migration to pnpm

  • Replace Yarn with pnpm across scripts, Husky hooks, docs, and lerna.json (npmClient: pnpm); add pnpm setup/caching in all GitHub Actions (CI, docs, e2e, publish)
  • Update publish workflows to use pnpm (versioning, publish, dry-run) and adjust caching to pnpm-lock.yaml

Package and dependency alignment

  • Move internal deps to workspace:*; replace imports from analytics-types/analytics-client-common with analytics-core in packages/tests
  • Add RN Jest transformIgnorePatterns for pnpm, test tsconfig files, and minor build script tweaks

Core and session replay tweaks

  • Export InstanceProxy from analytics-core; add proxy types
  • Session Replay: ensure sessionId parsed to number in targeting; add test; tighten types in getDebugConfig

Misc

  • Update templates and docs to reference pnpm; minor CI node/action version bumps

Written by Cursor Bugbot for commit d8c094d. This will update automatically on new commits. Configure here.

@macroscopeapp
Copy link
Contributor

macroscopeapp bot commented Jan 1, 2026

Migrate CI workflows, scripts, and workspaces to pnpm and update targeting-manager.evaluateTargetingAndStore in targeting-manager.ts to parse string sessionId values

Switch package management from Yarn to pnpm across CI, Husky hooks, workspace configs, and package scripts; add pnpm lock/workspace files; update inter-package dependencies to workspace:*; introduce core type exports and minor test config changes; and fix string-to-number sessionId handling in targeting.

📍Where to Start

Start with the workflow migration in .github/workflows/ci.yml and then review the sessionId parsing change in targeting-manager.ts.


Macroscope summarized d8c094d.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the repository from Yarn v1 to PNPM to take advantage of performance and security improvements. The migration involves updating package manager references, workspace configurations, CI/CD workflows, and dependency declarations across the monorepo.

Key Changes:

  • Migration from Yarn to PNPM as the package manager with workspace protocol for internal dependencies
  • Updated all GitHub Actions workflows to use PNPM with proper caching setup
  • Converted documentation and scripts to reference PNPM instead of Yarn

Reviewed changes

Copilot reviewed 75 out of 79 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
pnpm-workspace.yaml New PNPM workspace configuration with security settings
package.json Updated packageManager field, scripts, and publish commands for PNPM
lerna.json Changed npmClient from yarn to pnpm
packages/*/package.json Converted dependencies to workspace:* protocol and updated scripts to use pnpm
.github/workflows/*.yml Updated CI/CD workflows to use PNPM with setup-node v4 and caching
.husky/* Updated git hooks to use pnpm commands
README.md, CONTRIBUTING.md, AGENTS.md Updated documentation references from yarn to pnpm
test-server/README.md Updated test server instructions to use pnpm
tsconfig.json Removed 'idb' from types array
packages/*/test/tsconfig.json Added test-specific TypeScript configs
packages/*/jest.config.js Added transformIgnorePatterns for PNPM compatibility
packages/analytics-core/src/types/proxy.ts New file exporting InstanceProxy type
packages/session-replay-browser/src/targeting/targeting-manager.ts Bug fix for parsing string sessionId to number
packages/session-replay-browser/src/helpers.ts Added explicit return type annotation
packages/plugin-experiment-browser/package.json Fixed missing && operator in version script
Various test files Updated imports and mocking strategies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@daniel-graham-amplitude daniel-graham-amplitude force-pushed the pnpm-migration branch 3 times, most recently from c867195 to 5158268 Compare January 1, 2026 00:25
@daniel-graham-amplitude daniel-graham-amplitude force-pushed the pnpm-migration branch 2 times, most recently from a027f2a to a22af1e Compare January 1, 2026 00:31
Copy link
Contributor

@Mercy811 Mercy811 left a comment

Choose a reason for hiding this comment

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

LGTM

if: ${{ github.event.inputs.releaseType == 'prerelease' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:publish -- from-git -y --ignore-scripts --pre-dist-tag ${{ env.PREID }}
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:publish -y --ignore-scripts --tag ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing -- prevents arguments from reaching pnpm scripts

The prerelease workflow passes arguments directly to pnpm scripts without --, so flags like -y, --ignore-scripts, --tag, --conventional-prerelease, and --preid won't be forwarded to the underlying lerna version or pnpm publish commands. The release version step at line 97 correctly uses pnpm deploy:version -- -y ... with --, but these three lines omit it. This will cause prerelease and dry-run workflows to fail or behave incorrectly because the lerna/pnpm commands won't receive the necessary configuration flags.

Additional Locations (2)

Fix in Cursor Fix in Web

 - @amplitude/analytics-browser@2.33.2-pnpm-migration.0
 - @amplitude/analytics-client-common@2.4.20-pnpm-migration.0
 - @amplitude/analytics-core@2.35.1-pnpm-migration.0
 - @amplitude/analytics-node@1.5.30-pnpm-migration.0
 - @amplitude/analytics-react-native@1.5.33-pnpm-migration.0
 - @amplitude/analytics-types@2.11.1-pnpm-migration.0
 - @amplitude/gtm-snippet@2.33.2-pnpm-migration.0
 - @amplitude/plugin-autocapture-browser@1.18.4-pnpm-migration.0
 - @amplitude/plugin-global-user-properties@1.2.111-pnpm-migration.0
 - @amplitude/plugin-network-capture-browser@1.7.4-pnpm-migration.0
 - @amplitude/plugin-page-url-enrichment-browser@0.5.10-pnpm-migration.0
 - @amplitude/plugin-page-view-tracking-browser@2.6.7-pnpm-migration.0
 - @amplitude/plugin-session-replay-browser@1.25.6-pnpm-migration.0
 - @amplitude/plugin-session-replay-react-native@0.4.6-pnpm-migration.0
 - @amplitude/plugin-web-attribution-browser@2.1.104-pnpm-migration.0
 - @amplitude/plugin-web-vitals-browser@1.1.5-pnpm-migration.0
 - @amplitude/segment-session-replay-plugin@0.0.0-pnpm-migration.0
 - @amplitude/session-replay-browser@1.30.5-pnpm-migration.0
 - @amplitude/unified@1.0.0-pnpm-migration.0
- name: Publish Release to NPM
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:publish -- ${{ env.PUBLISH_FROM }} -y --pre-dist-tag beta --loglevel silly
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:publish --ignore-scripts
Copy link

Choose a reason for hiding this comment

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

Publish workflow may fail for unchanged packages

The deploy:publish script changed from lerna publish to pnpm -r --filter "./packages/**" publish. The old lerna publish from-git command intelligently published only packages that received new git tags from lerna version. The new pnpm approach attempts to publish ALL public packages recursively. For packages that weren't changed (and thus not version-bumped by lerna version), npm will reject the publish with "cannot publish over existing version", causing the entire workflow to fail. This affects both the release and prerelease jobs.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is incorrect. It won't publish the package if it already exists in the NPM registry. It will just skip over it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here's the output when it tries publishing packages that are already published:

➜  Amplitude-TypeScript git:(pnpm-migration) pnpm deploy:publish:dry-run

> @ deploy:publish:dry-run /Users/danielgraham/code/Amplitude-TypeScript
> DRY_RUN=true pnpm -r --filter "./packages/**" publish --dry-run --no-git-checks

There are no new packages that should be published

if: ${{ github.event.inputs.releaseType == 'dry-run' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} npm run deploy:version -- -y --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run--preid ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing space causes workflow script to not be found

The command pnpm deploy:version:dry-run--preid ${{ env.PREID }} is missing a space between dry-run and --preid. This causes pnpm to look for a script named deploy:version:dry-run--preid which doesn't exist in package.json. The actual script is named deploy:version:dry-run. This will cause the dry-run workflow to fail with a "script not found" error whenever someone runs the publish workflow with releaseType: dry-run.

Fix in Cursor Fix in Web

if: ${{ github.event.inputs.releaseType == 'dry-run' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run--preid ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing space creates invalid script name in workflow

The command pnpm deploy:version:dry-run--preid is missing a space between deploy:version:dry-run and --preid. The script deploy:version:dry-run--preid does not exist in package.json — only deploy:version:dry-run exists. This will cause the "Dry run pre-release version" workflow step to fail when releaseType is dry-run, breaking the publish dry-run functionality.

Fix in Cursor Fix in Web

if: ${{ github.event.inputs.releaseType == 'dry-run' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run--preid ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing space breaks dry-run workflow command

The command pnpm deploy:version:dry-run--preid is missing a space between dry-run and --preid. This causes pnpm to look for a non-existent script called deploy:version:dry-run--preid instead of running deploy:version:dry-run with the --preid argument. The dry-run pre-release workflow will fail when triggered.

Fix in Cursor Fix in Web

if: ${{ github.event.inputs.releaseType == 'dry-run' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run--preid ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing space causes workflow command to fail

The command pnpm deploy:version:dry-run--preid is missing a space before --preid. This causes pnpm to try to run a non-existent script called deploy:version:dry-run--preid instead of the intended script deploy:version:dry-run with --preid as an argument. The dry-run pre-release version workflow step will fail whenever triggered.

Fix in Cursor Fix in Web

if: ${{ github.event.inputs.releaseType == 'dry-run' }}
run: |
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run --no-private --conventional-prerelease --preid ${{ env.PREID }} --allow-branch ${{ steps.determine-branch.outputs.branch }} --no-changelog --no-push --no-git-tag-version
GH_TOKEN=${{ secrets.GH_PUBLISH_TOKEN }} pnpm deploy:version:dry-run--preid ${{ env.PREID }}
Copy link

Choose a reason for hiding this comment

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

Missing space causes invalid pnpm script name

The command pnpm deploy:version:dry-run--preid is missing a space between deploy:version:dry-run and --preid. This creates an invalid script name that doesn't exist in package.json, causing the dry-run pre-release workflow step to fail. The command should be pnpm deploy:version:dry-run --preid ${{ env.PREID }}.

Fix in Cursor Fix in Web

 - @amplitude/analytics-browser@2.33.2-pnpm-migration.0
 - @amplitude/analytics-client-common@2.4.20-pnpm-migration.0
 - @amplitude/analytics-core@2.35.1-pnpm-migration.0
 - @amplitude/analytics-node@1.5.30-pnpm-migration.0
 - @amplitude/analytics-react-native@1.5.33-pnpm-migration.0
 - @amplitude/analytics-types@2.11.1-pnpm-migration.0
 - @amplitude/gtm-snippet@2.33.2-pnpm-migration.0
 - @amplitude/plugin-autocapture-browser@1.18.4-pnpm-migration.0
 - @amplitude/plugin-global-user-properties@1.2.111-pnpm-migration.0
 - @amplitude/plugin-network-capture-browser@1.7.4-pnpm-migration.0
 - @amplitude/plugin-page-url-enrichment-browser@0.5.10-pnpm-migration.0
 - @amplitude/plugin-page-view-tracking-browser@2.6.7-pnpm-migration.0
 - @amplitude/plugin-session-replay-browser@1.25.6-pnpm-migration.0
 - @amplitude/plugin-session-replay-react-native@0.4.6-pnpm-migration.0
 - @amplitude/plugin-web-attribution-browser@2.1.104-pnpm-migration.0
 - @amplitude/plugin-web-vitals-browser@1.1.5-pnpm-migration.0
 - @amplitude/segment-session-replay-plugin@0.0.0-pnpm-migration.0
 - @amplitude/session-replay-browser@1.30.5-pnpm-migration.0
 - @amplitude/unified@1.0.0-pnpm-migration.0
"deploy:version": "lerna version",
"deploy:publish": "lerna publish",
"deploy:version:dry-run": "DRY_RUN=true lerna version --no-push --no-git-tag-version --allow-branch \"$(git rev-parse --abbrev-ref HEAD)\" --conventional-prerelease --no-changelog --no-push --no-git-tag-version",
"deploy:publish": "pnpm -r --filter \"./packages/**\" publish",
Copy link

Choose a reason for hiding this comment

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

Release workflow may fail publishing unchanged packages

The deploy:publish script changed from lerna publish to pnpm -r --filter "./packages/**" publish. The old lerna publish command supported from-git mode (used in the v1 workflow to publish only packages with new git tags after lerna version). The new pnpm command publishes ALL packages unconditionally. When lerna version bumps only changed packages, then pnpm publish runs on all packages, unchanged packages will fail because their versions already exist on npm. The workflow comment at line 184 of publish-v2.yml still references "Use 'from git' option" but this behavior is no longer implemented.

Fix in Cursor Fix in Web

"test:mobile": "jest --setupFiles './test/mock/setup-mobile.ts'",
"typecheck": "tsc -p ./tsconfig.json",
"version": "yarn version-file && yarn build",
"version": "pnpm version-file && pnpm build",
Copy link

Choose a reason for hiding this comment

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

Incomplete migration leaves yarn commands in scripts

The Yarn to PNPM migration is incomplete. The example scripts in three React Native packages still use yarn commands (yarn --cwd example and yarn workspace ...) while other scripts in the same files were updated to use pnpm. After migration, if Yarn is not installed or Corepack enforces the pnpm packageManager, running pnpm example in these packages will fail because the underlying command still invokes yarn.

Additional Locations (2)

Fix in Cursor Fix in Web

"deploy:version": "lerna version",
"deploy:publish": "lerna publish",
"deploy:version:dry-run": "DRY_RUN=true lerna version --no-push --no-git-tag-version --allow-branch \"$(git rev-parse --abbrev-ref HEAD)\" --conventional-prerelease --no-changelog --no-push --no-git-tag-version",
"deploy:publish": "pnpm -r --filter \"./packages/**\" publish",
Copy link

Choose a reason for hiding this comment

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

Prerelease publish command uses incompatible lerna arguments

The deploy:publish script was changed from lerna publish to pnpm -r --filter \"./packages/**\" publish. However, the prerelease publish step in publish-v2.yml (line 188) still calls npm run deploy:publish -- from-git -y --ignore-scripts --pre-dist-tag ${{ env.PREID }}. These are lerna-specific arguments (from-git, --ignore-scripts, --pre-dist-tag) that pnpm's recursive publish command doesn't understand. This will cause the prerelease workflow to fail when triggered.

Additional Locations (1)

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants