@e2b/python-sdk@2.45.1
219 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
43c28b15fb |
ci(js-sdk): install Playwright Chromium without --with-deps (#1699)
Supersedes #1698 (claimed via `/sdk claim` by @mishushakov). **Please close #1698 in favour of this PR** — I have no write access to close it myself. This is a straight clone: the commit `f65f602` from #1698 is applied here unmodified (original authorship and the `Co-authored-by: Mish Ushakov` trailer preserved), with `origin/main` merged in so the branch is current — `main` had moved one commit ahead (#1693), which touches none of the two files in this PR. The diff against `main` is identical to the original: `.github/workflows/js_sdk_tests.yml` and `packages/js-sdk/package.json`. Per the claim instructions, nothing was reviewed or changed. The original description follows, verbatim. --- Closes [SDK-339](https://linear.app/e2b/issue/SDK-339/js-sdk-node-ci-legs-spend-most-of-their-time-in-playwright-install). Related: [SDK-292](https://linear.app/e2b/issue/SDK-292/run-the-full-js-sdk-unit-test-suite-in-a-browser), which introduced the `browser` project this install serves. ## Problem `packages/js-sdk/package.json` had a `pretest` hook running `npx playwright install --with-deps chromium`. `--with-deps` shells out to apt on Linux, and to a DISM Media Foundation enable on Windows, on **every** invocation — regardless of whether the workflow's Playwright browser cache hit. On one `Test JS SDK` run that hook was 90% of the Node leg: | leg | step | time | | --- | --- | --- | | node / ubuntu-22.04 | `Run Node tests` total | 23m21s | | | ↳ `pretest` (`--with-deps`) | **20m57s** | | | ↳ `vitest run` (101 files, 100 passed) | 2m23s | | node / windows-latest | `pretest` DISM Media Foundation enable | 4m31s | The browser cache worked fine (`Cache hit for: playwright-Linux-1.55.1`, restored in 3s). The time went to apt: `apt-get update` 1m42s, then 18.4 MB fetched in 18m59s at 16.1 kB/s off a stalling Azure Ubuntu mirror (`fonts-wqy-zenhei` alone stalled 7m49s). The mirror stall is transient; being on that path at all is the structural problem. Every shared library Chromium needs (`libnss3`, `libgbm1`, `libdrm2`, `libcairo2`, `xvfb`, …) was already `already the newest version` on the runner image — the only 9 new packages were CJK/Cyrillic fonts (`fonts-wqy-zenhei`, `fonts-ipafont-gothic`, `xfonts-*`) that the single headless `browser` test never renders. For comparison, in the same run the bun (2m44s), deno (2m41s) and cloudflare (2m1s) legs run the same test code with no Playwright `pretest`. ## Change - `packages/js-sdk/package.json`: replace the `pretest` hook with an explicit `playwright:install` script (`playwright install chromium`, no `--with-deps`). - `.github/workflows/js_sdk_tests.yml`: run it as its own step gated on `matrix.runtime == 'node'`, right after the existing browser-cache step, with a comment recording why `--with-deps` is omitted. Moving it out of `pretest` also keeps it off every local `pnpm test`, including for contributors who never touch the browser project. ## Usage CI installs the browser as a distinct, cache-backed step: ```yaml - name: Install Playwright Chromium if: matrix.runtime == 'node' run: pnpm run playwright:install ``` Locally, the `browser` project needs Chromium once per Playwright version: ```bash cd packages/js-sdk pnpm run playwright:install # ~7s cold, ~0.8s once installed pnpm test ``` Without it, the `browser` project fails with Playwright's own "Executable doesn't exist … run `playwright install`" message; the other projects (`unit`, `template`, `connectionConfig`) are unaffected. ## Verification Run on this branch with no prior Playwright deps installed on the machine: - `pnpm run playwright:install`: 6.5s cold (Chromium headless shell + ffmpeg, no apt), 0.78s as a no-op afterwards. - `pnpm exec vitest run --project browser`: 1 passed. Chromium launches and drives a real sandbox without any `--with-deps` packages, confirming the fonts and libs weren't load-bearing. - `pnpm build` + full `pnpm test`: 101 files, 99 passed / 1 skipped in 2m34s. The one failure is `tests/sandbox/network.test.ts > injected header is reflected by the httpbin sidecar`, which fails with `404: template 'httpbin' not found` — it needs a prebuilt `httpbin` template that this agent's API key doesn't have, unrelated to this change. - `pnpm run format`, `pnpm run lint`, `pnpm run typecheck` clean for `packages/js-sdk` (the recursive root scripts fail only in `packages/python-sdk`, where `uv` isn't installed in this environment). - `pnpm run check-deps` (knip) reports no new findings; `playwright` is still resolved as a used devDependency through the new script. No changeset: this touches only dev tooling and CI, with no change to published behavior (the `pretest`/`playwright:install` scripts are inert for consumers of the package). The commit that originally added the hook, #977, likewise shipped without one. <div><a href="https://cursor.com/agents/bc-b8c7df94-5129-496b-ae9f-0c4cb552773a?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/automations/3b1a5376-9bd3-11f1-ba66-0e7d0216e441"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/view-automation-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/view-automation-light.png"><img alt="View Automation" width="141" height="28" src="https://cursor.com/assets/images/view-automation-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Mish Ushakov <mishushakov@users.noreply.github.com> |
||
|
|
e130ba7f3b |
chore(ci): remove the Dependabot changeset workflow (#1683)
Dependabot is being turned off for this repo, so `.github/workflows/dependabot_changeset.yml` — which committed a `patch` changeset to every Dependabot PR that touched a released package's direct production dependencies — has nothing left to run on, and it goes away along with the paragraph describing it in `.changeset/README.md`. No other file referenced the workflow, and nothing about hand-written changesets changes: `npx changeset` is still the way to add one. Two follow-ups live outside this diff. The repo has no `.github/dependabot.yml` (it never did), so the bumps we've been getting came from GitHub's **Dependabot security updates** toggle — that has to be switched off in *Settings → Advanced Security* for the PRs to actually stop. And if "Dependabot Changeset" is listed as a required check in branch protection, it needs removing there or PRs will wait on a check that no longer runs; the `VERSION_BUMPER_APPID` / `VERSION_BUMPER_SECRET` credentials this workflow used are worth double-checking against the other workflows before revoking. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
034c503f1f |
ci: guard production releases to main, harden the itinerary step (#1662)
Three fixes found while porting this workflow to `e2b-dev/code-interpreter` ([#327](https://github.com/e2b-dev/code-interpreter/pull/327)). **`release.yml` can be dispatched from any branch.** It is dispatch-only and `workflow_dispatch` offers every branch in the picker, so a feature branch carrying changesets would publish real packages to npm and PyPI and push the version bump to itself. `preflight` now fails fast unless the run is on `main`; candidates cut from a branch already go through `release-candidate.yml`. **The itinerary step can block a release.** It only feeds the Slack messages, but a `changeset status` hiccup — or a typo in a future edit to that inline `node -e` block, which no YAML validation catches — fails `preflight` and stops the release. It is now `continue-on-error` with a placeholder fallback in both messages, and the transform moved to `.github/scripts/build_release_itinerary.cjs` next to `is_release.sh`, where it can be run against fixture JSON. A package missing from the label map now shows under its workspace name instead of being dropped by `order.filter`, so a fourth publishable package would not silently vanish from the notification. **`report-failure` did not list `preflight`**, so whether a broken preflight pings `#monitoring-releases` rested on `failure()` looking past the job's direct dependencies — not documented either way, so the job now depends on it explicitly. Verified: the extracted script reproduces the current output exactly for `e2b` / `@e2b/python-sdk` / `@e2b/cli`, in the same order, and handles the empty and unlabeled-package cases; workflow validated against the Actions schema; the script matches the repo's prettier config. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
6cce3fde9d |
ci: pin GitHub Actions to full commit SHAs (#1646)
Every external action in `.github/` is now referenced by a 40-character commit SHA with the release tag as a trailing comment, so a compromised or retagged upstream release cannot silently change what runs in CI — this covers 78 `uses:` refs across 15 files, leaving in-repo `./.github/...` composite-action and reusable-workflow refs as-is since they are not a supply-chain surface. Each SHA was resolved from the tag the workflow already floated on and re-verified against the GitHub API, so the change is behaviour-preserving; all 15 files were also re-checked as valid YAML. Two pins are worth a reviewer's attention: - **`pnpm/action-setup` is pinned to v4.3.0, not v4.4.0.** Upstream's `v4.4.0` tag points at the same commit as `v5.0.0`, while the floating `v4` tag we were on still resolves to v4.3.0 — pinning to v4.4.0 would have silently jumped a major. - **`actions/checkout@v3` and `actions/create-github-app-token@v1` are pinned at their latest v3/v1 SHAs rather than bumped** to v4/v2, keeping this PR to pinning alone; bumping those majors is a good follow-up. A second commit unifies `dorny/paths-filter`, which was the one action already pinned (at v3.0.3 in the Dependabot changeset workflow) and would otherwise have left the repo carrying two SHAs for the same action; its comment justified the pin as being "rather than floating on `v3`", which no longer distinguishes it now that everything is pinned, so it is rewritten to keep only the still-relevant `pull_request_target` warning. One gap this PR does not close: there is no `.github/dependabot.yml` in the repo, so nothing will keep these SHAs current and they will drift away from upstream security fixes — adding a `github-actions` ecosystem entry (which understands SHA pins with version comments and bumps both) is worth doing separately. No SDK or CLI package is touched, so no changeset is needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
9c555a12aa |
ci: add a changeset to Dependabot pull requests automatically (#1639)
Dependabot bumps of a direct production dependency of `e2b`, `@e2b/cli` or `@e2b/python-sdk` need a changeset to reach users, and they kept merging without one (#1461, #1443). This workflow commits a `patch` changeset naming every released package the bump touches, and stays out of the way otherwise — dev-only bumps, transitive-only lockfile bumps, and pull requests that already carry a hand-written changeset are all skipped. The push uses the version-bumper App token rather than `GITHUB_TOKEN`, whose commits do not start workflow runs, so the required checks would never report on the new head commit and the pull request would be unmergeable. For #1461 it would have committed `.changeset/dependabot-1461.md`: ```md --- 'e2b': patch --- Update the `undici` dependency to 7.28.0. ``` The `changes` job now skips the Dependabot metadata lookup once a changeset is on the branch, so the workflow's own commit never sends `fetch-metadata` looking for metadata on a pull request that is no longer all-Dependabot commits, and `dorny/paths-filter` is SHA-pinned as the one third-party action this trigger reaches. Verified by running the commit step against a scratch repository with the exact expression outputs for single-package, grouped multi-package and Python-only bumps, then parsing each result with changesets' own `@changesets/parse`. Two things to watch on the first live run: the org-level `verification/cla-signed` check has to accept the App's commit, and adding a commit stops Dependabot auto-rebasing the branch (`@dependabot rebase` still works, and the workflow rewrites the changeset afterwards). 🤖 Generated with [Claude Code](https://claude.com/claude-code) SDK-311 --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
2df7651ee6 |
test(sdk): run firewall transform tests against an httpbin sidecar sandbox (#1631)
Follow-up to #1632, which added the template this depends on. Now rebased onto `main`, so this is just the test change. ## Problem The firewall transform tests asserted header injection by curling `httpbin.e2b.team`, an externally hosted service the suite had to keep alive. ## Fix Starts a sidecar sandbox from the `httpbin` template instead: the rule is keyed on the sidecar's `getHost(8080)` and the assertion reads the injected header back from `/headers`, in the JS, sync Python, and async Python suites. The sidecar's ready command has already passed by the time `create` resolves, so the server is serving and no readiness polling is needed. The template name lives in one fixture per SDK — `httpbinTemplate` in `tests/template.ts` and the `httpbin_template` fixture in `conftest.py`. Also drops two comments merged in #1632 that claimed the tests spawn `e2b/httpbin`. The bare alias is what resolves, same as `base` — the team slug only appears in the display name. ⚠️ Do not merge before **Build and push prepared templates** has been dispatched with `template: httpbin` — the tests resolve the template by name and fail until it exists on the E2B team. Verified against production: all three tests pass with the injected header reflected by the sidecar, spawning the template by its bare alias with a key that owns it — the same situation as CI. SDK-304 Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
b54e8d10df |
ci: add an httpbin template and a dropdown to pick which one to build (#1632)
## Problem The firewall transform tests assert header injection by curling `httpbin.e2b.team`, an externally hosted service the suite has to keep alive. Transforms are applied by the egress proxy on the way *out* of a sandbox, so the target has to be publicly reachable — which rules out a CI service container, but not another sandbox. ## Change Adds a `httpbin` template (`templates/httpbin`): go-httpbin on `debian:bookworm-slim`, SHA256-pinned against the release `checksums.txt` the way `templates/base` pins its Node install. Neither official image can serve as an E2B base — `ghcr.io/mccutchen/go-httpbin` is distroless (no shell, and `dockerfileParser.ts:79` rejects multi-stage so the binary can't be copied out), and `kennethreitz/httpbin` is Ubuntu 18.04 whose build fails on E2B's `fuse3` install (both verified by building). `templates.yml` gains a `template` choice input (`all` / `base` / `httpbin`) rather than a second near-identical workflow file. `all` is the default so a plain dispatch behaves as before, and the DockerHub image job is skipped for `httpbin`, which has no image counterpart. The template stays **private to the E2B team**, like `base` — publishing would only expose it to other projects, and the tests that spawn it use our API key anyway. The alias is passed unprefixed because the server namespaces it with the team slug, so the name the tests resolve is **`e2b/httpbin`**; only `base` predates namespacing and stays bare. Merge this, then dispatch **Build and push prepared templates** with `template: httpbin` — #1631 stacks on top and resolves the template as `e2b/httpbin`. <sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub> SDK-304 Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
86934c779c |
ci(js-sdk): make the Cloudflare deploy test leg advisory (#1622)
## Problem The `cloudflare-deploy` leg deploys to a brand-new Cloudflare preview account on every run, so it inherits that account's propagation and read-after-write races — the fresh `workers.dev` subdomain 404s until the route reaches the edge, and the subdomain API can 404 the script it just accepted (`This Worker does not exist on your account [code: 10007]`). That fails ~1 run in 8 (6 of ~46 runs since 2026-07-24) without saying anything about the SDK, and the job gates both the required `SDK Tests Status` check and the release workflow's `publish` step — both of today's release runs were blocked by it ([30473411814](https://github.com/e2b-dev/E2B/actions/runs/30473411814), [30474175682](https://github.com/e2b-dev/E2B/actions/runs/30474175682)). ## Fix `continue-on-error` on that matrix leg only, so it still runs and still reports on every PR but no longer blocks merges or releases. The signal survives: a genuine bundle regression (e.g. the #1579 Workers startup crash) is rejected at upload deterministically, not intermittently. Follow-ups to make the leg reliably green again: #1592 (propagation poll, still open) plus a retry around `wrangler deploy --temporary` for the 10007 race. CI-only change — no changeset, no user-facing surface. Closes SDK-301 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
05b7a792ff |
fix(ci): depend on the SDK via workspace:^ so releases tag the version bump (#1619)
Closes
[SDK-298](https://linear.app/e2b/issue/SDK-298/release-tags-point-at-the-commit-before-the-version-bump).
Replaces #1615, which moved the tags after the fact instead of removing
the reason they were misplaced.
## The bug
Every published release tag pointed at the commit *preceding* its own
version bump:
```console
$ git show '@e2b/python-sdk@2.35.0:packages/python-sdk/pyproject.toml' | head -3
[project]
name = "e2b"
version = "2.34.0" # ← tagged 2.35.0
```
Anything that builds from a git tag rather than a registry got the
previous release: distro packagers, `pip install git+…@tag`, any bisect
over a release regression. `python3Packages.e2b` in nixpkgs shipped
1.5.0 as 1.5.1 from June 2025.
## Root cause: a dependency cycle
`changeset publish` tags whatever commit it publishes from, so the fix
is to commit the version bump first. That was impossible:
```
tag must point at → release commit
release commit must contain → pnpm-lock.yaml
pnpm-lock.yaml contains → integrity hash of a tarball this release uploads
```
`packages/cli` depended on `e2b` by registry range, so `changeset
version` rewrote that range and the lockfile had to be re-resolved
against a tarball that did not exist yet. The lockfile could only be
refreshed *after* publishing, which forced the commit — and therefore
the tags — after it too.
## The fix
`packages/cli`: `"e2b": "^2.36.1"` → `"e2b": "workspace:^"`.
The lockfile now records `link:../js-sdk` and stops changing at release
time, so the release commit is complete before anything is uploaded:
| | before | after |
|---|---|---|
| 1 | `pnpm run version` | `pnpm run version` |
| 2 | publish **+ tag** ← wrong commit | **commit** (local) |
| 3 | refresh `pnpm-lock.yaml` (retry ≤6×) | publish **+ tag** ← right
commit |
| 4 | commit + push | push |
That deletes the lockfile-refresh step and its whole
registry-propagation retry loop (#1589), and `createGithubReleases:
true` keeps doing the tagging and GitHub releases — no custom tagging
code. Keeping the commit local also improves recovery: a publish that
uploads *nothing* leaves the branch untouched with the changesets
intact, so re-dispatching retries cleanly.
### Landing that commit is now mandatory, so the push is resilient
Once the tags point at a local commit, getting it onto the branch stops
being bookkeeping. `changesets/action` pushes each tag as soon as
`changeset publish` reports it (`runPublish` → `git.pushTag`), *before*
it propagates a non-zero exit — so three things changed:
- **The push is gated on the tags themselves** — `git tag --points-at
HEAD` — not on whether the publish step succeeded. The tags are the
thing that has to end up reachable, so they are the right thing to ask.
A partial failure (npm succeeds, then python-sdk's `postPublish` fails
on PyPI) used to skip the push and strand tags on a commit that reached
no branch while `main` kept the old versions.
I first wrote this as `!cancelled() && (success() ||
steps.release.outputs.published == 'true')`, which was wrong in both
directions: `success()` fires in exactly the case that must be skipped
(publish exits 0 having uploaded nothing → pushes a bump with no tags,
cementing a version that can never be published), and `published` is
left unset when the action *throws* after tagging (`core.setOutput` runs
only on a normal return from `runPublish`, but `git.pushTag` happens
inside it) — so it was skipped in the very case it existed for. The tag
gate also covers `@e2b/python-sdk`, which the npm-derived output never
did, since `privatePackages.tag` is on.
- **A partial publish is reported, not swallowed.** It still has to land
— otherwise the pushed tags hang off no branch — but the bump is then on
the branch with the changesets consumed, so re-dispatching will not
retry what failed. The step now names the tags that did land and points
out that `postPublish`'s PyPI upload was skipped (the root script is
`changeset publish && ... postPublish`, so a non-zero npm exit
short-circuits it).
- **A non-fast-forward is reconciled with a merge,** not a rebase (which
would orphan the tags) and not a hard failure. Hard-failing left an
already-published release needing manual git surgery, and a naive
re-dispatch would publish nothing (versions already on the registry),
tag nothing, and report **success** — quietly recreating SDK-298.
- **`git add -A` replaces `commit -am`,** which cannot stage new files.
`changeset version` writes each `CHANGELOG.md` fresh, so no release
commit has ever contained one:
```console
$ git show --stat
|
||
|
|
4fcf7cb150 |
feat: sync API specs from infra and belt with Copybara (#1564)
The specs in `spec/` were copied from their source repos by hand and had
drifted ~2,400 lines behind infra, so they are now imported with
Copybara (`copy.bara.sky`, run in a pinned Docker image by
`scripts/fetch-spec.sh`): `make codegen` re-fetches them at the commits
pinned in `spec/infra-ref` and `spec/belt-ref` before generating, and
the generated-files CI check fails if the tracked copies don't match the
pins. Regenerating from the current pins picks up the accumulated spec
changes in the generated JS/Python clients (renamed request schemas,
`SandboxNetworkConfig`, `SandboxIam` workload identity,
`FILE_TYPE_SYMLINK`, access-token auth deprecation, volume path-metadata
tweaks). The one handwritten SDK change follows from that: the public
`FileType` enums gain a `SYMLINK` member (JS and both Python surfaces)
so entries envd reports as symlinks show up in `files.list()` and
`getInfo()`/`get_info()` instead of being silently skipped as unknown
types. The custom `spec/remove_extra_tags.py` tag-filtering script is
replaced by Redocly CLI's `filter-in` decorator (`redocly.yaml`), which
produces identical generated JS output; a `filter-out` decorator
additionally drops any operation or component schema the upstream specs
mark `x-not-implemented: true` (currently the SOCKS5
`SandboxEgressProxyConfig`/`egressProxy` surface, which infra flagged as
spec-only); each SDK's bundle now goes to its own gitignored
`spec/openapi_generated.<api>.yml` instead of both pipelines overwriting
one shared file; Python client models now list fields in spec order
instead of alphabetical (mechanical reordering only — construct models
with keyword args). Spec fetches try whatever GitHub token is available
and fall back to the tracked copies with a warning (the public infra
specs also fetch anonymously); in CI a short-lived belt-scoped token is
minted from the org-wide Autofixer GitHub App (no new secrets), so fork
PRs simply fall back for the belt spec; the CI workflows also cache the
Copybara image alongside the codegen image, and the previously ignored
`CODEGEN_IMAGE` env is honored by the Makefile.
## Usage
```sh
# update the specs: bump a pin, then regenerate
echo <infra-commit-sha> > spec/infra-ref
make codegen
# fetch a single spec without regenerating
pnpm fetch:api-spec # spec/openapi.yml from infra
pnpm fetch:envd-spec # spec/envd/ from infra
pnpm fetch:volume-spec # spec/openapi-volumecontent.yml from belt
# try the latest spec without touching the pin
E2B_INFRA_REF=main pnpm fetch:api-spec
# change which endpoint tags an SDK exposes
$EDITOR redocly.yaml && make codegen
```
```ts
// symlinks are now visible in the filesystem API (JS; same shape in Python)
const entries = await sandbox.files.list('/home/user')
const link = entries.find((e) => e.type === FileType.SYMLINK)
console.log(link?.symlinkTarget)
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
1ae3f92090 |
feat(js-sdk): run the full unit test suite in Cloudflare workerd (#1593)
## What Promotes `test:cf` from a single dist smoke test to the **full unit + connectionConfig suite running inside Cloudflare's workerd** (`@cloudflare/vitest-pool-workers`) — the same coverage `test:bun` and `test:deno` get. Locally: **74 files / 393 tests green** against prod sandboxes. The real-deploy suite (`test:cf:deploy`) is unchanged and keeps covering the built bundle on actual Cloudflare infrastructure (the pool can't reproduce bundling bugs like #1579). ## SDK fixes the suite surfaced 1. **Dropped-connection mapping for Workers** (`src/envd/rpc.ts`): workerd surfaces a sandbox connection drop as `Network connection lost`, which fell through to a cryptic `SandboxError`. It's now matched like the Node/Bun/Deno variants, so killing a sandbox mid-request surfaces as the health-checked `TimeoutError`: ```ts const cmd = await sandbox.commands.run('sleep 60', { background: true }) await sandbox.kill() await cmd.wait() // now rejects with TimeoutError('…sandbox was killed or reached its end of life…') on Workers too ``` 2. **Double connection release on stream cancel** (`src/connectionConfig.ts`): `wrapStreamWithConnectionCleanup` claimed its `release` was idempotent but had no guard — cancelling a streamed download while a read was in flight ran `cleanup()` twice (both the `cancel` callback and the pending `pull` resolving `done` fire). workerd's stream scheduling hits this deterministically; the pooled connection was double-released. Both are runtime-behavior fixes specific to the JS fetch/streams stack — no Python SDK equivalent applies. ## Test adjustments - **boot_id reads** in the two "filesystem-only pause" tests now use `commands.run('cat …')` instead of `files.read`: envd's non-gzip download path serves procfs files as an empty 200 (filed as e2b-dev/infra#3363 — Go `ServeContent` sizes them by stat, which is 0). Only clients that don't negotiate gzip (workerd's fetch) observe it; the command path sidesteps the bug while keeping the reboot assertion on all runtimes. - **runtime.test.ts** Node-host detection scenarios skip under workerd via the existing host guard (same treatment as Bun/Deno). - **Pool config filters expected unhandled-rejection shapes** via vitest's `onUnhandledError` (not the blanket `dangerouslyIgnoreUnhandledErrors`): workerd reports a rejection as unhandled unless a handler attaches within the same microtask drain — even inline `await expect(op()).rejects` trips it — and vitest never processes the `rejectionhandled` retraction on any runtime, so the suite's deliberate rejections false-positive ~60× per run. A diagnostic pairing `unhandledrejection` with `rejectionhandled` confirmed all of them are handled-late false positives (zero genuine leaks). The filter drops only the shapes the tests provoke (SDK error classes, `ConnectError`, `AbortError`, workerd's `Network connection lost.`, one test stub); unknown rejection shapes and uncaught exceptions still fail the run — verified with a planted never-handled `TypeError` (exit 1). ## CI Rebased onto #1588's per-runtime matrix: the `cloudflare` leg (already ubuntu-only there) now runs the full suite; no extra jobs added. The stale `tests/integration` exclude was dropped after #1591 removed that suite. ## Notes - Suite config needs `nodejs_compat_populate_process_env` + `E2B_API_KEY`/`E2B_DOMAIN` miniflare bindings so the SDK and tests read env like on Node. - The deleted `tests/runtimes/cloudflare/run.test.ts` (dist smoke) is fully subsumed: lifecycle coverage by the suite, bundle coverage by `test:cf:deploy` + `tests/bundle/edgeCompat.test.ts`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
00253c39cc |
feat(python-sdk): migrate envd RPC to the official connectrpc client (#1558)
Replaces the vendored `e2b_connect` client and the custom Go `protoc-gen-connect-python` plugin with the official Connect RPC client for Python ([`connectrpc`](https://github.com/connectrpc/connect-py), transport: `pyqwest`/Rust hyper), and switches the envd messages from Google's `protobuf` runtime to Buf's [`protobuf-py`](https://github.com/bufbuild/protobuf-py) (which `connectrpc` already requires) — the SDK no longer depends on the conflict-prone `protobuf` package at all, and the protoc binary drops out of the codegen image. The wire format (same protos, same JSON) is unchanged. Closing a command or watch stream early now sends `RST_STREAM`, fixing abandoned streams leaking on the shared HTTP/2 connection, and peer resets surface as typed `ConnectError`s. The plumbing mirrors the `e2b.api` layout: shared pieces (a JSON codec that ignores unknown response fields, proxy narrowing, pool tuning) live in `e2b/envd/client_shared.py`, the flavor-specific pyqwest transports (wrapped in pyqwest's retry middleware, see the retry note below) and `create_rpc_client` factories in `e2b/envd/client_sync/` and `e2b/envd/client_async/`, and the default-header/logging interceptors in `e2b/envd/interceptors.py`; `e2b/envd/rpc.py` maps `connectrpc` error codes onto the existing SDK exceptions, so the public API is unchanged (`sandbox.commands.run(...)`, `files.watch_dir(...)`, etc. work exactly as before). The REST API and file upload/download keep using `httpx`. The `proxy` connection option now applies to sandbox RPC calls too — [pyqwest 0.7.0](https://github.com/curioswitch/pyqwest/releases/tag/v0.7.0) added an httpx-style `proxy` parameter to its transports, so commands, PTY, and filesystem watch traffic follow the same proxy as the REST API and file transfers (an earlier revision of this PR could only fall back to `http_proxy`/`https_proxy` env vars for RPC): ```python sandbox = Sandbox.create(proxy="http://user:pass@localhost:8030") # REST *and* RPC (commands, PTY, watch) traffic goes through the proxy result = sandbox.commands.run("echo through-the-proxy") ``` Notes: - `e2b_connect` is no longer shipped in the wheel; code importing it directly should switch to `connectrpc` (`ConnectError`, `Code`) — SDK exception types are unchanged. - The generated `e2b.envd.*.*_pb2` modules are replaced by `protobuf-py` equivalents (`process_pb`, `filesystem_pb`) with a different message API (`Oneof` objects, `has_field`); these are internal modules — `e2b-code-interpreter` and `e2b-desktop` were verified not to import them. - RPC transports are cached per proxy URL. `httpx.URL` and `httpx.Proxy` proxies keep working for RPC calls when they reduce to a proxy URL (`httpx.Proxy` auth is folded back into the URL userinfo); `httpx.Proxy` extras that pyqwest can't express — custom headers, an `ssl_context` — raise `InvalidArgumentException` rather than being silently dropped. - Plain (non-Connect-encoded) HTTP error responses — an edge proxy or gateway answering for envd — keep the vendored client's status mapping even when they carry a JSON body that isn't a valid Connect error (e.g. a gateway's `{"code": 429}` raises `RateLimitException`, not a misleading sandbox-timeout); only JSON bodies with a valid Connect `code` string are left to connectrpc to parse. An envd response that fails to decode surfaces as a `SandboxException` with a clear message — the SDK's JSON codec raises a typed `ConnectError(INTERNAL)` at the source (connectrpc re-raises codec-raised `ConnectError`s unchanged), rather than the error being reconstructed from `__cause__` heuristics in the exception mapper. - pyqwest 0.7.0 explicit transports default to an **empty TLS root store** (0.6.2 used reqwest's defaults), so the envd transports pass `tls_include_system_certs=True`; the dependency floor is `pyqwest>=0.7.0` accordingly. - Connection retries (`E2B_CONNECTION_RETRIES`, default 3) use pyqwest's transport-level retry middleware (`pyqwest.middleware.retry`), narrowed to retry only the builtin `ConnectionError` — raised solely while establishing the connection, before the request could have reached envd — with exponential backoff. A retry can therefore never replay a delivered request, for unary and streaming RPCs alike; the previous stack's replay of unary calls whose connection dropped mid-request is dropped deliberately, since it could re-execute a delivered call (e.g. `SendInput`). Pinned by unit tests plus end-to-end tests driving the generated stubs through the middleware (`tests/test_envd_retry_transport.py`). - For async streaming calls (`commands.run`/`connect`, PTY, `watch_dir`), `request_timeout` bounds opening the stream — the wait until envd confirms with a start event, matching the JS SDK's `requestTimeoutMs` — raising `TimeoutException` and cancelling the HTTP/2 stream when exceeded (pinned frame-level in `tests/test_envd_stream_reset.py`). The running stream stays bounded by the command/watch `timeout`. The sync SDK cannot interrupt its blocking wait, so `request_timeout` is not applied to sync stream setup — both setup and the running stream are bounded by `timeout` (unlimited when `0`). - The RPC logging interceptor was upstreamed to pyqwest as a logging middleware ([curioswitch/pyqwest#192](https://github.com/curioswitch/pyqwest/pull/192)); the SDK keeps its own `LoggingInterceptor` until that merges and ships in a release the SDK can depend on. - `pyqwest` ships binary wheels for manylinux/musllinux (x86_64, aarch64), macOS arm64 + x86_64 (Intel wheels landed in 0.7.0), Windows x64, and PyPy. - The `RST_STREAM`-on-early-close behavior is pinned by frame-level regression tests (`tests/test_envd_stream_reset.py`): a plaintext HTTP/2 server records the frames the real generated clients (with the SDK's codec and interceptors) send — early close via `disconnect()`, close through the logging interceptor, and abandoning the stream must all send `RST_STREAM(CANCEL)`; normal completion must send none (sync + async). - `E2B_MAX_CONNECTIONS` no longer applies to sandbox RPC traffic: reqwest's pool bounds only idle connections per host (`E2B_KEEPALIVE_EXPIRY`, `E2B_MAX_KEEPALIVE_CONNECTIONS`), not the total number of open connections. It still applies to the REST API and file transfers. - The sync sandbox modules build one RPC client each and share it across threads — the connectrpc sync client is stateless per call over the process-global transport (verified with a 16-thread frame-level test); only the httpx envd API clients stay per-thread with their transports. - Also fixes numeric env-var parsing (`E2B_KEEPALIVE_EXPIRY`, `E2B_MAX_KEEPALIVE_CONNECTIONS`, `E2B_MAX_CONNECTIONS`, `E2B_CONNECTION_RETRIES`): an empty-string value now falls back to the default instead of raising `ValueError` at import time. |
||
|
|
9ee4414e6d |
feat(js-sdk): run the template test suite on Deno (#1595)
## What Extends the Deno vitest run (#1585) with the `template` project and fixes the real runtime bug the suite surfaced. Split out of #1594 (Bun counterpart: #1596). ```jsonc // packages/js-sdk/package.json "test:deno": "deno run -A npm:vitest run --project unit --project connectionConfig --project template", ``` ## Bug — Deno: template uploads used chunked transfer encoding Deno's native `fetch` ignores an explicit `Content-Length` header on stream bodies and falls back to `Transfer-Encoding: chunked` — exactly the failure #1243 fixed for Node, since S3-compatible presigned PUT URLs reject chunked uploads with 501. `uploadFile` now streams the spooled archive through **undici's `fetch`** (via the existing `loadUndici()` helper — undici 8 where it imports, undici 7 on Bun, global `fetch` where undici isn't resolvable, e.g. bundled apps), which honors the `Content-Length` header on stream bodies on every runtime. One upload path, no runtime sniffing. Approaches rejected along the way, all verified empirically with 1GB uploads + RSS sampling: - **File-backed `Blob` body (`fs.openAsBlob`)** — lazy on Node/Bun, but Deno's shim reads the whole file into memory eagerly (denoland/deno#32316), and Bun infers an unstrippable MIME type from the extension whose `Content-Type` breaks presigned signatures (403 against production storage). - **`node:http(s)` on Deno** — works (and is memory-bounded), but can't be unified: Bun's `node:http` ignores abort signals, and it's a second code path. Known caveat: Deno's `Readable.toWeb` shim has no backpressure, so the archive is buffered in memory during upload on Deno (Node and Bun stream in lockstep with the socket). Filed upstream as denoland/deno#36275 — accepted as Deno's to fix rather than worked around here. As part of this, `tarFileStream` became `spoolTarArchive`, returning `{ path, size, cleanup }` with caller-owned cleanup instead of a self-deleting read stream. `tests/template/uploadFile.test.ts` also asserts no `Content-Type` header is sent. ## Python SDK parity Intentionally none: `upload_file` already sends a sized file body via httpx. ## Testing - Real template builds (`tests/template/build.test.ts`, against prod S3 presigned URLs) green under **Node, Deno, and Bun** - `uploadFile` + `spoolTarArchive` suites green under Node, Deno, and Bun - `tests/template/abortSignal.test.ts` green under Deno - `pnpm build`, `lint`, `typecheck`, `prettier --check` clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
e00503b090 |
fix(ci): recover release 30006966441 and retry lockfile update with backoff (#1589)
## What happened
Release run
[30006966441](https://github.com/e2b-dev/E2B/actions/runs/30006966441)
successfully published **e2b@2.35.3** and **@e2b/cli@2.15.0** to npm and
pushed both tags, but then failed on the **Update lock file** step:
`pnpm i` ran ~6 seconds after `npm publish` and the registry had not
propagated the new version yet (`ERR_PNPM_NO_MATCHING_VERSION: No
matching version found for e2b@^2.35.3 — the latest release of e2b is
"2.35.2"`). Because that step failed, the **Commit new versions** step
was skipped, leaving main with stale versions and unconsumed changesets.
Auditing the rest of the publish path for similar races also turned up a
long-dead step: the `@e2b/sdk` alias republish.
## Changes
**Commit 1 — replay the missing release commit.** Reproduces exactly
what the bot would have committed: `pnpm run version` (consumes the
three changesets, bumps js-sdk 2.35.2 → 2.35.3 and cli 2.14.0 → 2.15.0)
followed by `pnpm i --no-link --no-frozen-lockfile` (now succeeds — the
registry has long since propagated). The only commit that landed on main
after the release was dispatched
([
|
||
|
|
e334c87f8f |
ci(js-sdk): split test workflow into parallel per-runtime jobs (#1588)
Splits the JS SDK test workflow's serial ubuntu job (Node → Cloudflare pool → Cloudflare deploy → Bun → Deno) into a `fail-fast: false` matrix of parallel legs: `node` on ubuntu and windows, plus `bun`, `deno`, `cloudflare`, and `cloudflare-deploy` on ubuntu. This cuts wall-clock time to the slowest single suite and lets a failed runtime be identified and re-run individually; Playwright setup is gated to the `node` legs (the only ones running the vitest browser project), while every leg keeps `pnpm build` since the unit bundle test and both Cloudflare configs require `dist/` in CI. A new `node-only` workflow input collapses the matrix to the two Node legs, and the staging caller in `sdk_tests.yml` sets it — Bun/Deno only run API-free unit suites and the Cloudflare legs just add sandbox load, so the extra runtimes are exercised against production only. The `workflow_call` interface stays backward-compatible, so `release.yml`, `release-candidate.yml`, and the required `SDK Tests / SDK Tests Status` check need no changes and keep the full matrix. Production coverage is identical to before — the Windows job never ran the extra suites anyway. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
e29d406887 |
feat(js-sdk): run the vitest unit suite on Deno (#1585)
## Description `pnpm test:deno` now runs the full vitest suite — the `unit` and `connectionConfig` projects, 421 sandbox/files/commands/pty/git/api/config tests — under the Deno runtime via `deno run -A npm:vitest run --project unit --project connectionConfig`, replacing the previous single dist-based smoke test (superseded — the suite covers the SDK under Deno far more thoroughly). The CI step runs on ubuntu only and covers the same projects as the Bun suite step from #1584, and the Deno pin is bumped from 1.46.3 to 2.8.1 (`setup-deno@v2`) since vitest needs Deno 2's Node compat. Also drops the `edge` vitest project: `tests/runtimes/edge/` no longer exists, so it matched zero files. Rebased on main after #1584: the off-Node fetch-caching fix originally in this PR was superseded by #1584's late-binding fix, which also makes the whole suite (including the per-proxy cache tests) pass under Deno with no test changes — so this PR is pure test/CI wiring. Verified locally on Deno 2.8.1: unit project green (349 passed, 0 failed, 29 skipped — same skips as Node), connectionConfig project green (43 passed), and Node suite green. ## Usage ```bash cd packages/js-sdk pnpm test:deno ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d417e9c4e6 |
test(js-sdk): Cloudflare Workers smoke tests (workerd pool + real deploy) (#1586)
Adds two Cloudflare Workers smoke suites for the JS SDK, both exercising the built `dist/index.mjs`: `pnpm test:cf` runs the sandbox lifecycle inside workerd via `@cloudflare/vitest-pool-workers`, and `pnpm test:cf:deploy` deploys a worker to an ephemeral Cloudflare preview account (`wrangler deploy --temporary` in the suite's global setup — no Cloudflare credentials needed) and asserts the same lifecycle against the live `workers.dev` URL, deleting the worker in teardown. The pool suite immediately caught a runtime-detection bug: Node-compat shims populate `process.release.name` inside Workers, so `getRuntime()` misdetected Workers as Node and loaded `undici`; explicit runtime markers now take precedence over the generic Node check (unit-tested, changeset included). Both suites run in CI after the build step, alongside the Bun and Deno suites (deploy suite on ubuntu only). > [!IMPORTANT] > Merge #1583 first: the deploy suite reproduces the exact #1579 startup crash (Cloudflare rejects the upload with validation error 10021, `createRequire` receiving undefined `import.meta.url`) and stays red until that fix lands. Verified green end-to-end with #1583 applied. Usage: ```bash cd packages/js-sdk && pnpm build # sandbox lifecycle inside local workerd (vitest-pool-workers) pnpm test:cf # deploy to a temporary Cloudflare preview account, test the live worker, delete it E2B_API_KEY=... pnpm test:cf:deploy ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a406f78658 |
feat(js-sdk): run the full test suite under Bun (#1584)
## What
Runs the JS SDK's full vitest suite (the `unit` and `connectionConfig`
projects — 419 tests) under the Bun runtime, replacing the previous
single `bun:test` smoke test (superseded — the suite covers the SDK
under Bun far more thoroughly).
- `pnpm test:bun` → `bunx --bun vitest run --project unit --project
connectionConfig`
- CI step in `js_sdk_tests.yml` (ubuntu only for now); the old smoke
test and its Windows Bun install are removed
## SDK fixes surfaced by running the suite under Bun
1. **Late-bind `globalThis.fetch` on non-Node runtimes**
(`src/api/http2.ts`, `src/envd/http2.ts`). The factories previously
returned the bare global `fetch` reference, so:
- every per-proxy cache entry was the identical function, and
- a `fetch` swapped in *after* client creation (msw, instrumentation,
test stubs) was either ignored or — worse — a temporary stub was
captured permanently in the module-level fetcher cache.
They now return a closure that reads `globalThis.fetch` at call time.
2. **Pin abort reasons to their `AbortController`**
(`src/connectionConfig.ts`). Bun (observed on 1.3.14) holds
`AbortSignal.reason` weakly: a timeout `DOMException` constructed inside
a `setTimeout` callback gets garbage-collected, so consumers saw
`signal.reason === undefined` instead of a `TimeoutError`. Reasons are
now also stored on the controller, keeping them alive, and a losing
(post-abort) call never overwrites the pin. No behavior change on other
runtimes.
```ts
// Before (on Bun): sandbox operations that timed out aborted with
reason undefined
// After: they abort with DOMException('Request handshake timed out
after 30000ms', 'TimeoutError')
const sbx = await Sandbox.create({ requestTimeoutMs: 30_000 })
```
## Test changes
- `tests/envd/http2.test.ts`: the "uses global fetch outside Node" test
now asserts late-binding behavior (a fetch stubbed after fetcher
creation is picked up) instead of reference identity.
- `tests/volume/volume.test.ts`: the msw-mocked `format: 'stream'` read
is split into its own test and skipped on Bun — reading `response.body`
of an msw-intercepted fetch via a reader yields an immediately-done
stream there (msw/Bun incompatibility; `.text()`/`.blob()` work). Real
network streams on Bun work and are covered by the sandbox `files.read`
tests that now run under Bun.
## Verification
Locally on Bun 1.3.14 (macOS arm64) and Node 22:
- `pnpm test:bun`: 73 files passed, 389 tests passed / 30 skipped, 0
failed
- `npx vitest run --project unit --project connectionConfig` (Node): 389
passed / 29 skipped, 0 failed
- browser project (chromium via playwright): passed
- `pnpm run format` / `lint` / `typecheck`: clean
Python SDK parity: not applicable — the changes are JS-runtime-specific
(Bun/global-fetch handling).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
e68b876689 |
fix(ci): notify success on releases that skip CLI tests (#1484)
## What `report-success` (the **Release Succeeded** Slack notification) silently skips on releases that don't bump the CLI — even when the release publishes successfully. ## Why The job used: ```yaml report-success: needs: [preflight, publish] if: needs.publish.result == 'success' ``` That `if` contains no status-check function (`always()`, `!cancelled()`, `failure()`, `success()`). When `cli-tests` is skipped — which happens whenever the changeset releases the SDKs but not the CLI (`cli-tests` has `if: needs.preflight.outputs.cli == 'true'`) — GitHub Actions **skip propagation** cascades through the dependency graph and skips `report-success` too, before its condition is meaningfully evaluated. So no success notification fires. The `publish` job avoids this exact trap because its `if` already starts with `(!cancelled())`, which is why `publish` runs (and succeeds) regardless. `report-success` just lacked the same guard. ### Evidence `report-success` skipped **iff** `cli-tests` skipped, across recent releases: | Run | `cli-tests` | `report-success` | |-----|-------------|------------------| | [28189674867](https://github.com/e2b-dev/E2B/actions/runs/28189674867) | skipped | **skipped** ❌ | | 27978450216 | skipped | **skipped** ❌ | | 28150204186 | ran ✅ | fired ✅ | | 27843301597 | ran ✅ | fired ✅ | ## Fix ```diff report-success: needs: [preflight, publish] - if: needs.publish.result == 'success' + if: (!cancelled()) && needs.publish.result == 'success' ``` `(!cancelled())` disables skip propagation so the condition is always evaluated, while `needs.publish.result == 'success'` preserves the original intent: notify only when the publish actually succeeded. `report-failure` (`if: failure()`) and `report-start` are unaffected — both already evaluate correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
423a1b7302 |
ci: seed codegen image cache from main instead of per-PR scopes (#1549)
## Why `generated_files.yml` only runs on `pull_request`, so its `cache-to: type=gha,mode=max` wrote buildkit blobs into per-PR scopes that other PRs cannot read — every new PR cold-built the codegen image (235–365s in 11 of 17 runs over the past week vs ~65s warm), and ~6 GB of duplicate blobs pushed the repo's Actions cache to 9.9 GB of the 10 GB limit, evicting the Playwright and pnpm caches that #1538 relies on. ## What Adds `codegen_image_cache.yml`, which builds the image on pushes to `main` touching its actual inputs (`codegen.Dockerfile`, `packages/connect-python/**`, or the workflow itself) and exports the cache to main's scope, readable by all PRs; it also supports `workflow_dispatch` for manual re-seeding. The PR-side build in `generated_files.yml` keeps `cache-from` but drops `cache-to`. Merging this PR triggers the first seed automatically, since the new workflow file matches its own paths filter. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
504c60999f |
ci: key Playwright browser cache on Playwright version (#1538)
## Why The Playwright browser cache in `js_sdk_tests.yml` keyed on the Node version + a hash of `packages/js-sdk/package.json`. Node bumps (e.g. #1515) and release-bot version bumps rotated the key, so PRs kept re-downloading Chromium — ~3 minutes per Windows job, twice per run (staging + production) — e.g. [this run](https://github.com/e2b-dev/E2B/actions/runs/29036879724/job/86183938330?pr=1536). The churn also created a fresh ~250 MB cache entry per OS on every release. ## What Browser binaries depend only on the Playwright version, so the cache is now keyed on the installed Playwright version (read from `node_modules` after `pnpm install`), and the two OS-conditional cache steps are collapsed into one. The key only rotates when Playwright itself is upgraded, which is exactly when a re-download is needed. On a cache hit, the `pretest` `playwright install` becomes a no-op skip instead of a download. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
e6c4e7e9d5 |
chore(js): modernize Connect/Protobuf and React test deps (#1512)
## What Modernizes the JS SDK's dependencies while remaining fully compatible with the current supported Node range (`>=20.18.1`) — no engine changes and no breaking impact for consumers. - **`@connectrpc/connect` / `@connectrpc/connect-web`:** `2.0.0-rc.3` → `^2.1.2` (off the pre-release pin onto the stable line, and switched to a `^` range). - **`@bufbuild/protobuf`:** `^2.6.2` → `^2.12.1`. - **React test deps:** `react` / `@types/react` → `^19.2.0`, and `react-dom` / `@types/react-dom` added at `^19.2.0` (previously auto-installed as v18 peers). Dev/test-only — no runtime impact. - **CI:** standardized `actions/setup-node` (mixed v3/v4/v6) to `v6` across all workflows; the three `@v3` uses were on the deprecated Node16 action runtime. No public SDK API changes — the sandbox filesystem and command RPCs use the same Connect transport configuration. ## Why undici / Node floor were dropped from this PR An earlier revision also bumped `undici` 7 → 8 and raised the Node floor to `>=22.19.0`. Usage data shows **Node 20 is still the single largest SDK runtime (~39% of sandbox creations)**, so dropping it would break the largest consumer segment via `engine-strict` install failures. undici 8 was the *only* change forcing Node 22, and undici `7.28.0` (already the latest 7.x) supports Node 20 — so undici stays at `^7.28.0` and the engine floor is unchanged. undici 8 is a good candidate for a future major once Node 20 usage declines. ## Verification - typecheck, lint (oxlint), and build pass - 22 mocked Connect/undici transport unit tests pass - 106 live filesystem/command tests pass over connectrpc `2.1.2` + undici `7.28.0` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
be4eb5fd96 |
chore(python-sdk): migrate from Poetry to uv (#1513)
Migrates the Python SDK's packaging and CI from Poetry to [uv](https://docs.astral.sh/uv/): `pyproject.toml` is converted to PEP 621 metadata using uv's native `uv_build` backend (verified to produce a byte-equivalent wheel containing both `e2b` and `e2b_connect`), `poetry.lock` is replaced with `uv.lock`, and the `Makefile`, `package.json` scripts, `.tool-versions`, `CLAUDE.md`, and all six GitHub workflows now use `uv` (`astral-sh/setup-uv` + `uv sync`/`build`/`version`/`publish`). It also drops the now-redundant explicit sync steps (since `uv run` auto-syncs) and removes the orphaned `pydoc-markdown` dev dependency, whose only consumer was deleted long ago — trimming 58 packages from the dev lockfile. ## Usage ```sh cd packages/python-sdk uv sync # install deps (replaces `poetry install`) uv run pytest # run tests uv build # build the wheel/sdist make lint # ruff (run via `uv run`) ``` No user-facing SDK change — packaging/tooling only — so no changeset is included; the published package contents are unchanged. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a39db3bb36 |
chore: switch from eslint to oxlint (#1514)
Replaces ESLint (and its `@typescript-eslint/*` and `unused-imports` plugins) with [oxlint](https://oxc.rs) across the `js-sdk` and `cli` packages. A root `.oxlintrc.json` replaces the three `.eslintrc.cjs` files, the package `lint` scripts now run `oxlint`, the related devDependencies are swapped for `oxlint`, and the lint CI path filter is updated accordingly. Formatting rules (`quotes`/`semi`/`linebreak-style`) are dropped because Prettier already enforces them, and `no-unused-vars` is set to error to preserve the previous unused-imports check. The one behavior change is that `@typescript-eslint/member-ordering` has no oxlint equivalent and is no longer enforced. `lint`, `typecheck`, and `prettier` all pass clean for both packages. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
42538836f3 |
ci: show skipped tests as skipped instead of green pass (#1486)
green passed tests is misleading. indicate when tests skipped. |
||
|
|
5c8c3ad7fc |
ci: split release workflow into production and candidate workflows (#1483)
## Why
GitHub Actions cannot conditionally show `workflow_dispatch` inputs
based on other inputs, so the single **Release** form always displayed
the six candidate-only fields even when running a production release —
confusing for anyone doing their first release.
## What
Split the combined workflow into two so each form matches its intent:
- **`release.yml` ("Release")** — production only; the `mode` dropdown
and all candidate fields are removed, leaving a form with no inputs.
- **`release-candidate.yml` ("Release candidate")** — new file
containing only the RC inputs (js-sdk, python-sdk, cli, tag, preid,
skip-tests), with the now-redundant "(candidate only)" label suffixes
dropped.
People choose by sidebar name instead of a dropdown, and the `mode ==/!=
'candidate'` job guards are gone since workflow selection does that job.
Two follow-ups from review to keep behavior intact across the split:
- **Concurrency:** both files use a shared literal group `release-${{
github.ref }}` (instead of `${{ github.workflow }}-…`) so production and
candidate releases on the same ref still serialize.
- **RC versioning:** `publish_candidates.yml` now derives RC version
suffixes from `github.run_id` instead of `github.run_number`.
`run_number` is per-workflow-file and would reset to 1 for the new
workflow, causing RC versions to go backwards (npm dist-tag downgrade /
publish collisions); `run_id` is globally unique and monotonic.
> [!NOTE]
> Any automation or docs that ran the old workflow with `-f
mode=candidate` must now target `release-candidate.yml` (no `mode`
field).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
46615194c1 |
ci: rebase before push in release commit step to avoid push race (#1469)
## Problem
The release workflow's "Commit new versions" step
(`.github/workflows/publish_packages.yml`) ran `git commit -am … && git
push` with no rebase. If any PR merged into the target branch while a
release was in flight, the remote moved ahead and the push failed as a
non-fast-forward — failing the whole release.
## Fix
Run `git pull --rebase origin "${GITHUB_REF_NAME}"` before `git push`,
so the release commit is replayed on top of the latest remote state.
```yaml
git commit -am "[skip ci] Release new versions" || exit 0
git pull --rebase origin "${GITHUB_REF_NAME}"
git push
```
Note: a narrow window remains if a PR merges between the rebase and the
push (sub-second), which would still fail; a retry loop would fully
eliminate it but adds complexity. Happy to add one if preferred.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
58566d45f6 |
ci: skip CI on docs-only changes (#1467)
## Summary PR-gated workflows filter changed paths to decide whether to run, but their package/spec globs (`packages/**`, `spec/**`) matched every `.md` file in those directories — so docs-only changes (e.g. a package README) triggered full test/lint/typecheck/codegen runs. This appends the picomatch extglob `**/!(*.md)` to those directory globs so Markdown no longer matches, across: - **sdk_tests.yml** — JS/Python/CLI suites (prod + staging) - **lint.yml** — lint/format only touch `src/`, `tests/`, and Python code, never Markdown - **typecheck.yml** — typecheck only covers `.ts`/`.py` - **generated_files.yml** — codegen derives from `spec/`, unaffected by docs The exclusion is baked into each glob rather than added as a `!**/*.md` rule because that only subtracts under `predicate-quantifier: every`, which is global to the step and would break the OR between the shared and package globs. PRs touching code (or code **and** docs together) still run as before. Note: `pkg_artifacts.yml` builds packages on every PR with no path filter at all — left as-is since gating it would require adding a `changes` job and change its always-runs behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
e03d1b88fc |
ci: Slack notifications on release start and success with itinerary (#1463)
## What The release workflow only pinged Slack on failure. This adds two notifications to the `monitoring-releases` channel, each including an itinerary of what is being released: - **Release Started** (`report-start`) — posts as soon as a production release is triggered. - **Release Succeeded** (`report-success`) — posts when the release publishes successfully. The itinerary (package name + target version) is computed once in `preflight` via `changeset status` and exposed as a job output, so both notifications stay consistent. The jobs only fire for production releases (`release == 'true'` / `publish` success), never for RC publishes. ## Example Slack messages **Started** > 🚀 A new release has been triggered ⏳ > > *Releasing:* > • JS SDK (e2b) v2.30.3 > • Python SDK (e2b) v2.29.3 > • CLI (@e2b/cli) v2.12.1 **Succeeded** > 🚀 🎉 A new version has been released successfully! :ship-it-parrot: > > *Released:* > • JS SDK (e2b) v2.30.3 > • Python SDK (e2b) v2.29.3 > • CLI (@e2b/cli) v2.12.1 --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
02bcf83adf | chore: remove Supabase (#1460) | ||
|
|
6372946856 |
ci: build prepared templates on manual trigger only (#1449)
Changes the **Build and push prepared templates** workflow to run only
on manual trigger (`workflow_dispatch`) instead of automatically on
every push to `main` touching `templates/**`.
This prevents the base template from being rebuilt and republished to
DockerHub/E2B on every change, giving control over when builds happen.
Once merged to `main`, the workflow can be triggered from the Actions UI
("Run workflow") or via `gh workflow run templates.yml`.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
a467e04144 |
fix(ci): gate SDK test steps on inputs.run so matrix checks always expand (#1447)
## Problem
The reusable SDK test workflows gated the matrix `test` job with `if:
${{ inputs.run }}`. GitHub evaluates a job's `if` *before* expanding the
matrix, so when `run` was `false` the per-OS check contexts (`JS SDK -
Build and test (ubuntu-22.04)`, `... (windows-latest)`, and the
Python/CLI equivalents) were never created — leaving required
branch-protection checks pending forever on path-filtered PRs that don't
touch the relevant package.
## Fix
Removed the job-level `if` so the matrix always expands and every per-OS
check context is created, and moved `if: ${{ inputs.run }}` onto each
step instead. When `run` is false all steps skip and the job reports
success, satisfying the required check; when true, behavior is
unchanged. Applied to `js_sdk_tests.yml`, `python_sdk_tests.yml`, and
`cli_tests.yml`.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
8c72291307 |
ci: build base template via e2b CLI in addition to DockerHub push (#1401)
Adds a `buildTemplate` CI job that builds and publishes the `base` template through the e2b CLI, running alongside the existing DockerHub image push (renamed to `buildAndPushImage`). For security, the CLI is built from source in this repo rather than installing the published `@e2b/cli` package; this build-and-global-install logic lives in a reusable composite action at `.github/actions/build-cli` so it can be shared across workflows. Removes the static `templates/base/e2b.toml` since template config is now driven by the CLI invocation, and switches the Dockerfile's `node` user/group creation to system accounts (`-r`). ## Usage Any workflow can build and install the CLI globally with a single step: ```yaml steps: - uses: actions/checkout@v4 - uses: ./.github/actions/build-cli - run: e2b template create base --memory-mb 512 ``` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1d6c45c060 |
ci: skip CI jobs when unaffected by changed paths (#1380)
Adds a `dorny/paths-filter` change-detection job to the PR-triggered workflows so jobs only run when relevant paths change: Lint/Typecheck run only when package code, spec, or lint configs change; Generated files runs only when codegen inputs/outputs change; and the JS/Python/CLI SDK tests run only when the respective SDK changes (CLI also runs on JS SDK changes since it builds against it). The SDK test jobs are gated *inside* the reusable workflows via a new `run` input rather than by skipping the caller, so the required matrix status checks still report (skipped jobs report success) and branch protection stays satisfied. Shared paths (spec, lockfiles, `package.json`, `.tool-versions`) and `workflow_dispatch` runs still trigger everything. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6e3b699072 |
chore: add issue template config (#1377)
Adds `.github/ISSUE_TEMPLATE/config.yml` to disable blank issues, forcing users to pick an existing template. Also adds contact links to the E2B Docs and the E2B Discord (reusing the invite already referenced in `CONTRIBUTING.md`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
089b8b9805 |
Remove: SDK Reference artifacts and apps/web (#1199)
<!-- CURSOR_SUMMARY --> > [!NOTE] > **Medium Risk** > Medium risk because it deletes a large subtree (`apps/web`) and removes SDK-reference generation/commit steps from the package publish workflow, which may affect downstream docs/release expectations. > > **Overview** > **Removes the docs web app and generated SDK reference content.** The PR deletes `apps/web` configs/scripts (Next.js/MDX setup, Sentry config, prebuild/sitemap generation) and removes the committed `sdk-reference` MDX pages. > > **Simplifies repo automation and ownership.** The package publish workflow no longer generates/clones/commits SDK reference docs, `CODEOWNERS` drops web/docs ownership entries, and the root ESLint config removes `@stylistic/ts` in favor of the built-in `semi` rule. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4158d777b5f3d3fa30b538e434d34ce0e697d473. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> |
||
|
|
d1d6ddf0ce |
Update Docker build to support arm64 platform (#1163)
Update Docker build to support arm64 platform |
||
|
|
85f5b8d2b3 |
chore: various bug fixes (#1145)
<!-- CURSOR_SUMMARY --> > [!NOTE] > **Low Risk** > Mostly CI/test changes plus a small logging tweak; low production impact, with main risk being altered test timing/flake behavior due to new timeout defaults. > > **Overview** > Improves release-candidate GitHub workflows by passing sanitized `tag`/`preid` via step `env` vars and quoting them when running `npm version`/`npm publish`, reducing the chance of input/expansion issues. > > Stabilizes sandbox internet-access tests in JS and Python by switching the curl target to Google’s `generate_204` endpoint and updating expected status codes. Python tests also tighten global `pytest` timeout to 30s, remove per-sandbox default timeouts from fixtures, and add 180s timeouts specifically for template test suites via new `conftest.py` files. > > CLI sandbox status polling now logs the caught error when `Sandbox.getInfo` fails (instead of silently returning `false`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 187849338dd46f9d0dd1adb0a070719ebad87309. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> |
||
|
|
571210af0c | chore: allow releases from PRs (#1142) | ||
|
|
c5e64341cc | chore(ci): add unified SDK tests workflow with staging (#1141) | ||
|
|
bffab42226 | chore: allow canary releases (#1139) | ||
|
|
59057f5a98 |
Potential fix for code scanning alert no. 3: Workflow does not contain permissions (#1135)
Potential fix for [https://github.com/e2b-dev/E2B/security/code-scanning/3](https://github.com/e2b-dev/E2B/security/code-scanning/3) In general, the fix is to declare an explicit `permissions` block that restricts the `GITHUB_TOKEN` to the minimal scope required. For this workflow, the steps only need to read the repository contents to check out code and run tooling; they do not perform any write operations against the GitHub API, so `contents: read` at the workflow or job level is sufficient. The best minimal fix is to add a top-level `permissions` block immediately after the `name: Lint` line in `.github/workflows/lint.yml`. This will apply to all jobs in the workflow (currently just `lint`) without altering any existing steps. The block should be: ```yaml permissions: contents: read ``` No additional imports, steps, or changes to the existing job logic are required. _Suggested fixes powered by Copilot Autofix. Review carefully before merging._ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > CI-only change that narrows GitHub token permissions; no application logic or deployment behavior is affected. > > **Overview** > Adds an explicit top-level `permissions` block to the `Lint` GitHub Actions workflow, restricting the default `GITHUB_TOKEN` to **read-only** repository access (`contents: read`). > > No lint job steps or behavior are changed; the update is purely to tighten workflow token scope to satisfy code-scanning guidance. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit fd6bd36e778825fcf2f1c9d758c65b36ba0a045a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> |
||
|
|
17130809ba |
Potential fix for code scanning alert no. 4: Workflow does not contain permissions (#1136)
Potential fix for [https://github.com/e2b-dev/E2B/security/code-scanning/4](https://github.com/e2b-dev/E2B/security/code-scanning/4) In general, the fix is to explicitly declare a `permissions:` block that grants only the minimal required scopes. Since this workflow only needs to read repository contents (to check out code and inspect git status/diff) and does not perform any writes via the GitHub API, `contents: read` is sufficient. The best minimally invasive fix is to add a `permissions:` block at the workflow root (top level, alongside `on:` and `jobs:`) so that it applies to all jobs in this workflow. Concretely, in `.github/workflows/generated_files.yml`, insert: ```yaml permissions: contents: read ``` between the `on:` block (lines 3–5) and the `jobs:` block (line 6). No changes to steps, images, or other configuration are required, and no additional imports or tools are needed. This documents the workflow’s needs and prevents it from gaining unintended write powers if repository defaults change. _Suggested fixes powered by Copilot Autofix. Review carefully before merging._ <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Workflow-only change that restricts token permissions; no application logic or data paths are affected. > > **Overview** > Tightens the GitHub Actions `Generated files` workflow by explicitly setting top-level `permissions` to `contents: read`. > > This addresses code-scanning guidance by ensuring the workflow token is read-only while still allowing `actions/checkout` and the generated-file checks to run. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 225a3ee2370629605e4372768b3d018031e68e9e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> |
||
|
|
c38a1819b6 |
Fix Python SDK type issues with ty type checker (#1122)
## Summary - Resolved 43 type diagnostics reported by ty (Astral's Python type checker) - Fixed Self type issues on class singletons - Added explicit type annotations for shadowed attributes - Replaced None with UNSET for auto-generated API parameters - Fixed method signature alignment for protocol matching - Added targeted type: ignore suppressions for pattern-based limitations All checks pass: ty check, ruff format, ruff check. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Mostly typing/CI changes, but some adjustments affect sandbox connect/pause overload dispatch and API response/parameter handling (`UNSET` vs `None`), which could alter edge-case runtime behavior. > > **Overview** > Fixes Python SDK static typing issues for Astral’s `ty` checker and wires typechecking into CI. > > Adds a new `Typecheck` GitHub Action plus workspace `typecheck` scripts (TS packages via `tsc`, Python SDK via `make typecheck` running `ty`), and publishes a patch changeset for `@e2b/python-sdk`. > > Across the Python SDK, adjusts type annotations and overloads (e.g., `Self`/singleton typing, `connect` overloads, optional `user`/token/domain handling), tightens API model parsing with `cast`/`Optional` checks and `UNSET` usage, and adds a few targeted `ty` ignore comments in tests/protocols to silence checker limitations. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit f66402847c40cee7e44e1aaa7caa97e271ba9978. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> |
||
|
|
2781109a26 |
Update bug_report form template (#1082)
New GitHub issue form with more specific fields for customer reports |
||
|
|
d911c55c3e |
Improve CI/CD speed for template tests (#1035)
<!-- CURSOR_SUMMARY --> > [!NOTE] > Caches Playwright binaries in JS CI and refactors JS/Python template tests to use API mocks and aliases, add Dockerfile tests, and update install APIs to single-package calls. > > - **CI**: > - Cache Playwright binaries on `ubuntu-22.04` and `windows-latest` in `.github/workflows/js_sdk_tests.yml` to speed JS SDK tests. > - **JS SDK Tests**: > - Extend `buildTemplate` options to accept `alias` in `tests/setup.ts`. > - Add `fromDockerfile` tests and switch some builds to `fromBaseImage`; add build-from-base-template test. > - Update install method tests to single-package calls for `aptInstall`, `npmInstall`, `bunInstall`, `pipInstall`. > - Tweak `makeSymlink` test order to ensure overwrite behavior. > - Overhaul stacktrace tests to use `msw` server mocks and alias-based failure mapping. > - **Python SDK Tests**: > - `build`/`async_build` fixtures accept optional `alias`. > - Add `from_dockerfile` tests (sync/async); use base image/base template where applicable. > - Update install method tests to single-package calls. > - Rewrite stacktrace tests to monkeypatch API calls with alias-based failure mapping. > - **Dependencies**: > - Add dev dependency `msw` to `packages/js-sdk/package.json`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1b7f84f4ce692f664c3ce4cdb345f4c3a028b17a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> |
||
|
|
6ff14f8b2e |
Add Windows CI to test matrix (#1020)
<!-- CURSOR_SUMMARY --> > [!NOTE] > Add Windows to CI matrices and make JS/Python utils and tests cross-platform via path handling updates. > > - **CI**: > - Add Windows to test matrices in `cli_tests.yml`, `js_sdk_tests.yml`, `python_sdk_tests.yml`; set bash shell/workdirs; disable fail-fast for some jobs. > - Python CI runs `pytest -n 4` via Poetry. > - **JS SDK**: > - Path normalization for globbing (`normalizePath`) and use of `Path.relativePosix()` in hashing and tar creation in `src/template/utils.ts`. > - **Python SDK**: > - Add `normalize_path` and use forward-slash glob patterns in `e2b/template/utils.py`. > - **Tests**: > - Make stack trace parsing robust to Windows paths; use `basename` in file assertions; adjust Python tar tests tempdir fixture handling. > - **Changeset**: add patch note for windows-related fixes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 1b8dbe4a1af642dbcb86500837e93f7998b223f6. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Joseph Lombrozo <joe.lombrozo@e2b.dev> |
||
|
|
bbeff746f8 |
Support overriding envd API URL (#1013)
This requires [infra#1448](https://github.com/e2b-dev/infra/pull/1448) first. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds support to override the sandbox API URL (E2B_SANDBOX_URL) across JS/Python SDKs, centralizes sandbox host/url logic with headers, and updates CI to build the SDK before CLI. > > - **SDKs (JS & Python)** > - Add `sandboxUrl` support in `ConnectionConfig` (env var `E2B_SANDBOX_URL`), with new helpers `getSandboxUrl`/`getHost` and shared `envdPort`. > - Refactor sandbox initialization to use `ConnectionConfig.getSandboxUrl(...)` and `getHost(...)`. > - Always attach sandbox headers `E2b-Sandbox-Id` and `E2b-Sandbox-Port` to sandbox and connect requests. > - Python: thread `sandbox_url` through opts; update async/sync connect calls to pass headers; minor fix to default `headers=None` in `e2b_connect.client.Client` stream prep. > - **CI** > - Build `packages/js-sdk` before `packages/cli`; set step `working-directory` for build/test. > - **Dependencies** > - Point `e2b` dependency in lockfile to local `../js-sdk` link. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 5dc58171af6c170f8640f49d736dbe9c571f2b21. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Mish <10400064+mishushakov@users.noreply.github.com> |
||
|
|
d2e22e3748 |
Some general pytest cleanup (#1021)
- Individual tests must complete in less than 5 minutes - Add a `make test` option that runs tests - Upgrade poetry to 2.1.1 (the lock file was generated by this version, so this just matches what we already expect) |
||
|
|
60fb009e4a |
Use OIDC for npm publish (#990)
<!-- CURSOR_SUMMARY --> > [!NOTE] > Move npm publishing to OIDC by adding id-token permissions and removing NPM_TOKEN, update actions/setup-node to v6, and upgrade npm in workflows. > > - **Workflows**: > - **OIDC for npm publish**: > - Add `permissions: id-token: write` in `workflows/publish_packages.yml` and `workflows/release.yml`. > - Remove `NPM_TOKEN` secret requirement and set `NPM_TOKEN: ""` in `changesets/action` env. > - **Node/tooling updates**: > - Bump `actions/setup-node` from `v3` to `v6` and set `registry-url` where needed. > - Add step to upgrade `npm` to `^11.6` in `publish_packages.yml`. > - Keep pnpm caching/configuration and other steps intact. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 539db5937bfe83c4222015de3dcf9c1f90764bf3. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> |