Fix network examples and speed up CI#11
Merged
jsturtevant merged 2 commits intomainfrom Mar 31, 2026
Merged
Conversation
e148143 to
fbf34e1
Compare
The network demos across all backends were silently failing — every example printed success regardless of whether HTTP requests actually succeeded. This hid two real bugs: - AnyPollable::block() polled with a tight yield_now() loop capped at 100k iterations. Real HTTPS requests take hundreds of milliseconds, but 100k yields complete in microseconds, so the guest always gave up before the response arrived. Remove the iteration cap and keep the yield so the loop waits as long as the request needs. - The HyperlightJS sandbox eval-based handler couldn't support await. The handler ran guest code through synchronous eval(), so 'await fetch(...)' created an unresolved promise that crashed outside the try/catch. Wrap the code in AsyncFunction to make top-level await work. Additionally, denied HTTP requests now return proper HTTP responses (403/500/502 status codes) instead of throwing JS exceptions via json_error. All network demos now have real assertions that will fail CI if anything regresses. An HTTPS integration test against httpbin.org covers TLS end-to-end. Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
The three Python SDK backend crates were separate Cargo workspaces with duplicate [patch] sections and isolated target/ directories, causing the full dependency tree (~500 crates) to be compiled three times. Moving them into the root workspace means the second and third builds are essentially free. This required several related fixes: - Rename native lib targets from '_native' to '_native_wasm' and '_native_js' to avoid artifact collisions in the shared target/ dir. Both crates produced lib_native.so; the last one built would overwrite the other. - Restructure python-build to use 'uv sync' with --no-install-package for the backend crates (installed separately via maturin develop) and 'uv run --no-sync' for maturin to prevent PEP 517 editable rebuilds that fail due to missing release-profile runtime binaries. - Add 'just jssandbox build' before Python SDK steps in CI so hyperlight-js-runtime is compiled in the shared target/ directory. - Clean stale cargo fingerprints before release-profile maturin builds to force the build scripts to re-run and produce the runtime binaries. - Update examples/Justfile integration dep syncs to skip building backend crates (already installed by maturin develop). Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The network demos across all backends (WASM Python, WASM JS, HyperlightJS) were silently failing — every example printed
All tests passed!regardless of whether the HTTP requests actually succeeded. This hid two real bugs and a CI design issue:The first bug was in AnyPollable::block(), which polled for HTTP responses using a tight yield_now() loop capped at 100k iterations.Real HTTPS requests take hundreds of milliseconds, but 100k yields complete in microseconds, so the guest always gave up before the response arrived. Removing the iteration cap and keeping the yield lets the loop wait as long as the request needs.
The second bug was in the HyperlightJS sandbox's eval-based handler, which couldn't support await. The handler ran guest code through synchronous eval(), so await fetch(...) created an unresolved promise that crashed outside the try/catch. Wrapping the code in AsyncFunction makes top-level await work. Additionally, denied HTTP requests were throwing JS exceptions via json_error instead of returning proper HTTP responses — now they return 403 status codes that guest code can inspect normally.
All six network demos now have real assertions (assert!/assert_eq! in Rust, assert in Python) that will fail CI if anything regresses.
An HTTPS integration test against httpbin.org was added to cover TLS end-to-end.
On the CI side, the three Python SDK backend crates were separate Cargo workspaces with duplicate [patch] sections and isolated target/directories, causing the full dependency tree (~500 crates) to be compiled three times. Moving them into the root workspace means the second and third builds are essentially free.