Skip to content

Build the JS render client at packaging time instead of committing it#214

Merged
adhami3310 merged 4 commits into
mainfrom
claude/compiled-js-git-repo-b091f0
Jul 22, 2026
Merged

Build the JS render client at packaging time instead of committing it#214
adhami3310 merged 4 commits into
mainfrom
claude/compiled-js-git-repo-b091f0

Conversation

@adhami3310

Copy link
Copy Markdown
Member

Why

The minified render-client bundles (python/xy/static/index.js, standalone.js) were committed to git — two ~291 KB generated files. Any branch that touched the TypeScript client regenerated them, so they were a constant source of merge conflicts. This treats them like the Rust core: a generated artifact built during packaging, never version-controlled.

What

  • Un-track + git-ignore the two bundles.
  • Build hook builds them (hatch_build.py): runs node js/build.mjs for both the wheel and sdist targets, gated on Node via XY_REQUIRE_NODE / XY_SKIP_NODE (mirroring the existing XY_*_CARGO switches). Registered under targets.wheel.hooks.custom and targets.sdist.hooks.custom.
  • [tool.hatch.build] artifacts re-includes the git-ignored bundles into both distributions. (A build hook's build_data["force_include"] turned out not to be honored by the sdist builder — artifacts is the mechanism that works for both.)
  • CI: dropped the node js/build.mjs --check freshness gate everywhere (nothing committed to compare against). Dist jobs set XY_REQUIRE_NODE=1 and let the hook build; jobs that read the bundle on disk build it explicitly. Added Node to install_without_rust and python_floor (both run bundle-reading tests).
  • Kept in sync: verify_ci_workflow.py, verify_local.py, build.mjs (removed --check mode), Makefile, the widget.py error message, dossier §33, production-readiness.md, CLAUDE.md.

Impact

End users are unaffected — published wheels and sdists carry the client prebuilt, no Node needed (including pip install <sdist>). The only change: building from a raw git clone now needs Node + npm ci, exactly as it already needs Rust for the core.

Validation

  • ✅ sdist built with bundles deleted → hook rebuilds them → verify_sdist.py passes
  • ✅ pure wheel carries xy/static/*.js at the correct path → verify_wheel.py --expect-pure passes
  • ✅ wheel built from the unpacked sdist with Node and cargo hidden still carries the client → pip install <sdist> needs no Node
  • ✅ editable install builds the bundles into the tree via the hook
  • verify_ci_workflow.py + 187 verifier/local tests pass; ruff check/format clean

(The native-core test suite wasn't run locally — crates.io is unreachable in the dev sandbox — but that path is exercised by CI.)

The minified render-client bundles (python/xy/static/{index,standalone}.js)
were committed to git, so every branch that touched the client produced merge
conflicts in a 291 KB generated file. Treat them like the Rust core: a
generated artifact built during packaging, never version-controlled.

- git-ignore the two bundles; the hatch build hook now runs `node js/build.mjs`
  for both the wheel and sdist targets (gated on Node via XY_REQUIRE_NODE /
  XY_SKIP_NODE, mirroring the cargo switches).
- Include them via `[tool.hatch.build] artifacts` so the git-ignored bundles
  ride into both distributions (a build hook's force_include is not honored by
  the sdist builder; artifacts is).
- Drop the `node js/build.mjs --check` freshness gate everywhere (nothing
  committed to compare against); dist CI jobs set XY_REQUIRE_NODE and let the
  hook build, consumers build explicitly. Add Node to install_without_rust and
  python_floor (both run bundle-reading tests).
- Keep verify_ci_workflow / verify_local / build.mjs / Makefile / widget error
  message / dossier §33 / production-readiness / CLAUDE.md in sync.

End users are unaffected: published wheels and sdists carry the client prebuilt
(no Node needed, incl. `pip install <sdist>`). Only building from a raw clone
now needs Node + `npm ci`, exactly as it already needs Rust for the core.
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown

Greptile Summary

This PR builds the JavaScript render client during packaging instead of storing generated bundles in Git. The main changes are:

  • Adds wheel and sdist hooks that build the required client bundles.
  • Includes the generated bundles as Hatch build artifacts.
  • Removes the obsolete read-only bundle check command.
  • Updates CI and release jobs to provision or build the client where needed.
  • Ignores and removes the generated bundles from version control.

Confidence Score: 5/5

This looks safe to merge.

Required distribution builds now fail when the client bundles cannot be produced. Active callers no longer invoke the removed read-only check mode.

No blocking issues were found in the updated code.

T-Rex T-Rex Logs

What T-Rex did

  • Validated the packaging lifecycle by comparing the pre-change log to the post-change results and confirming that old bundles were removed, Vite regenerated bundles, the sdist was verified, archive bundle listings were produced, and the process exited with code 0.
  • Confirmed that the distribution tarball xy-0.0.1.tar.gz is the real generated and verified sdist.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
hatch_build.py Builds the render client for wheel and sdist targets and fails required builds when the bundles cannot be produced.
pyproject.toml Registers the custom sdist hook and includes both generated client bundles as build artifacts.
js/build.mjs Removes the read-only check mode and always writes freshly built bundles.
package.json Removes the script that called the deleted check mode.
.github/workflows/ci.yml Updates CI jobs to provision Node and build the client where tests or distributions require it.
.github/workflows/release.yml Moves release artifact generation to the packaging hook and removes duplicate client build steps.

Reviews (3): Last reviewed commit: "Address review: require the render clien..." | Re-trigger Greptile

Comment thread hatch_build.py Outdated
Comment thread js/build.mjs
CI jobs that install xy from a source checkout (matplotlib_reference, codspeed,
docs quality/production) hit a FileNotFoundError once the bundle stopped being
committed: HTML export and the reflex_xy adapter link-out both read
python/xy/static/*.js, which those jobs never built.

Make the build hook self-provisioning instead of patching each job: when the
bundle is absent and a source tree is present, run `npm ci` (if needed) then
`node js/build.mjs` — the JS analogue of compiling the Rust core from source.
It only triggers when the bundle is missing, so installs from a published
wheel/sdist stay completely Node-free (they carry it prebuilt).

- hatch_build.py: _provision_js returns early if bundles already exist; else
  builds from js/ source, provisioning vite/tsc via npm ci first.
- Pin Node 22 on the source-install jobs that lacked it (matplotlib_reference,
  codspeed, docs quality) so the hook's build uses a vite-compatible Node.
- Fix export.py's stale "npm run build" hint (no such script) to match widget.py.

Verified locally: with both the bundle and node_modules removed, `uv build`
runs npm ci + build and the wheel/sdist carry the client at the right paths.
…t-repo-b091f0

# Conflicts:
#	python/xy/static/index.js
#	python/xy/static/standalone.js
@codspeed-hq

codspeed-hq Bot commented Jul 22, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 102 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing claude/compiled-js-git-repo-b091f0 (9a299f8) with main (d53f8c6)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

…cript

Greptile review of #214:

- P1 (incomplete distributions succeed silently): the render client is
  mandatory in every wheel — verify_wheel.py requires static/*.js in both
  native and pure wheels — unlike the *optional* native core. So make it
  required by default instead of opt-in: a from-source wheel/sdist build that
  can neither find nor build the bundle now fails loudly rather than shipping a
  broken, client-less distribution. XY_SKIP_NODE=1 is the explicit opt-out
  (prebuilt-bundle steps, or a deliberately client-less build). Replaces the
  opt-in XY_REQUIRE_NODE, dropped from the CI/release dist jobs accordingly.

- P2 (npm check script mutates): package.json's `check` script still passed the
  removed `--check` flag, so `npm run check` silently rebuilt in place instead
  of validating. Nothing invokes it; removed it (build/typecheck remain).

Verified locally: with node hidden and no bundle, `uv build` now fails with a
clear "render client is required" error by default, and succeeds client-less
only under XY_SKIP_NODE=1. verify_ci_workflow + 187 verifier tests pass.
@adhami3310
adhami3310 merged commit 8a99500 into main Jul 22, 2026
50 checks passed
Sign up for free to 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