Skip to content

Commit ffdc140

Browse files
balzssclaude
andcommitted
feat(many): migrate from npm to pnpm Phase 1
Implement Phase 1 of pnpm migration with workspace protocol and core tooling updates: Configuration: - Add pnpm-workspace.yaml defining workspace packages - Add .npmrc with pnpm configuration (hoisted node linker, strict peer deps) - Update lerna.json to use pnpm as npm client - Update root package.json with pnpm 10.18.3 as packageManager - Update engines requirement to pnpm >=10 - Update .gitignore for pnpm artifacts - Delete package-lock.json (replaced by pnpm-lock.yaml) Workspace Dependencies: - Convert all internal @instructure/* dependencies from exact versions to workspace:* - Update 94 package.json files across all packages Build Tooling: - Update scripts/bootstrap.js to use pnpm and run builds sequentially - Update packages/ui-scripts/lib/commands/bump.js to use pnpm install - Update packages/ui-scripts/lib/utils/npm.js to use pnpm whoami - Fix babel-plugin-transform-imports for pnpm workspace module resolution - Fix generate-all-tokens for pnpm workspace package resolution CI/CD: - Update all GitHub Actions workflows to use pnpm version 10 - Add pnpm/action-setup@v4 - Update caching to use pnpm lock files - Configure registry-url for npm publishing - Fix visual-regression.yml: use pnpm workspace protocol instead of global linking - Fix visual-regression.yml: explicitly install Cypress binary before tests - Add Cypress binary caching with lockfile hash (cypress-io/github-action#1138) TypeScript References: - Fix TypeScript project references in 10 packages (ui-drawer-layout, ui-expandable, ui-file-drop, ui-instructure, ui-link, ui-number-input, ui-popover, ui-radio-input, ui-text-area, ui-text-input) - Add missing tsconfig.build.json references to match package.json dependencies Regression Test Updates: - Update regression-test app to use @instructure/ui meta package - Convert all component imports to use single import from @instructure/ui - Update InstUISettingsProvider import path Documentation: - Add pnpm-migration-plan.md with complete migration strategy - Add pnpm-phase1-test-plan.md with testing procedures - Add pnpm-phase1-investigation.md analyzing implementation - Update building-instui.md and contributing.md with pnpm instructions Notes: - All Babel builds and token generation working successfully with pnpm - Cypress binary installation resolved by explicit `cypress install` step - Phase 2 will focus on fixing phantom dependencies and removing workarounds 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 7450ddc commit ffdc140

File tree

166 files changed

+51623
-41435
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+51623
-41435
lines changed

.github/workflows/deploy.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ jobs:
1313
runs-on: ubuntu-latest
1414
steps:
1515
- uses: actions/checkout@v4
16+
- uses: pnpm/action-setup@v4
1617
- name: Install Node 22
1718
uses: actions/setup-node@v4
1819
with:
1920
node-version: '22'
20-
- run: npm ci && npm run bootstrap
21+
cache: 'pnpm'
22+
- run: pnpm install --frozen-lockfile && pnpm run bootstrap
2123
- name: Set build directory and deployment path based on branch
2224
id: set-build-dir
2325
run: |
@@ -37,7 +39,7 @@ jobs:
3739
;;
3840
esac
3941
- name: Build docs-app
40-
run: npm run build:docs
42+
run: pnpm run build:docs
4143
- name: Deploy to GitHub Pages
4244
uses: JamesIves/github-pages-deploy-action@v4
4345
with:
@@ -57,13 +59,15 @@ jobs:
5759
if: github.ref == 'refs/heads/master'
5860
steps:
5961
- uses: actions/checkout@v4
62+
- uses: pnpm/action-setup@v4
6063
- name: Install Node 22
6164
uses: actions/setup-node@v4
6265
with:
6366
node-version: '22'
64-
- run: npm ci && npm run bootstrap
67+
cache: 'pnpm'
68+
- run: pnpm install --frozen-lockfile && pnpm run bootstrap
6569
- name: Build docs-app
66-
run: npm run build:docs
70+
run: pnpm run build:docs
6771
- name: Deploy to GitHub Pages
6872
uses: JamesIves/github-pages-deploy-action@v4
6973
with:

.github/workflows/manual-release-from-pr.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@ jobs:
88
- uses: actions/checkout@v4
99
with:
1010
fetch-depth: 0
11+
- uses: pnpm/action-setup@v4
1112
- uses: actions/setup-node@v4
1213
with:
1314
node-version: '22'
14-
cache: 'npm'
15+
cache: 'pnpm'
1516
- name: Install packages
16-
run: npm ci
17+
run: pnpm install --frozen-lockfile
1718
- name: Set up project
18-
run: npm run bootstrap
19+
run: pnpm run bootstrap
1920
- name: Release to NPM
2021
env:
2122
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
2223
NPM_EMAIL: ${{secrets.NPM_EMAIL}}
2324
NPM_USERNAME: ${{secrets.NPM_USERNAME}}
24-
run: npm run release -- --prRelease
25+
run: pnpm run release -- --prRelease
2526
- name: Get commit message
2627
run: | # puts the first line of the last commit message to the commmit_message env var
2728
echo "commmit_message=$(git log --format=%B -n 1 ${{ github.event.after }} | head -n 1)" >> $GITHUB_ENV

.github/workflows/manual-release-to-npm.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@ jobs:
88
- uses: actions/checkout@v4
99
with:
1010
fetch-depth: 0
11+
- uses: pnpm/action-setup@v4
1112
- name: Install Node 22
1213
uses: actions/setup-node@v4
1314
with:
1415
node-version: '22'
16+
cache: 'pnpm'
1517
- name: Install packages
16-
run: npm ci
18+
run: pnpm install --frozen-lockfile
1719
- name: Set up project
18-
run: npm run bootstrap
20+
run: pnpm run bootstrap
1921
- name: Release to NPM
2022
env:
2123
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
2224
NPM_EMAIL: ${{secrets.NPM_EMAIL}}
2325
NPM_USERNAME: ${{secrets.NPM_USERNAME}}
24-
run: npm run release
26+
run: pnpm run release
2527
- name: Get commit message
2628
run: | # puts the first line of the last commit message to the commmit_message env var
2729
echo "commmit_message=$(git log --format=%B -n 1 ${{ github.event.after }} | head -n 1)" >> $GITHUB_ENV

.github/workflows/pr-validation.yml

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,51 @@ jobs:
88
- uses: actions/checkout@v4
99
with:
1010
fetch-depth: 0
11+
- uses: pnpm/action-setup@v4
1112
- uses: actions/setup-node@v4
1213
with:
1314
node-version: '22'
14-
cache: 'npm'
15+
cache: 'pnpm'
1516
- name: Install dependencies
16-
run: npm ci
17+
run: pnpm install --frozen-lockfile
1718
- name: Bootstrap project
18-
run: npm run bootstrap
19+
run: pnpm run bootstrap
1920
- name: Lint commits
20-
run: npm run lint:commits
21+
run: pnpm run lint:commits
2122
- name: Lint code
22-
run: npm run lint:changes
23+
run: pnpm run lint:changes
2324
vitest-tests:
2425
name: Vitest unit tests
2526
runs-on: ubuntu-latest
2627
steps:
2728
- uses: actions/checkout@v4
29+
- uses: pnpm/action-setup@v4
2830
- uses: actions/setup-node@v4
2931
with:
3032
node-version: '22'
31-
cache: 'npm'
33+
cache: 'pnpm'
3234
- name: Install dependencies
33-
run: npm ci
35+
run: pnpm install --frozen-lockfile
3436
- name: Bootstrap project
35-
run: npm run bootstrap
37+
run: pnpm run bootstrap
3638
- name: Run vitest unit tests
37-
run: npm run test:vitest
39+
run: pnpm run test:vitest
3840
cypress:
3941
name: Cypress component tests
4042
runs-on: ubuntu-latest
4143
steps:
4244
- uses: actions/checkout@v4
45+
- uses: pnpm/action-setup@v4
4346
- uses: actions/setup-node@v4
4447
with:
4548
node-version: '22'
46-
cache: 'npm'
49+
cache: 'pnpm'
4750
- name: Install dependencies
48-
run: npm ci
51+
run: pnpm install --frozen-lockfile
52+
- name: Install Cypress binary
53+
run: npx cypress install
4954
- name: Bootstrap project
50-
run: npm run bootstrap
55+
run: pnpm run bootstrap
5156
- name: Run Cypress components tests
52-
run: npm run cy:component
57+
run: pnpm run cy:component
5358

.github/workflows/preview.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@ jobs:
1414
runs-on: ubuntu-latest
1515
steps:
1616
- uses: actions/checkout@v4
17+
- uses: pnpm/action-setup@v4
1718
- name: Install Node 22
1819
uses: actions/setup-node@v4
1920
with:
2021
node-version: '22'
21-
- name: Npm install and bootstrap
22-
run: npm ci && npm run bootstrap
22+
cache: 'pnpm'
23+
- name: Install and bootstrap
24+
run: pnpm install --frozen-lockfile && pnpm run bootstrap
2325
if: github.event.action != 'closed' # don't run install and bootstrap unnecessarily when pr is closed
2426
- name: Build docs-app
25-
run: npm run build:docs
27+
run: pnpm run build:docs
2628
if: github.event.action != 'closed'
2729
- uses: rossjrw/pr-preview-action@v1
2830
with:

.github/workflows/release.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,23 @@ jobs:
1111
- uses: actions/checkout@v4
1212
with:
1313
fetch-depth: 0
14+
- uses: pnpm/action-setup@v4
1415
- uses: actions/setup-node@v4
1516
with:
1617
node-version: '22'
17-
cache: 'npm'
18+
cache: 'pnpm'
1819
- name: Install packages.
19-
run: npm ci
20+
run: pnpm install --frozen-lockfile
2021
- name: Set up project.
21-
run: npm run bootstrap
22+
run: pnpm run bootstrap
2223
- name: Run tests.
23-
run: USE_REACT_STRICT_MODE=0 npm run test:vitest
24+
run: USE_REACT_STRICT_MODE=0 pnpm run test:vitest
2425
- name: Release to NPM
2526
env:
2627
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
2728
NPM_EMAIL: ${{secrets.NPM_EMAIL}}
2829
NPM_USERNAME: ${{secrets.NPM_USERNAME}}
29-
run: npm run release
30+
run: pnpm run release
3031
tag:
3132
needs: release
3233
if: "startsWith(github.event.head_commit.message, 'chore(release)')"

.github/workflows/visual-regression.yml

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,32 @@ jobs:
1313
- uses: actions/checkout@v4
1414
with:
1515
fetch-depth: 0
16+
- uses: pnpm/action-setup@v4
17+
- uses: actions/setup-node@v4
18+
with:
19+
node-version: '22'
20+
cache: 'pnpm'
21+
- name: Cache Cypress binary
22+
uses: actions/cache@v4
23+
with:
24+
path: ~/.cache/Cypress
25+
key: ${{ runner.os }}-cypress-${{ hashFiles('regression-test/pnpm-lock.yaml') }}
1626
- name: Build InstUI
17-
run: npm ci && npm run bootstrap
18-
- name: Install dependencies
19-
run: npm ci
27+
run: pnpm install --frozen-lockfile && pnpm run bootstrap
28+
- name: Install regression-test dependencies
29+
run: pnpm install --frozen-lockfile
30+
working-directory: regression-test
31+
- name: Install Cypress binary
32+
run: pnpm exec cypress install
2033
working-directory: regression-test
2134
- name: Run Cypress tests
2235
uses: cypress-io/github-action@v6
2336
env:
2437
ELECTRON_EXTRA_LAUNCH_ARGS: "--remote-debugging-port=9222"
2538
with:
26-
build: npm run build
27-
start: npm start
39+
install: false
40+
build: pnpm run build
41+
start: pnpm start
2842
working-directory: regression-test
2943
- name: Upload cypress artifact for chromatic
3044
uses: actions/upload-artifact@v4
@@ -42,11 +56,15 @@ jobs:
4256
uses: actions/checkout@v4
4357
with:
4458
fetch-depth: 0
59+
- uses: pnpm/action-setup@v4
4560
- uses: actions/setup-node@v4
4661
with:
4762
node-version: 22
48-
- name: Install dependencies
49-
run: npm ci
63+
cache: 'pnpm'
64+
- name: Build InstUI
65+
run: pnpm install --frozen-lockfile && pnpm run bootstrap
66+
- name: Install regression-test dependencies
67+
run: pnpm install --frozen-lockfile
5068
working-directory: regression-test
5169
- name: Download Cypress test results
5270
uses: actions/download-artifact@v4

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
node_modules/
22
npm-debug.log
3+
pnpm-debug.log
34
lerna-debug.log
45
./build-storybook.log
56
coverage/
@@ -9,10 +10,10 @@ __build__
910
.idea
1011
.DS_Store
1112
.viminfo
12-
.npmrc
1313
.env
1414
.env.test
1515
.tmp/
16+
.pnpm-store/
1617

1718
tsconfig.build.tsbuildinfo
1819

@@ -31,3 +32,6 @@ tsconfig.build.tsbuildinfo
3132
.claude/commands/*
3233
!.claude/commands/commit.md
3334
!.claude/commands/pr.md
35+
36+
# Playwright MCP
37+
.playwright-mcp

.npmrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Strict peer dependencies (recommended)
2+
auto-install-peers=false
3+
strict-peer-dependencies=true
4+
5+
# Workspace protocol
6+
link-workspace-packages=true
7+
8+
# Use hoisted node linker initially for compatibility
9+
node-linker=hoisted
10+
11+
# Can enable later for stricter isolation:
12+
# node-linker=isolated
13+
# shamefully-hoist=false

cypress/webpack.config.cjs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,62 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
124
const path = require('path')
25+
const fs = require('fs')
26+
27+
// Generate aliases for all @instructure/* workspace packages
28+
// This is needed because Cypress tests run from the root workspace
29+
// and need to resolve workspace package imports during testing
30+
function getWorkspaceAliases() {
31+
const packagesDir = path.resolve(__dirname, '../packages')
32+
const packages = fs.readdirSync(packagesDir)
33+
const aliases = {}
34+
35+
packages.forEach((pkg) => {
36+
const pkgPath = path.join(packagesDir, pkg)
37+
if (fs.statSync(pkgPath).isDirectory()) {
38+
const pkgJsonPath = path.join(pkgPath, 'package.json')
39+
if (fs.existsSync(pkgJsonPath)) {
40+
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8'))
41+
const pkgName = pkgJson.name
42+
if (pkgName && pkgName.startsWith('@instructure/')) {
43+
// Alias package name to its source directory
44+
aliases[pkgName] = pkgPath
45+
// Also alias deep imports (e.g., '@instructure/ui-button/src/...')
46+
aliases[`${pkgName}/src`] = path.join(pkgPath, 'src')
47+
}
48+
}
49+
}
50+
})
51+
52+
return aliases
53+
}
254

355
module.exports = {
456
mode: 'development',
557
resolve: {
658
extensions: ['.ts', '.tsx', '.js'],
59+
alias: getWorkspaceAliases(),
760
fallback: {
861
fs: false,
962
module: false,
@@ -20,4 +73,4 @@ module.exports = {
2073
}
2174
]
2275
}
23-
}
76+
}

0 commit comments

Comments
 (0)