Skip to content

Commit c3a429f

Browse files
pete-murphyclaude
andauthored
Migrate to spago v1 (#316)
* feat: migrate client to latest spago Resolves #315 * feat: migrate staging to latest spago, package set and bring compiler up to date with latest Hackage release (0.15.15) * doc: __DEVELOPMENT__ flag * chore: update CHANGELOG * fix: npm command in CI * docs: remove irrelevant stuff from RELEASE.md * fix: avoid exceeding max-heap * fix: spago fetch in start script * fix: trim package set by "cannot run in playground", record exclusions Addresses PR feedback that the trim in 0fd79d9 left no record of what was removed or why, so the next `spago install $(spago ls packages ...)` per RELEASE.md would have silently reinstalled the full set. - Add staging/excluded-packages.txt: 148 packages, one line each with the reason. The only criterion is that a package cannot execute in the playground: its foreign modules (or a dependency's) import bare JS specifiers that the import map in client/public/frame.html does not shim. Packages previously cut for size despite being runnable (spec, spec-mocha, test-unit, pmock, react-basic-dom-beta, css-frameworks) are back in. - Filter the RELEASE.md install step through the exclusion list, and document the criterion and the un-exclude path (add a shim, delete the line). - Upgrade the package set 77.6.0 -> 77.10.2; spago.{yaml,lock} regenerated by running the documented steps for real: 492 of 640 packages installed. The 77.10.2 cannot-run closure is identical to 77.6.0's; both packages new to the set (harmonia, yoga-format) are clean. - Verified at production RTS settings (-M3G): cold boot compiles all 3,798 modules (peak residency 1,165 MB); warm restart peaks at 1,907 MB, ~160 MB below the previous trim, leaving ~1.1 GB headroom. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: remove irrelevant note about metadata * docs: instruction for measuring heap usage * chore: use same purs version everywhere * fix: node version in ci because spago needs node:sqlite (added in v22) --------- Co-authored-by: Peter Murphy <26548438+ptrfrncsmrph@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 729af7b commit c3a429f

23 files changed

Lines changed: 12089 additions & 617 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ jobs:
6262
- uses: actions/checkout@v4
6363
- uses: actions/setup-node@v4
6464
with:
65-
node-version: "20"
65+
node-version: "22"
6666

6767
- name: Build client code
6868
run: |
@@ -71,7 +71,7 @@ jobs:
7171
npm run build
7272
npm run test
7373
npm run build:production
74-
npm run bundle
74+
npm run bundle:production
7575
7676
- name: Check SharedConfig.purs versions
7777
run: |
@@ -80,7 +80,7 @@ jobs:
8080
node updateSharedConfigVersions.mjs sharedConfig.out
8181
diff src/Try/SharedConfig.purs sharedConfig.out || {
8282
echo 'PureScript and/or package set versions in "client/src/Try/SharedConfig.purs"'
83-
echo 'do not match the versions extracted from "stack.yaml" and "staging/packages.dhall".'
83+
echo 'do not match the versions extracted from "stack.yaml" and "staging/spago.yaml".'
8484
echo 'Please run "cd client && npm run updateConfigVersions". CI will fail until then.'
8585
exit 1
8686
}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ New features:
1111
Bugfixes:
1212

1313
Other improvements:
14+
- Bump PureScript to `0.15.15` (#316 by @pete-murphy)
15+
- Bump Spago to `1.0.4` (#316 by @pete-murphy)
16+
- Update to latest package set (#316 by @pete-murphy)
17+
- Exclude packages that cannot run in the playground (unshimmed JS imports) from the package set, with per-package reasons recorded in `staging/excluded-packages.txt` (#316 by @pete-murphy)
1418

1519
## [v2026-07-03.1](https://github.com/purescript/trypurescript/releases/tag/v2026-07-03.1)
1620

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Most of these features can be controlled not only from the toolbar, but also usi
4747

4848
### Which Libraries Are Available?
4949

50-
Try PureScript aims to provide a complete, recent package set from <https://github.com/purescript/package-sets>. The available libraries are those listed in [`staging/spago.dhall`](./staging/spago.dhall), at the versions in the package set mentioned in [`staging/packages.dhall`](./staging/packages.dhall).
50+
Try PureScript aims to provide a complete, recent package set from <https://github.com/purescript/registry/tree/main/package-sets>. The available libraries are those listed under `package.dependencies` in [`staging/spago.yaml`](./staging/spago.yaml), at the versions in the package set named by `workspace.packageSet.registry` in that same file.
5151

5252
## Development
5353

@@ -109,13 +109,12 @@ npm run serve:(dev|production)
109109

110110
### 4. Choosing a Tag
111111

112-
The built-in examples for Try PureScript are loaded from this GitHub repository. To change the tag that the examples are loaded from, you'll need to touch three files:
112+
The built-in examples for Try PureScript are loaded from this GitHub repository. To change the tag that the examples are loaded from, you'll need to touch two files:
113113

114-
* `client/config/dev/Try.Config.purs`
115-
* `client/config/prod/Try.Config.purs`
114+
* `client/src/Try/Config.js`
116115
* `client/examples/Main.purs`, in the `fromExample` function.
117116

118-
If you are preparing a release or if you need to adjust examples in development, you should change the tag in these three places (and ensure you're using the same tag in each place!).
117+
If you are preparing a release or if you need to adjust examples in development, you should change the tag in these two places (and ensure you're using the same tag in each place!).
119118

120119
## Server API
121120

RELEASE.md

Lines changed: 76 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,42 @@ After making a new compiler release, do the following to redeploy Try PureScript
1414
2. Once the PR is merged, create a new GitHub tagged release using `vYYYY-MM-DD.X` (where `X` is usually `1` or the release attempt) as the version schema. The release will trigger a GitHub Actions build.
1515
3. Wait for the GitHub Actions build to finish (it builds the assets)
1616
4. Run `./deploy/run.sh vX-X-X.1`, replacing `vX-X-X.1` with the version you created.
17-
- Note: if you're updating the compiler, be sure to push the corresponding tag to [`purescript-metadata`](https://github.com/purescript/purescript-metadata). Otherwise, `spago install` will fail on the server and prevent the server from starting.
1817

1918
## Updating the Package Set
2019

2120
The try.purescript.org server only has a limited amount of memory. If the package set we use in deployment is too large, the server will run out of memory.
2221

2322
Before deploying an updated package set, someone (your reviewer) should check that the memory required to hold the package set's externs files does not exceed that of the try.purescript.org server.
2423

24+
To check, run the server locally from `staging/` with the production RTS flags (see `deploy/start`) plus `-s`, which prints a heap summary when the server exits:
25+
26+
```console
27+
$ cd staging
28+
$ rm -rf .psci_modules # start cold: the server's compilation cache
29+
$ (set -o noglob && stack exec trypurescript -- +RTS -N2 -A128m -M3G -s -RTS 8081 $(spago sources))
30+
```
31+
32+
Cold boot compiles the whole set, which takes a few minutes. Once the server responds on port 8081, stop the server with Ctrl-C and you should see a summary printed on exit. The number to watch is `bytes maximum residency`. You'll have to run this a _second time_, keeping the `.psci_modules` that the first run produced, to measure the peak memory usage (warm boot has higher max live heap than cold boot without cache).
33+
2534
Update the package set by doing the following. Each step is explained below:
2635

2736
### Summary
2837

2938
```sh
3039
pushd staging
31-
spago upgrade-set
32-
cat > spago.dhall << EOF
33-
{ name = "try-purescript-server"
34-
, dependencies = [] : List Text
35-
, packages = ./packages.dhall
36-
, sources = [ "src/**/*.purs" ]
37-
}
40+
cat > spago.yaml << EOF
41+
package:
42+
name: try-purescript-server
43+
dependencies: []
44+
workspace:
45+
packageSet:
46+
registry: 0.0.1
47+
extraPackages: {}
3848
EOF
39-
spago ls packages | cut -f 1 -d ' ' | xargs spago install
49+
spago upgrade
50+
spago install $(spago ls packages --json --quiet \
51+
| jq -r 'to_entries[] | select(.value.type == "registry") | .key' \
52+
| grep -vxF -f <(awk -F'\t' '!/^#/ && NF {print $1}' excluded-packages.txt))
4053
popd
4154
pushd client
4255
npm run updateConfigVersions
@@ -47,33 +60,41 @@ popd
4760

4861
### Step-by-Step Explanation
4962

50-
1. Update the `upstream` package set in `staging/packages.dhall`:
63+
1. Overwrite `staging/spago.yaml` with a placeholder config: an empty
64+
`dependencies` list and any valid registry package set as a seed (the exact
65+
version doesn't matter — the next step overwrites it). Starting from a clean
66+
file ensures packages dropped from the new set don't linger.
5167

52-
```
53-
$ pushd staging && spago upgrade-set && popd
54-
```
68+
2. Upgrade to the latest package set:
5569

56-
2. Set the `dependencies` key in the `spago.dhall` file to be an empty list. This will require a type annotation of `List Text`:
70+
```console
71+
$ spago upgrade
72+
```
5773

58-
```dhall
59-
{ name = "try-purescript-server"
60-
, dependencies = [] : List Text
61-
, packages = ./packages.dhall
62-
, sources = [ "src/**/*.purs" ]
63-
}
64-
```
74+
This rewrites `workspace.packageSet.registry` to the newest available set,
75+
replacing the seed version. Each set's JSON at
76+
<https://github.com/purescript/registry/tree/main/package-sets> records the
77+
`compiler` version it targets, which should line up with the `purescript`
78+
version in `stack.yaml` — pin the set explicitly in step 1 instead if the
79+
latest set targets a compiler you don't want.
6580

66-
3. For `staging/spago.dhall`, install all packages in the package set by running this command:
81+
3. Install every package in the new set — except those listed in
82+
`staging/excluded-packages.txt` (see [Excluded Packages](#excluded-packages))
83+
— so they're all available in the playground. This overwrites the empty
84+
`dependencies` list in `staging/spago.yaml`, then downloads, compiles, and
85+
locks them.
6786

68-
```
69-
$ spago ls packages | cut -f 1 -d ' ' | xargs spago install
70-
```
87+
```console
88+
$ spago install $(spago ls packages --json --quiet \
89+
| jq -r 'to_entries[] | select(.value.type == "registry") | .key' \
90+
| grep -vxF -f <(awk -F'\t' '!/^#/ && NF {print $1}' excluded-packages.txt))
91+
```
7192

7293
4. Update the `client/src/Try/SharedConfig.purs` file by running this command in `client`:
7394

74-
```console
75-
$ npm run updateConfigVersions
76-
```
95+
```console
96+
$ npm run updateConfigVersions
97+
```
7798

7899
5. If any packages need NPM dependencies, you can try adding their shims to the import map in `client/public/frame.html`
79100
- Open up the `generator.jspm.io` URL in the comment
@@ -86,9 +107,30 @@ popd
86107

87108
6. If `es-module-shims` releases a new version, you can calculate its SHA-384 via
88109

89-
```console
90-
$ ESM_VERSION=1.5.5
91-
$ curl -L -o es-module-shims.js "https://ga.jspm.io/npm:es-module-shims@$ESM_VERSION/dist/es-module-shims.js"
92-
$ echo "sha384-$(openssl dgst -sha384 -binary es-module-shims.js | openssl base64 -A)"
93-
$ rm es-module-shims.js
94-
```
110+
```console
111+
$ ESM_VERSION=1.5.5
112+
$ curl -L -o es-module-shims.js "https://ga.jspm.io/npm:es-module-shims@$ESM_VERSION/dist/es-module-shims.js"
113+
$ echo "sha384-$(openssl dgst -sha384 -binary es-module-shims.js | openssl base64 -A)"
114+
$ rm es-module-shims.js
115+
```
116+
117+
### Excluded Packages
118+
119+
`staging/excluded-packages.txt` lists the packages deliberately left out of the
120+
set, one per line with a tab-separated reason. The install command above
121+
filters through this file, so re-running the update steps keeps them excluded.
122+
123+
The only exclusion criterion is that a package cannot *run* in the playground:
124+
its foreign modules (or a dependency's) import bare JS specifiers — npm packages
125+
or Node builtins — that the import map in `client/public/frame.html` does not
126+
shim, so the compiled code throws as soon as it executes. Excluding these
127+
packages also keeps the server inside its memory budget (see the note at the top
128+
of this section).
129+
130+
To bring an excluded package back: add shims for its imports to the import map
131+
(step 5 above), then remove its line — along with the lines of any packages
132+
that were excluded only for depending on it — and re-run the install step.
133+
134+
When upgrading to a new package set, check any packages that are new to the
135+
set for unshimmed bare imports in their foreign modules, and append them here
136+
with a reason.

client/config/dev/Try.Config.purs

Lines changed: 0 additions & 15 deletions
This file was deleted.

client/config/prod/Try.Config.purs

Lines changed: 0 additions & 15 deletions
This file was deleted.

client/package.json

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,24 @@
33
"private": true,
44
"scripts": {
55
"clean": "rimraf output",
6-
"test": "spago test --path config/dev/Try.Config.purs",
7-
"build": "spago build --path config/dev/Try.Config.purs",
8-
"build:dev": "spago bundle-app --path config/dev/Try.Config.purs --to client.js",
9-
"build:production": "spago bundle-app --path config/prod/Try.Config.purs --purs-args '--censor-lib --strict' --to client.js",
10-
"bundle": "esbuild --outfile=public/js/index.js --bundle --minify --platform=browser --format=iife --tree-shaking=true client.js",
6+
"test": "spago test",
7+
"build": "spago build",
8+
"build:dev": "spago bundle --outfile client.js --force",
9+
"build:production": "spago bundle --outfile client.js --force --strict",
10+
"bundle:dev": "esbuild --define:__DEVELOPMENT__=true --outfile=public/js/index.js --bundle --minify --platform=browser --format=iife --tree-shaking=true client.js",
11+
"bundle:production": "esbuild --define:__DEVELOPMENT__=false --outfile=public/js/index.js --bundle --minify --platform=browser --format=iife --tree-shaking=true client.js",
1112
"serve": "http-server public/ -o / --cors=\"Access-Control-Allow-Origin: *\" -c-1",
12-
"serve:dev": "npm run build:dev && npm run bundle && npm run serve",
13-
"serve:production": "npm run build:production && npm run bundle && npm run serve",
13+
"serve:dev": "npm run build:dev && npm run bundle:dev && npm run serve",
14+
"serve:production": "npm run build:production && npm run bundle:production && npm run serve",
1415
"updateConfigVersions": "node updateSharedConfigVersions.mjs src/Try/SharedConfig.purs"
1516
},
1617
"devDependencies": {
1718
"esbuild": "^0.14.43",
1819
"http-server": "^14.1.0",
19-
"purescript": "^0.15.2",
20+
"purescript": "^0.15.15",
2021
"purescript-psa": "^0.8.2",
2122
"rimraf": "^2.5.4",
22-
"spago": "^0.20.9"
23+
"spago": "^1.0.4"
2324
},
2425
"dependencies": {
2526
"ace-builds": "^1.5.0",

client/packages.dhall

Lines changed: 0 additions & 5 deletions
This file was deleted.

client/spago.dhall

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)