Skip to content

Commit c7f6f63

Browse files
authored
Migrate Perseus to pnpm (#2202)
## Summary: This PR migrates this repo from `yarn` to [pnpm](pnpm.io). The version of Yarn we are using is very outdated and is no longer supported. Khan Academy has made an engineering-wide decision to adopt pnpm as its "package manager of choice" and so let's adopt! Notable changes: * Use `workspace:` syntax for in-repo dependencies * Use `catalog:` syntax for peer/dev dependencies (easier "global" upgrade of these) - and Github _just_ added support for `catalog:` support Dependabot [_yesterday_](https://github.blog/changelog/2025-02-04-dependabot-now-supports-pnpm-workspace-catalogs-ga/)!! * Build system is simplified because we don't have to worry about build order * Issue: LEMS-2825 ## Test plan: `pnpm build` `pnpm dev` `pnpm start` # storybook `pnpm cypress:ci` Author: jeremywiebe Reviewers: mark-fitzgerald, jeremywiebe, benchristel, handeyeco, jeresig, jandrade, kevinb-khan Required Reviewers: Approved By: mark-fitzgerald, handeyeco, benchristel Checks: ✅ Publish npm snapshot (ubuntu-latest, 20.x), ✅ Check for .changeset entries for all changed files (ubuntu-latest, 20.x), ✅ Cypress (ubuntu-latest, 20.x), ✅ Lint, Typecheck, Format, and Test (ubuntu-latest, 20.x), ✅ Publish Storybook to Chromatic (ubuntu-latest, 20.x), ✅ Check builds for changes in size (ubuntu-latest, 20.x) Pull Request URL: #2202
1 parent 56b4ee6 commit c7f6f63

File tree

46 files changed

+18735
-15529
lines changed

Some content is hidden

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

46 files changed

+18735
-15529
lines changed

.changeset/empty-lemons-agree.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
---
2+
"perseus-build-settings": minor
3+
"@khanacademy/perseus-dev-ui": minor
4+
"@khanacademy/kas": minor
5+
"@khanacademy/keypad-context": minor
6+
"@khanacademy/kmath": minor
7+
"@khanacademy/math-input": minor
8+
"@khanacademy/perseus": minor
9+
"@khanacademy/perseus-core": minor
10+
"@khanacademy/perseus-editor": minor
11+
"@khanacademy/perseus-linter": minor
12+
"@khanacademy/perseus-score": minor
13+
"@khanacademy/pure-markdown": minor
14+
"@khanacademy/simple-markdown": minor
15+
---
16+
17+
Tooling:
18+
19+
- Switching to `pnpm`.

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"forwardPorts": [6006],
1313

1414
// Use 'postCreateCommand' to run commands after the container is created.
15-
"postCreateCommand": "yarn install"
15+
"postCreateCommand": "pnpm install"
1616

1717
// Configure tool-specific properties.
1818
// "customizations": {},

.github/actions/shared-node-cache/action.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,17 @@ inputs:
1212
runs:
1313
using: "composite"
1414
steps:
15-
- name: Set up node
15+
- uses: pnpm/action-setup@v4
16+
name: Install pnpm
17+
with:
18+
run_install: false
19+
20+
- name: Use Node.js ${{ inputs.node-version }}
1621
uses: actions/setup-node@v4
1722
with:
1823
node-version: ${{ inputs.node-version }}
19-
cache: yarn
24+
cache: pnpm
2025

21-
- name: yarn install
26+
- name: pnpm install
2227
shell: sh
23-
run: yarn install
28+
run: pnpm install ---frozen-lockfile

.github/workflows/maintenance.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ jobs:
4747
4848
## Reviewing notes:
4949
50-
There should only be changes to the `yarn.lock` file in
50+
There should only be changes to the `pnpm-lock.yaml` file in
5151
this PR. Check that there is only 1 `caniuse-lite` package
52-
reference in the `yarn.lock` file (the intent of this
52+
reference in the `pnpm-lock.yaml` file (the intent of this
5353
update is to ensure that `caniuse-lite` is on the latest
5454
version and that there aren't multiple, conflicting
5555
versions that different tools might see).
5656
5757
If everything looks fine, please approve this PR and then
58-
land it (either with the Big Green Merge Button ™️ or by
58+
land it (either with the Big Green Merge Button™️ or by
5959
using `git land <this pr #>` in a terminal).

.github/workflows/node-ci.yml

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,17 @@ jobs:
3535
with:
3636
fetch-depth: 0
3737

38+
- uses: pnpm/action-setup@v4
39+
name: Install pnpm
40+
with:
41+
run_install: false
42+
3843
- name: Force Node version
3944
uses: actions/setup-node@v4
4045
with:
4146
node-version: ${{ matrix.node-version }}
42-
cache: yarn
47+
# Note that we don't specify 'cache: pnpm' here because we
48+
# don't install node_modules in this workflow/job!
4349

4450
- name: Get changed files
4551
uses: Khan/actions@get-changed-files-v2
@@ -60,7 +66,7 @@ jobs:
6066
ssh-private-key: ${{ secrets.KHAN_ACTIONS_BOT_SSH_PRIVATE_KEY }}
6167

6268
- name: Verify changeset entries
63-
uses: Khan/[email protected]
69+
uses: Khan/actions@check-for-changeset-v1
6470
with:
6571
changed_files: ${{ steps.match.outputs.filtered }}
6672

@@ -86,55 +92,55 @@ jobs:
8692

8793
- name: Check formatting
8894
run: |
89-
yarn -s prettier --check .
95+
pnpm prettier --check .
9096
9197
- id: js-files
9298
name: Find .js(x)/.ts(x) changed files
9399
uses: Khan/actions@filter-files-v1
94100
with:
95101
changed-files: ${{ steps.changed.outputs.files }}
96102
extensions: ".js,.jsx,.ts,.tsx"
97-
files: "yarn.lock"
103+
files: "pnpm-lock.yaml"
98104

99105
- id: eslint-reset
100106
uses: Khan/actions@filter-files-v1
101107
name: Files that would trigger a full eslint run
102108
with:
103109
changed-files: ${{ steps.changed.outputs.files }}
104-
files: ".eslintrc.js,package.json,yarn.lock,.eslintignore"
110+
files: ".eslintrc.js,package.json,pnpm-lock.yaml,.eslintignore"
105111

106112
# Linting / type checking
107113
- name: Eslint
108114
uses: Khan/actions@full-or-limited-v0
109115
with:
110116
full-trigger: ${{ steps.eslint-reset.outputs.filtered }}
111-
full: yarn lint packages
117+
full: pnpm lint packages
112118
limited-trigger: ${{ steps.js-files.outputs.filtered }}
113-
limited: yarn lint {}
119+
limited: pnpm lint {}
114120

115121
- name: Typecheck
116122
if: (success() || failure()) && steps.js-files.outputs.filtered != '[]'
117-
run: yarn typecheck
123+
run: pnpm typecheck
118124

119125
- name: Build types
120126
if: (success() || failure()) && steps.js-files.outputs.filtered != '[]'
121-
run: yarn build:types
127+
run: pnpm build:types
122128

123129
# Run tests for our target matrix
124130
- id: jest-reset
125131
uses: Khan/actions@filter-files-v1
126132
name: Files that would trigger a full jest run
127133
with:
128134
changed-files: ${{ steps.changed.outputs.files }}
129-
files: "jest.config.js,package.json,yarn.lock,test.config.js,test.transform.js"
135+
files: "jest.config.js,package.json,pnpm-lock.yaml,test.config.js,test.transform.js"
130136

131137
- name: Jest
132138
uses: Khan/actions@full-or-limited-v0
133139
with:
134140
full-trigger: ${{ steps.jest-reset.outputs.filtered }}
135-
full: yarn jest
141+
full: pnpm jest
136142
limited-trigger: ${{ steps.js-files.outputs.filtered }}
137-
limited: yarn jest --passWithNoTests --findRelatedTests {}
143+
limited: pnpm jest --passWithNoTests --findRelatedTests {}
138144

139145
# We use STOPSHIP internally to mark code that's not safe to go live yet.
140146
# We use an if block because we want to return the exact inverse of what
@@ -153,13 +159,20 @@ jobs:
153159
- name: Checking out latest commit
154160
uses: actions/checkout@v4
155161

162+
# MUST be before we install node_modules as that depends on finding
163+
# Cypress binaries in this cache!
164+
- uses: actions/cache@v4
165+
with:
166+
path: ~/.cache/Cypress
167+
key: cypress-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
168+
156169
- name: Install & cache node_modules
157170
uses: ./.github/actions/shared-node-cache
158171
with:
159172
node-version: ${{ matrix.node-version }}
160173

161174
- name: Run tests
162-
run: yarn cypress:ci
175+
run: pnpm cypress:ci
163176

164177
- name: Upload Screenshots
165178
uses: actions/upload-artifact@v4
@@ -219,6 +232,7 @@ jobs:
219232
uses: actions/checkout@v4
220233
with:
221234
fetch-depth: "0"
235+
222236
- name: Ensure main branch is available
223237
run: |
224238
REF=$(git rev-parse HEAD)
@@ -301,7 +315,7 @@ jobs:
301315
302316
Example:
303317
```sh
304-
yarn add @khanacademy/perseus@${{
318+
pnpm add @khanacademy/perseus@${{
305319
steps.publish-snapshot.outputs.npm_snapshot_tag }}
306320
```
307321

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ jobs:
4848

4949
- name: Build Storybook
5050
# Generate a static version of storybook inside "storybook-static/"
51-
run: yarn build-storybook
51+
run: pnpm build-storybook
5252

5353
- name: Deploy to GitHub pages
5454
uses: JamesIves/[email protected]
@@ -62,7 +62,7 @@ jobs:
6262
id: changesets
6363
uses: changesets/action@v1
6464
with:
65-
publish: yarn publish:ci
65+
publish: pnpm publish:ci
6666
env:
6767
# We use a Personal Access Token here rather than the GITHUB_TOKEN
6868
# so that it will trigger our other actions. The token has to be on

.prettierignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
.nvmrc
2828
.prettierignore
2929
LICENSE
30-
yarn.lock
30+
pnpm-lock.yaml
31+
pnpm-workspace.yaml
3132

3233
coverage/
3334
docs/

.storybook/main.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import viteConfig from "../dev/vite.config";
1+
import viteConfig from "../vite.config";
22
import {mergeConfig} from "vite";
33

44
import type {StorybookConfig} from "@storybook/react-vite";
@@ -59,6 +59,11 @@ const config: StorybookConfig = {
5959
viteFinal: async (config, {configType}) => {
6060
return mergeConfig(config, {
6161
...viteConfig,
62+
define: {
63+
// This is used to determine if we are running in a
64+
// Dev/Storybook environment.
65+
"process.env.STORYBOOK": "true",
66+
},
6267
build: {
6368
// Vite 5 has a bug with how it builds `url(data: )` urls when
6469
// it inlines SVGs. Given this is mostly used for static
@@ -72,7 +77,7 @@ const config: StorybookConfig = {
7277
},
7378
// Fix from: https://github.com/storybookjs/storybook/issues/25256#issuecomment-1866441206
7479
assetsInclude: ["/sb-preview/runtime.js"],
75-
plugins: [...viteConfig.plugins, lessWrapper],
80+
plugins: [...(viteConfig.plugins ?? []), lessWrapper],
7681
});
7782
},
7883
staticDirs: ["../static"],

.storybook/preview.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import * as React from "react";
22
import {color} from "@khanacademy/wonder-blocks-tokens";
33
import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
4-
import {Dependencies} from "@khanacademy/perseus";
54

6-
import {DependenciesContext} from "../packages/perseus/src/dependencies";
5+
import {
6+
setDependencies,
7+
DependenciesContext,
8+
} from "../packages/perseus/src/dependencies";
79
import {
810
storybookTestDependencies,
911
storybookDependenciesV2,
@@ -14,7 +16,7 @@ import type {Preview} from "@storybook/react";
1416
// IMPORTANT: This code runs ONCE per story file, not per story within that file.
1517
// If you want code to run once per story, see `StorybookWrapper`.
1618

17-
Dependencies.setDependencies(storybookTestDependencies);
19+
setDependencies(storybookTestDependencies);
1820

1921
const preview: Preview = {
2022
// These decorators apply to all stories, both inside and outside the

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ This repo is a constellation of sub-repos for showing exercise content. Please s
1818
### Prerequisites
1919

2020
- [Node.js v20](https://nodejs.org/en/blog/announcements/v20-release-announce)
21-
- [Yarn](https://yarnpkg.com/lang/en/docs/install/)
21+
- [pnpm](https://pnpm.io/)
2222

2323
### Installation
2424

2525
To install Perseus, you need to run the following commands:
2626

27-
#### `yarn`
27+
#### `pnpm install`
2828

2929
Installs project dependencies and tooling
3030

3131
### Using Storybook
3232

33-
The components and widgets of Perseus are developed using [Storybook](https://github.com/storybookjs/storybook). After you clone the project and get dependencies installed, the next step is to start storybook by running `yarn storybook`. This will start a server and give you a playground to use each component.
33+
The components and widgets of Perseus are developed using [Storybook](https://github.com/storybookjs/storybook). After you clone the project and get dependencies installed, the next step is to start storybook by running `pnpm storybook`. This will start a server and give you a playground to use each component.
3434

3535
### Using Changesets
3636

37-
We use [changesets](https://github.com/changesets/changesets) to help manage our versioning/releases. Before pushing a new PR, add a changeset by running `yarn changeset`. Commit and submit that with the PR.
37+
We use [changesets](https://github.com/changesets/changesets) to help manage our versioning/releases. Before pushing a new PR, add a changeset by running `pnpm changeset`. Commit and submit that with the PR.
3838

3939
### Updating Dependencies
4040

@@ -53,13 +53,13 @@ cd packages/perseus-editor
5353
2. Run the following command to update the dev dependencies and the peer dependencies.
5454
```
5555
// All dependencies
56-
yarn add --dev [dependency name]
56+
pnpm add --dev [dependency name]
5757
// Include this too if webapp is using this dependency
58-
yarn add --peer [dependency name]
58+
pnpm add --peer [dependency name]
5959
6060
// Example
61-
yarn add --dev @khanacademy/wonder-blocks-button
62-
yarn add --peer @khanacademy/wonder-blocks-button
61+
pnpm add --dev @khanacademy/wonder-blocks-button
62+
pnpm add --peer @khanacademy/wonder-blocks-button
6363
```
6464

6565
## Contributing
@@ -79,14 +79,14 @@ Perseus is a monorepo - a single repository that ships multiple npm packages. Ge
7979
3. ☢️ We don’t use deploy branches in Perseus
8080
4. Start a dev server
8181

82-
a. `yarn start` will start [Storybook](https://storybook.js.org/) on [localhost:6006](http://localhost:6006)
82+
a. `pnpm start` will start [Storybook](https://storybook.js.org/) on [localhost:6006](http://localhost:6006)
8383

84-
b. `yarn dev` will start the custom Dev UI on
84+
b. `pnpm dev` will start the custom Dev UI on
8585
[localhost:5173](http://localhost:5173/)
8686

8787
5. Do stuff
88-
6. `yarn test` will run [Jest](https://jestjs.io/)/[RTL](https://testing-library.com/docs/react-testing-library/intro/) tests; `yarn cypress` will run [Cypress](https://www.cypress.io/) tests
89-
7. `yarn changeset` will walk you through creating a [changeset](https://github.com/changesets/changesets) (we generally stick to [semver](https://semver.org/))
88+
6. `pnpm test` will run [Jest](https://jestjs.io/)/[RTL](https://testing-library.com/docs/react-testing-library/intro/) tests; `pnpm cypress` will run [Cypress](https://www.cypress.io/) tests
89+
7. `pnpm changeset` will walk you through creating a [changeset](https://github.com/changesets/changesets) (we generally stick to [semver](https://semver.org/))
9090
8. ☢️ Empty changesets should be considered an exception to the rule and should generally be avoided
9191
9. `git add` and `git commit`
9292
10. `git pull-request` will walk you through creating a pull request

0 commit comments

Comments
 (0)