Skip to content

feat(electrobun): Ship — 0.1.0, macOS-only guard, docs, package-test CI, release pipeline (PR5)#318

Merged
goosewobbler merged 17 commits into
feat/electrobun-servicefrom
feat/electrobun-ship
Jun 2, 2026
Merged

feat(electrobun): Ship — 0.1.0, macOS-only guard, docs, package-test CI, release pipeline (PR5)#318
goosewobbler merged 17 commits into
feat/electrobun-servicefrom
feat/electrobun-ship

Conversation

@goosewobbler
Copy link
Copy Markdown
Contributor

@goosewobbler goosewobbler commented Jun 2, 2026

PR5 — Ship (stack: feat/electrobun-shipfeat/electrobun-servicemain)

Final PR in the @wdio/electrobun-service stack. The service ships pre-1.0 (0.1.0), macOS-only — see #316 and the "Framework gaps" for the upstream CEF catch-22.

Done

  • Version → 0.1.0-next.0 (both packages) — releases as 0.1.0; 0.x because upstream blocks Linux/Windows/multiremote/multi-window/deeplink, 1.0 reserved for full parity.
  • macOS-only CEF runtime guardSevereServiceError in launcher.onPrepare native mode on Linux/Windows, framed around the CEF renderer, pointing to macOS / browser mode / Electrobun: support non-CEF (native-renderer) apps to fill the Linux/Windows gaps #317. Browser mode unaffected. (+ unit tests)
  • Package-test CI (macOS-only) — _ci-build-electrobun-package-app.reusable.yml (Bun/CEF, symlink-preserving tar), the electrobun arm in _ci-package.reusable.yml, ci.yml build + package jobs + ci-status, detect-changes, test:package:electrobun. Plus the fixture test harness (2-staggered-window backend, wdio.conf.ts, smoke spec, tsconfig.wdio.json) — PR3 had stubbed only a build script.
  • scripts/test-package.ts — electrobun threaded (CDP arm) + renamed the stale both service option → all (now excludes electrobun; flattened the service-detect ternary).
  • Release pipelineelectrobun scope in release.yml + _release.reusable.yml (CDP target set, no Rust/GTK) + releasekit.config.json (skip fixtures, scope:electrobun). Also fixed the pre-existing dioxus gap in the same file.
  • Docs — service README rewritten (0.1.0/macOS-only/limitations/Electrobun: support non-CEF (native-renderer) apps to fill the Linux/Windows gaps #317); root README Experimental Support section; AGENTS/ROADMAP/architecture/package-structure/e2e-testing/CONTRIBUTING.
  • Greptile feat: @wdio/electrobun-service — Electrobun desktop testing support #314 ×4 — Error-mock stack symmetry, writeRemoteDebuggingPort JSDoc, syncWebDriverWindow handle restore, drop needless async.

Notes

  • ReleaseKit generates release notes + CHANGELOG; no hand-authored docs/release-notes/ file.
  • The recurring E2E - Electron/Dioxus [Windows] CI reds are known-flaky and unrelated (re-run clears them).

goosewobbler and others added 3 commits June 2, 2026 12:51
…aceholder

The "start at 0.1.0" wording conflated the in-repo dev placeholder with the published
version. The repo convention is a `X.Y.0-next.0` placeholder that releases as stable
`X.Y.0` on `latest` (with `-next.N` prereleases on `next`) — so the pre-1.0 form is a
`0.1.0-next.0` placeholder releasing as `0.1.0`, NOT a bare `0.1.0`. Clarify both the
"When upstream blocks" version section and the Phase 1 conventions line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The service ships pre-1.0 (0.x) because upstream blocks Linux/Windows/multiremote/
multi-window/deeplink — 1.0 is reserved for full parity once those gaps fill. Relabel
the dev placeholder from 1.0.0-next.0 (which implied a 1.0 target) to 0.1.0-next.0;
it releases as stable 0.1.0 on `latest`, with 0.1.0-next.N prereleases on `next`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ly in 0.x)

