From ab6ec290fe22fa475551de827b1a46facc0e0e61 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sun, 9 Aug 2026 09:48:25 +0200 Subject: [PATCH 1/4] chore: use global virtual store --- workspace.jsonc | 1 + 1 file changed, 1 insertion(+) diff --git a/workspace.jsonc b/workspace.jsonc index af7d6ab5a9ec..db55391f7978 100644 --- a/workspace.jsonc +++ b/workspace.jsonc @@ -11,6 +11,7 @@ "resolveEnvsFromRoots": true }, "teambit.dependencies/dependency-resolver": { + "enableGlobalVirtualStore": true, "allowScripts": { "@apollo/protobufjs": true, "@parcel/watcher": true, From 7ab837201901300caf5f58b6ca2289ae5eb84707 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sun, 9 Aug 2026 10:05:50 +0200 Subject: [PATCH 2/4] ci: keep the global virtual store inside the persisted workspace With enableGlobalVirtualStore, node_modules holds only symlinks into /links. pnpm's default store is ~/.local/share/pnpm, outside setup_harmony's persist_to_workspace root, so every job that merely attaches the workspace received dangling symlinks (lint died on a missing node_modules/oxlint/bin/oxlint). Point store-dir under ~/bit and persist the links directory. files/ is left out: the consumers of this workspace read node_modules, they never fetch packages, and carrying the content-addressable store too would duplicate every package in the archive. Co-Authored-By: Claude Opus 5 (1M context) --- .circleci/config.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c207f2a68133..05201a88dc89 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -662,9 +662,15 @@ jobs: # tracked changes) — without it, a duplicate user-agent line lands on master every # release and, being last in the file, overrides bit-repo-local for local installs too. # the flag lives in .git/index, so it survives persist_to_workspace into later jobs. + # + # store-dir moves the store — and with it the global virtual store at /links, + # which every node_modules entry symlinks into — under the persist_to_workspace root, so + # the later jobs that only attach the workspace get resolvable symlinks. pnpm's default + # store lives in ~/.local/share/pnpm, outside that root. command: > cd bit && echo "user-agent=bit-repo-circleci" >> .npmrc && + echo "store-dir=/home/circleci/bit/.pnpm-store" >> .npmrc && git update-index --skip-worktree .npmrc && bbit install # `bbit install` compiles as part of the install, but that pass can fall back to the @@ -683,7 +689,10 @@ jobs: root: . paths: - bit - - .pnpm-store + # only the global virtual store, not the content-addressable files/ it hardlinks from: + # the consumers of this workspace read node_modules, they never fetch packages, and + # carrying files/ too would duplicate every package in the archive. + - .pnpm-store/*/links - store_artifacts: path: ~/Library/Caches/Bit/logs - store_artifacts: From 187da47807e7097d45cf188a991ae8008932250d Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sun, 9 Aug 2026 10:16:14 +0200 Subject: [PATCH 3/4] ci: set the pnpm store dir where the config reader actually reads it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit store-dir in .npmrc is ignored: pnpm keeps only npm-compatible settings there, and bit installs through @pnpm/napi's config reader, which takes storeDir from the pnpm-workspace.yaml cascade. The store stayed in ~/.local/share/pnpm, outside the persist_to_workspace root, so the node_modules symlinks reaching into /links still dangled in every job that only attaches the workspace. Write a CI-only pnpm-workspace.yaml instead, and check the store landed inside the workspace before persisting it — a persist path that matches nothing is not an error, so the previous attempt failed as a MODULE_NOT_FOUND in lint rather than in the job that got it wrong. Co-Authored-By: Claude Opus 5 (1M context) --- .circleci/config.yml | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 05201a88dc89..f02bc52220a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -663,15 +663,20 @@ jobs: # release and, being last in the file, overrides bit-repo-local for local installs too. # the flag lives in .git/index, so it survives persist_to_workspace into later jobs. # - # store-dir moves the store — and with it the global virtual store at /links, - # which every node_modules entry symlinks into — under the persist_to_workspace root, so - # the later jobs that only attach the workspace get resolvable symlinks. pnpm's default - # store lives in ~/.local/share/pnpm, outside that root. + # storeDir moves the store — and with it the global virtual store at //links, + # which every node_modules entry symlinks into — under the persist_to_workspace root, so the + # later jobs that only attach the workspace get resolvable symlinks. pnpm's default store + # lives in ~/.local/share/pnpm, outside that root. it has to go in pnpm-workspace.yaml: + # .npmrc only carries npm-compatible settings, and store-dir there is silently ignored by + # the config reader bit installs through (see scopes/dependencies/pnpm/read-config.ts). + # the repo has no committed pnpm-workspace.yaml; info/exclude keeps this CI-only one from + # being picked up by anything that stages untracked files. command: > cd bit && echo "user-agent=bit-repo-circleci" >> .npmrc && - echo "store-dir=/home/circleci/bit/.pnpm-store" >> .npmrc && git update-index --skip-worktree .npmrc && + echo "storeDir: /home/circleci/bit/.pnpm-store" > pnpm-workspace.yaml && + echo "pnpm-workspace.yaml" >> .git/info/exclude && bbit install # `bbit install` compiles as part of the install, but that pass can fall back to the # default TypeScript compiler for components whose env is still being imported - notably @@ -685,6 +690,16 @@ jobs: # - run: cd bit && ls -l node_modules/@babel # - run: cd bit && ls -l node_modules/@babel/cli/bin # - run: cd bit && ls -l node_modules/.bin + - run: + # a persist path that matches nothing is not an error, so without this check a store that + # landed outside the workspace root only shows up much later, as a MODULE_NOT_FOUND on a + # dangling node_modules symlink in whichever job runs first. + name: verify the global virtual store sits inside the persisted workspace + command: | + set -e + ls -d /home/circleci/bit/.pnpm-store/*/links + ls -l bit/node_modules/oxlint + test -e bit/node_modules/oxlint/bin/oxlint - persist_to_workspace: root: . paths: From 82d9421d5cda2bed9e295bd4dbe218fefe13dc95 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Sun, 9 Aug 2026 10:28:24 +0200 Subject: [PATCH 4/4] test: load the mocha reporters by path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The global virtual store puts every package's real directory outside the project, so a package that requires an undeclared dependency by bare name no longer finds it: node resolves from the realpath, and the ancestor walk out of /links/@/mocha/... never reaches the project's node_modules the way the walk out of node_modules/.pnpm/mocha@11.1.0/ did. mocha requires the reporter, and mocha-multi-reporters requires each reporter it composes, so both hops died — taking down every e2e job before a single test ran. Both accept a path resolved against cwd, which is the repo root for these scripts. Co-Authored-By: Claude Opus 5 (1M context) --- mocha-multi-reporters-config.json | 2 +- package.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mocha-multi-reporters-config.json b/mocha-multi-reporters-config.json index 4501ddb97115..e524b539c00f 100644 --- a/mocha-multi-reporters-config.json +++ b/mocha-multi-reporters-config.json @@ -1,5 +1,5 @@ { - "reporterEnabled": "spec, mocha-junit-reporter", + "reporterEnabled": "spec, ./node_modules/mocha-junit-reporter", "mochaJunitReporterReporterOptions": { "mochaFile": "${MOCHA_FILE}", "outputs": "true" diff --git a/package.json b/package.json index 5b4a1e27fe47..3a049af45c67 100644 --- a/package.json +++ b/package.json @@ -31,14 +31,14 @@ "lint-full": "./scripts/validate-import-named-aspects.sh && ./scripts/validate-no-ramda.sh && node scripts/validate-pkg-exist-in-pkg-json.js && npm run lint", "format": "prettier \"{e2e,scopes,components}/**/*.{ts,js,jsx,css,scss,tsx,md,mdx}\" --write", "prettier:check": "prettier --list-different \"{e2e,scopes,components}/**/*.{ts,js,jsx,css,scss,tsx,md,mdx}\"", - "mocha-circleci": "cross-env NODE_OPTIONS='--no-warnings --max-old-space-size=5000' registry-mock prepare && mocha --require ./babel-register --reporter mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors --exit", + "mocha-circleci": "cross-env NODE_OPTIONS='--no-warnings --max-old-space-size=5000' registry-mock prepare && mocha --require ./babel-register --reporter ./node_modules/mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors --exit", "e2e-test": "registry-mock prepare && cross-env NODE_OPTIONS=--no-warnings mocha --require ./babel-register './e2e/**/*.e2e*.ts'", "e2e-test:debug": "npm run e2e-test --debug", - "e2e-test-circle": "cross-env NODE_OPTIONS='--no-warnings --max-old-space-size=5000' mocha --require ./babel-register --reporter mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors --exit './e2e/**/*.e2e*.ts'", + "e2e-test-circle": "cross-env NODE_OPTIONS='--no-warnings --max-old-space-size=5000' mocha --require ./babel-register --reporter ./node_modules/mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors --exit './e2e/**/*.e2e*.ts'", "performance-test": "mocha --require ./babel-register ./e2e/performance/*.performance*.ts", "performance-test:debug": "npm run performance-test --debug", - "performance-test-circle": "mocha --require ./babel-register --reporter mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors ./e2e/performance/*.performance*.ts", - "bit-hub-test-circle": "mocha --require ./babel-register --reporter mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors ./e2e/bit-hub/*.ts", + "performance-test-circle": "mocha --require ./babel-register --reporter ./node_modules/mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors ./e2e/performance/*.performance*.ts", + "bit-hub-test-circle": "mocha --require ./babel-register --reporter ./node_modules/mocha-multi-reporters --reporter-options configFile=mocha-multi-reporters-config.json --colors ./e2e/bit-hub/*.ts", "clean-node-modules": "find . -type d -name node_modules -prune -exec rm -rf '{}' +", "setup": "bit install && bit compile", "full-setup": "rm -rf node_modules/.bin/bit && bit install && husky && bit compile",