Skip to content

fix(ci): give the web build a heap ceiling and repair stale typecheck filters - #150

Merged
elkaix merged 2 commits into
mainfrom
fix/web-build-heap-ceiling
Aug 23, 2026
Merged

fix(ci): give the web build a heap ceiling and repair stale typecheck filters#150
elkaix merged 2 commits into
mainfrom
fix/web-build-heap-ceiling

Conversation

@elkaix

@elkaixelkaix commented Aug 23, 2026

Copy link
Copy Markdown
Member

Related Issue

No filed issue. Three release jobs failed on main at ae4211f1f, and the failure then walked past two gates that should have caught it.

Problem

1. apps/pythinker-web outgrew Node's default heap on macOS runners. The workspace file editor pulled Monaco into the production module graph (1 source file importing it before #145, 4 after), and the vite build now needs a little over 2 GB of old space. macOS runners default to a ~2053 MB ceiling, so three jobs died with FATAL ERROR: ... JavaScript heap out of memory and exit 134:

WorkflowJob
Desktop Releasemac — "Build workspace"
ReleaseNative bundle darwin-x64
ReleaseNative bundle darwin-arm64

Linux and Windows runners default higher and stayed green, so CI and Nix Build never saw it.

2. A half-shipped release passed as a good one.publish-native-assets refused to publish a partial native set, exactly as designed. But a job whose dependency failed reports skipped, not failure, and redeploy-cdn only checked for failure — so it deployed 1.0.0 to the CDN while the GitHub release @pymodel/pythinker-code@1.0.0 held zero assets. Every native installer would have been sent to a release that has none. verify-cdn-release had no always(), so the same skip propagated through the graph and silently disabled the one gate that exists to catch this. Both went quiet in precisely the run that needed them.

3. Three typecheck gates in CI had gone quietly dead.pnpm --filter <name> exits 0 when the filter matches nothing, so a rename turns a gate into a no-op with nothing red to show for it:

  • @pymodel/dashboard-server and @pymodel/dashboard-web matched nothing after the packages became @pymodel/vis-server / @pymodel/vis-web.
  • pythinker-code matched the CLI directory (apps/pythinker-code), not the VS Code extension, whose package name is pythinker. The extension was never typechecked in CI, and the CLI was already covered by the tsgo step above it.

What changed

The heap ceiling lives in apps/pythinker-web's own build script. That is the one point every consumer shares — CI, Nix, both release workflows, and local builds — and it stays portable: a NODE_OPTIONS= prefix would break the Windows desktop job, which runs the same script under cmd.exe. Measured on this repo rather than guessed: 2048 MB fails, 2560 MB passes, and the build peaks near 2.2 GB. 4096 leaves headroom without reserving anything, since V8 only grows to what it needs. Rebuilding the committed bundle produced a byte-identical dist-web — only the input fingerprint moved, which confirms the change is behaviour-neutral.

redeploy-cdn now requires publish-native-assets to have succeeded whenever the release has native artifacts at all, so a release with no assets leaves the CDN on the last installable version instead of advertising one nobody can install. verify-cdn-release now runs on its own merits and reports a stale CDN rather than disappearing with it.