CEF-rendered Electrobun apps are only drivable on macOS in the 0.x line: on Linux/Windows
CEF's failed-persist:default-profile fallback serves no /json, so Chromedriver can never
attach (upstream-blocked). Throw a clear SevereServiceError in launcher.onPrepare's native
branch instead of letting users hit a cryptic CDP-attach timeout — the message points to
macOS / browser mode and the native-renderer follow-up (#317). Browser mode is unaffected.
Tests stub process.platform (darwin happy-path + linux/win32 guard) per the dioxus pattern.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

This is the final PR in the @wdio/electrobun-service stack, shipping version 0.1.0 as macOS-only. It adds the CEF platform guard, package-test CI infrastructure, release pipeline wiring, and a set of fixes from the previous review round.

  • macOS guardcefNativeModeMacOnly throws a SevereServiceError in launcher.onPrepare for native mode on Linux/Windows; browser mode is explicitly unaffected; unit tests cover both platforms and the cross-mode interaction.
  • Package-test CI — new _ci-build-electrobun-package-app.reusable.yml builds the CEF fixture as a symlink-preserving tarball; _ci-package.reusable.yml gains the electrobun arm (download → extract → pack → --skip-build test); ci.yml adds the two new macOS-ARM jobs and wires them into ci-status; test-package.ts renames bothall and adds the full electrobun service branch.
  • Bug fixessyncWebDriverWindow now restores the caller's original window handle on the no-match path; mock.ts adds stack symmetry; connection.ts drops the needless async/unhandled-promise pattern.

Confidence Score: 5/5

Safe to merge — all changed paths are well-tested, the platform guard and window-handle restore are correct, and the CI wiring follows the established patterns in the repo.

The logic changes are small and well-scoped: the macOS guard is a fail-fast throw correctly positioned after the browser-mode early return; the syncWebDriverWindow restore is a targeted fix with a corresponding mock added to the test; the mock.ts and connection.ts changes are cosmetic/symmetry fixes. The CI additions follow the existing Dioxus/Tauri patterns exactly. No existing behaviour is regressed.

fixtures/package-tests/electrobun-app/wdio.conf.ts uses globSync from node:fs which requires Node 22+, while the service itself advertises Node 18/20 support.

Important Files Changed

Filename Overview
packages/electrobun-service/src/launcher.ts Adds macOS-only CEF runtime guard in onPrepare for native mode; correctly placed after the browser-mode early-return so browser mode is unaffected; throws the new cefNativeModeMacOnly error on Linux/Windows.
packages/electrobun-service/src/errors.ts Adds cefNativeModeMacOnly factory function returning SevereServiceError; message includes platform name, browser-mode escape hatch, and #317 follow-up link.
packages/electrobun-service/src/service.ts Captures the session's original window handle before the syncWebDriverWindow probe loop and restores it on the no-match path, preventing the session from being stranded on the last probed handle.
packages/electrobun-service/src/mock.ts Adds stack to the serialised __wdioError object so mockRejectedValue errors arrive with the same shape as errors captured through the read-call-data path.
packages/electrobun-service/test/launcher.spec.ts Adds a setPlatform helper to stub process.platform per-test (defaulting to darwin), and two new test cases covering the macOS-only guard on Linux and Windows; a browser-mode Linux test is also added.
fixtures/package-tests/electrobun-app/wdio.conf.ts New WDIO config for the package-install smoke fixture; uses globSync from node:fs (Node 22+) to locate the built .app bundle; mirrors the e2e config pattern.
.github/workflows/_ci-build-electrobun-package-app.reusable.yml New reusable workflow that builds the Electrobun package-test fixture on macOS with Bun/CEF and uploads the result as a symlink-preserving tarball to avoid .app framework symlink loss.
scripts/test-package.ts Renames both → all, adds the electrobun service arm (build/pack/install/detect), excludes electrobun-* fixtures from the all run, and flattens the service-detection ternary to a prefix-lookup array.
.github/workflows/_ci-package.reusable.yml Adds the electrobun arm: downloads the tarball artifact, extracts it with symlink-preservation, packs the service + CDP bridge, and runs the package test with --skip-build; both → all rename propagated consistently.
releasekit.config.json Adds electrobun scope mapping (@wdio/electrobun-*) and pre-existing dioxus fixtures/scopes that were missing; also adds electrobun and dioxus example/e2e-app names to the skip list.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[launcher.onPrepare] --> B{browser mode?}
    B -- yes --> C[coerce browserName → chrome\nreturn early — no platform check]
    B -- no\nnative mode --> D{process.platform === darwin?}
    D -- no\nLinux / Windows --> E[throw cefNativeModeMacOnly\nSevereServiceError — fast fail]
    D -- yes\nmacOS --> F[resolveElectrobunApp + verifyCefRenderer\nper-capability]
    F --> G[onWorkerStart: clone bundle\npin CDP port → spawn app]
    G --> H[onWorkerEnd: stop app]

    subgraph CI Package Test Pipeline
        I[detect-changes: run_electrobun?] -- true --> J[build job\nDownload JS artifacts]
        J --> K[build-electrobun-package-app-macos-arm\nBun + CEF build → tar upload]
        K --> L[package-electrobun-macos-arm\nDownload tar → extract → pack service → test:package:electrobun --skip-build]
    end
Loading

Fix All in Claude Code Fix All in Cursor

Reviews (6): Last reviewed commit: "test(electrobun): bump e2e specFileRetri..." | Re-trigger Greptile

Comment thread packages/electrobun-service/test/launcher.spec.ts Outdated
goosewobbler and others added 14 commits June 2, 2026 14:20
…describe

Greptile P2 (#318): the "native-mode macOS guard does not fire in browser mode" case
exercises browser mode but sat in the onPrepare native-mode describe. Move it beside the
analogous mixed-mode test in the browser-mode describe so each block is self-contained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…th→all

Thread the electrobun service through scripts/test-package.ts (CDP archetype like
electron: service + native-types + electrobun-cdp-bridge; a macOS-only skipBuild path
that copies the pre-built CEF `build/` bundle rather than rebuilding). Electrobun reuses
the existing cdpBridgePath field — it never co-packs with electron (not part of the
aggregate), so the field is unambiguous per run.

Also rename the stale `both` SERVICE option → `all` (it was a two-service artifact; now
means electron+tauri+dioxus — electrobun is excluded, it's macOS-only and always run via
its own `--service=electrobun` job). The moduleType `both` (cjs+esm) is unrelated and
unchanged. Flatten the now-three-way service-detection into a prefix lookup table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the package-test CI plumbing for @wdio/electrobun-service (macOS-only, CEF):
- _ci-build-electrobun-package-app.reusable.yml — builds the electrobun-app fixture
  (Bun/CEF) and uploads a symlink-preserving tar (like the e2e build, not the zip
  upload-archive the dioxus/tauri package builds use).
- _ci-package.reusable.yml — `electrobun` arm (download + untar the bundle, pack the
  service + cdp-bridge, run test:package:electrobun --skip-build); also rename the
  service input `both` → `all` to match scripts/test-package.ts.
- ci.yml — build-electrobun-package-app-macos-arm + package-electrobun-macos-arm jobs,
  both gated on run_electrobun and added to ci-status needs.
- _ci-detect-changes — add the new build workflow to infra_electrobun.
- package.json — test:package:electrobun script.

Fixture test harness (wdio.conf + smoke spec + `test` script) lands in the next commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…obun-app fixture

PR3 stubbed the fixture with only a `build` script. Add the wdio test harness so the
package-test can actually run:
- src/bun/index.ts: open TWO staggered CEF windows (a single window exposes no /json
  target after CEF's persist:default→global-context fallback — same workaround the e2e
  fixture uses).
- wdio.conf.ts: macOS-only .app resolution, @wdio/electrobun-service native mode,
  browserVersion pinned to CEF's Chromium 147, specFileRetries for the residual race.
- test/smoke.spec.ts: install smoke — launch, attach over CDP, read #app-title + #status.
- tsconfig.wdio.json (+ @types/mocha) and a `test` script.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- mock.ts: include `stack` when serialising an Error mock value (mockRejectedValue),
  matching the read-call-data path — no asymmetry for users inspecting thrown errors.
- electrobunConfig.ts: fix writeRemoteDebuggingPort JSDoc — the userDataDir param is
  supported but the launcher intentionally never passes it (the disproven approach),
  contradicting the old "isolates each worker's profile" claim.
- service.ts: syncWebDriverWindow restores the caller's original window handle on the
  no-match path instead of stranding the session on the last-probed handle.
- connection.ts: drop the unnecessary `async` on the ws 'message' handler (the body is
  sync; only the catch is async) — `void this.#errorHandler(error)`.
- service.spec.ts: add getWindowHandle to the browser mock for the restore path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`all` (the no-arg default of `pnpm test:package`) scanned every fixture, including
electrobun-app — but buildAndPackService('all') never packs the electrobun tarball, so
testExample threw "Electrobun service packages not available", crashing a bare local run.
CI is unaffected (it always passes an explicit --service), but the local DX regression was
real. Exclude electrobun-* from `all` to match the documented intent ("never part of all");
run it via `--service=electrobun`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…moke

The package-test run showed the harness works (CEF build + launch + CDP attach + execute
all green); only the #status assertion was wrong — the mainview script overwrites #status
to "Application loaded successfully" on load, not the static "Ready for testing". Assert
the script-set text (which also confirms the view JS ran) and poll for it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- release.yml: add `electrobun` to the workflow_dispatch scope choices.
- _release.reusable.yml: target set `@wdio/electrobun-service,@wdio/electrobun-cdp-bridge`
  + a build case (CDP, no Rust/build:rust — mirrors electron). No GTK/Rust toolchain steps.
- releasekit.config.json: skip the private electrobun fixtures (electrobun-app-example,
  electrobun-e2e-app) from versioning/publish; map scope:electrobun → @wdio/electrobun-*.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- electrobun-service/README.md: rewrite from the stale PR1 foundation copy — 0.1.0,
  macOS-only, CEF-renderer requirement, quick start, the supported surface, and the
  upstream-blocked known limitations (Linux/Windows, multiremote, multi-window, deeplink)
  with the #317 link.
- README.md: add the @wdio/electrobun-service entry + package-tree + framework line.
- AGENTS.md: add Electrobun to supported frameworks + the package tree.
- ROADMAP.md: mark Phase 5 shipped (0.1.0, macOS-only) with the upstream caveat + #317.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ng gap)

Surfaced while wiring electrobun: dioxus was missing from both releasekit.config.json
sections that every other framework has. Latent because @wdio/dioxus-service is
unpublished, but a future dioxus release would otherwise try to publish its private
fixtures (electron/tauri fixtures are private yet still explicitly skipped) and
scope:dioxus would resolve to no packages. Add dioxus-app-example + wdio-dioxus-e2e-app
to version.skip and scope:dioxus → @wdio/dioxus-*.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…or docs

- README.md: move electrobun into a dedicated "Experimental Support" section (0.x,
  macOS-only, CEF-required, #317) so it's clearly distinct from the 1.0 frameworks.
- architecture.md / package-structure.md: add the service + cdp-bridge to the package
  tables + the browser.electrobun.* API-injection list.
- e2e-testing.md: add the electrobun test dir + wdio.electrobun.conf.ts (macOS-only).
- CONTRIBUTING.md: add the Electrobun row to the release-packages table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…moke

Greptile P2 (#318): the `Doc` helper type was declared identically in two test callbacks.
Hoist it to module scope (DRY + easier to extend).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…configs

Greptile P2 (#318): the package-test conf set browserName: 'chrome' directly, bypassing
the launcher's electrobun→chrome rewrite and diverging from the sibling convention
(browserName: 'tauri'/'dioxus'). Use 'electrobun' across the package-test conf, the e2e
conf, and the README quick-start — the launcher coerces it to 'chrome' in onPrepare
(already covered by launcher.spec), so it's a functional no-op that exercises the documented
rewrite and makes the configs honest copy-paste templates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The macOS `standard` gate failed twice running with an elevated rate of CEF's
"Timeout of new browser info response" (the 2-window global-context race) — at
specFileRetries:2 (3 attempts) one spec exhausted its retries. Bump to 3 (4 attempts/spec)
to absorb the elevated rate. This is the documented upstream flake (#317), not a service
regression — the browserName change is exonerated (same CEF timeout; package-test passes).
Drop back once the upstream fix lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@goosewobbler goosewobbler merged commit 9896d8e into feat/electrobun-service Jun 2, 2026
102 checks passed
@goosewobbler goosewobbler deleted the feat/electrobun-ship branch June 2, 2026 18:05
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