The CI typecheck steps become one loop that resolves each filter to a real workspace package before running it, so a stale name fails instead of passing silently. All five targets pass locally, including the VS Code extension, which this turns on for the first time.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (external PRs: the issue must have a maintainer's /approve).
  • I have added tests that prove my feature works. — mutation-tested: a bogus filter name exits 1, and 2048 MB reproduces the OOM locally.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

[skip changeset] — build and CI infrastructure only; the shipped bundle is byte-identical.

Summary by CodeRabbit

  • Bug Fixes

    • Improved release verification so incomplete native asset releases are detected instead of being silently redeployed.
    • CDN release checks now run consistently when applicable, helping identify deployment issues earlier.
  • Chores

    • Improved build reliability for larger web projects.
    • Strengthened automated type checking across all current packages.
    • Refreshed web bundle metadata to keep deployed assets synchronized.

… filters
The `apps/pythinker-web` vite build needs just over 2 GB of old space since
the workspace file editor pulled Monaco into the production graph. macOS
runners default to a ~2053 MB ceiling, so three jobs died with exit 134:
Desktop Release's `mac` and Release's `darwin-x64` / `darwin-arm64` native
bundles. Linux and Windows runners default higher and stayed green, which is
why CI never caught it.
Setting the ceiling in the package's own build script covers every consumer —
CI, Nix, both release workflows and local builds — and stays portable, unlike
a `NODE_OPTIONS=` prefix, which cmd.exe rejects on the Windows desktop job.
Measured floor: 2048 MB fails, 2560 MB passes; the build peaks near 2.2 GB.
Separately, `pnpm --filter <name>` exits 0 when nothing matches, so three
typecheck gates had gone quietly dead: `@pymodel/dashboard-server` and
`@pymodel/dashboard-web` matched nothing after the vis rename, and
`pythinker-code` matched the CLI directory instead of the VS Code extension
(`pythinker`), leaving the extension unchecked. Resolving each filter before
running it turns a stale name back into a failure.
@coderabbitai

coderabbitaiBot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6ac84c04-4ccf-4f36-a9c7-b12c93e83996

📥 Commits

Reviewing files that changed from the base of the PR and between d766fda and 2559b1c.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The PR increases the web build memory limit, updates the bundle manifest hash, replaces fixed CI typecheck steps with a fail-fast workspace loop, and strengthens release CDN verification gates.

Changes

Build and Release Validation

Layer / File(s)Summary
Web build configuration and manifest
apps/pythinker-web/package.json, apps/pythinker-code/dist-web/.web-bundle-manifest.json
The web build runs Vite through Node with a 4096 MB memory limit. The bundle manifest uses a new source hash.
Workspace typecheck loop
.github/workflows/ci.yml
CI resolves the listed workspace packages, fails when a filter matches no package, and runs each package’s typecheck script.
Release CDN verification gates
.github/workflows/release.yml
CDN redeployment requires successful native asset publication when native artifacts are expected. CDN verification evaluates after upstream jobs finish and requires a successful release. verify-cdn-release retains the package-published or release-commit condition.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk:⚪ Minimal · up to 2559b

The PR adjusts build memory limits and release/typecheck workflow behavior; no actionable merge-blocking risk remains based on the supplied evidence.

Sequence Diagram(s)

sequenceDiagram
participant release
participant publish_native_assets
participant redeploy_cdn
participant verify_cdn_release
release->>publish_native_assets: publish native assets when applicable
publish_native_assets->>redeploy_cdn: report publication status
release->>redeploy_cdn: report release status
redeploy_cdn->>verify_cdn_release: complete or skip CDN redeployment
release->>verify_cdn_release: report release status
verify_cdn_release->>verify_cdn_release: evaluate release and commit conditions
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check nameStatusExplanationResolution
Title check⚠️ WarningThe title uses a valid prefix and describes the changes, but it is 77 characters and exceeds the 72-character limit.Shorten the title to 72 characters or fewer while preserving the imperative wording and conventional-commit prefix.
Description check⚠️ WarningThe description has all required sections and detailed technical context, but it does not provide the required related issue link.Add a valid related issue link in the Related Issue section and obtain maintainer approval when required.
✅ Passed checks (3 passed)
Check nameStatusExplanation
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (1 skipped: 1 unsupported.)
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-newBot commented Aug 23, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@pymodel/pythinker-code@2559b1c
npx https://pkg.pr.new/@pymodel/pythinker-code@2559b1c

commit: 2559b1c

`publish-native-assets` correctly refuses to publish a partial native set, but
a job whose dependency failed reports `skipped`, not `failure`. `redeploy-cdn`
only checked for `failure`, so it deployed 1.0.0 to the CDN while the GitHub
release held zero assets — every native installer would have been pointed at a
release that has none. It now requires that job to have succeeded whenever the
release has native artifacts at all, leaving the CDN on the last installable
version otherwise.
`verify-cdn-release` had no `always()`, so the same upstream skip propagated
through the graph and silently disabled the one gate that exists to catch a
half-shipped release. It now runs on its own merits and reports the stale CDN
instead of vanishing with it.
@elkaix
elkaix merged commit 3acb36c into mainAug 23, 2026
20 checks passed
@elkaix
elkaix deleted the fix/web-build-heap-ceiling branch August 23, 2026 00:41
Sign up for freeto 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.

1 participant

@elkaix