Skip to content

fix(sample): restore missing wasmJs browser target - #105

Merged
jamesarich merged 1 commit into
mainfrom
fix/sample-wasmjs
Jul 26, 2026
Merged

fix(sample): restore missing wasmJs browser target#105
jamesarich merged 1 commit into
mainfrom
fix/sample-wasmjs

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

What broke

release.yml's sample-artifacts job builds the linux-x64 leg with one Gradle invocation:

:sample:androidApp:assembleRelease
:sample:packageReleaseDistributionForCurrentOS
:sample:wasmJsBrowserDistribution

:sample:wasmJsBrowserDistribution did not exist, because sample/build.gradle.kts declared no wasmJs target. Gradle fails at task-selection time, before running anything — so the whole job died and the release lost the .apk and the .deb, not just the wasm zip. v0.6.0's GitHub Release shows the damage: only .dmg, .msi and SBOMs.

sample/src/wasmJsMain/ was fully populated the whole time (Main.kt with ComposeViewport, index.html, favicons) — an orphaned source set with no compilation. The target was almost certainly dropped when the library split into per-transport modules: MqttSampleViewModel referenced TcpTransportFactory from commonMain, and :transport-tcp deliberately omits wasmJs (a browser cannot open a raw TCP socket), so a wasmJs target could not have compiled as the code stood.

What changed

Took the "properly restore it" path rather than deleting the task from the workflow.

  • sample/build.gradle.kts — add wasmJs { browser(); binaries.executable() }, matching the idiom in transport-ws/build.gradle.kts. binaries.executable() is the part that registers wasmJsBrowserDistribution.
  • sample/build.gradle.kts — move implementation(project(":transport-tcp")) off commonMain and onto androidMain, desktopMain and iosMain. :core and :transport-ws stay in commonMain — both support wasmJs.
  • PlatformTransport.kt (new, commonMain + 4 actuals)internal expect fun platformTransportFactory(): MqttTransportFactory. Android/desktop/iOS return TcpTransportFactory() + WebSocketTransportFactory(); wasmJs returns WebSocketTransportFactory() alone. Four small explicit actual files, no hand-wired dependsOn intermediate source set.
  • MqttSampleViewModel.kt — calls platformTransportFactory(); the three transport imports are gone from common code. No behaviour change on any existing platform.
  • kotlin-js-store/wasm/yarn.lock — regenerated via kotlinWasmUpgradeYarnLock. Compose's wasm target pulls in @js-joda/core; purely additive, and the existing ws@8.21.0 security pin is untouched.
  • sample/README.md — one line for the new file. The README already documented wasmJs as a supported target and already told browser users to switch to a ws:// URI, so no other doc change was needed.

kotlinx-browser was not needed — kotlinx.browser.document resolves transitively through Compose on Kotlin 2.4.10 / CMP 1.11.1.

The UI is untouched. The default broker URI stays tls://mqtt.meshtastic.org:8883 (asserted by a commonTest test); in the browser you switch it to ws:///wss://, exactly as the README already says.

Verification (local, macOS, JDK 21)

Command Result
:sample:wasmJsBrowserDistribution BUILD SUCCESSFUL — output at sample/build/dist/wasmJs/productionExecutable, the exact path the workflow's zip step cds into, containing index.html, sample.js (the filename index.html references), both .wasm blobs and the favicons
:sample:androidApp:assembleRelease BUILD SUCCESSFULandroidApp-release-unsigned.apk (10.8 MB) at the workflow's artifact_glob path
:sample:packageReleaseDistributionForCurrentOS BUILD SUCCESSFULmqtt-sample-1.6.0.dmg on this macOS host, proving the task graph the linux .deb leg uses
:sample:compileKotlinDesktop :sample:compileKotlinWasmJs BUILD SUCCESSFUL
:sample:compileKotlinIosArm64 :sample:compileKotlinIosSimulatorArm64 BUILD SUCCESSFUL
spotlessCheck detekt BUILD SUCCESSFUL
:sample:desktopTest BUILD SUCCESSFUL
:sample:wasmJsBrowserTest BUILD SUCCESSFULtests="7" failures="0" errors="0"

That last one is new surface worth flagging: ci.yml's test-wasm job runs ./gradlew wasmJsBrowserTest unscoped, so the sample's commonTest now also executes in headless Chrome. All 7 existing tests pass there.

One thing I could not verify locally: :sample:linkReleaseFrameworkIosArm64 OOMs (Java heap space) on this machine. I confirmed it fails identically on unmodified origin/main, so it is pre-existing and environmental — this box pins org.gradle.jvmargs=-Xmx2048M and Compose's iOS release framework link needs more. Neither ci.yml nor release.yml builds iOS release frameworks; ci.yml links only the debug test binary, which passes here with a larger heap.

The release workflow's linux-x64 sample job ran :sample:androidApp:assembleRelease,
:sample:packageReleaseDistributionForCurrentOS and :sample:wasmJsBrowserDistribution
in a single Gradle invocation, but the sample declared no wasmJs target, so the third
task did not exist. Gradle failed at task-selection time and the whole job died,
costing the release its .apk and .deb as well as the wasm zip.

Restore the target and give the orphaned sample/src/wasmJsMain a compilation:

- Add wasmJs { browser(); binaries.executable() } — the executable binary is what
  registers the wasmJsBrowserDistribution task.
- Move :transport-tcp off commonMain onto androidMain/desktopMain/iosMain. It has
  no wasmJs variant because a browser cannot open a raw TCP socket.
- Add internal expect fun platformTransportFactory() so common code no longer
  references TcpTransportFactory directly: non-web targets get
  TcpTransportFactory() + WebSocketTransportFactory(), wasmJs gets WebSockets only.
- Regenerate kotlin-js-store/wasm/yarn.lock for Compose's @js-joda/core npm dep.
Copilot AI review requested due to automatic review settings July 26, 2026 18:47
@jamesarich
jamesarich enabled auto-merge July 26, 2026 18:47
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jamesarich, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 14 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: df3462df-9630-44d3-8c3b-69d65ebb13cd

📥 Commits

Reviewing files that changed from the base of the PR and between 72f350d and 0206e83.

⛔ Files ignored due to path filters (1)
  • kotlin-js-store/wasm/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • sample/README.md
  • sample/build.gradle.kts
  • sample/src/androidMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.android.kt
  • sample/src/commonMain/kotlin/org/meshtastic/mqtt/sample/MqttSampleViewModel.kt
  • sample/src/commonMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.kt
  • sample/src/desktopMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.desktop.kt
  • sample/src/iosMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.ios.kt
  • sample/src/wasmJsMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.wasmJs.kt

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores the :sample module’s missing wasmJs browser target so the release workflow can successfully select and execute :sample:wasmJsBrowserDistribution, preventing the entire sample-artifacts job from failing at Gradle task-selection time.

Changes:

  • Added a wasmJs { browser(); binaries.executable() } target to sample/build.gradle.kts to register the wasmJsBrowserDistribution task.
  • Refactored the sample’s transport wiring to avoid :transport-tcp in commonMain (so wasmJs can compile) by introducing an expect/actual platformTransportFactory() and moving the TCP dependency to non-web source sets.
  • Updated the sample README and regenerated the wasm yarn lockfile for the restored wasm build graph.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
sample/build.gradle.kts Adds wasmJs browser executable target; moves :transport-tcp dependency out of commonMain and into per-platform source sets.
sample/src/commonMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.kt Introduces internal expect fun platformTransportFactory() to select transports per platform.
sample/src/androidMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.android.kt Android actual uses TCP + WebSocket transport factories.
sample/src/desktopMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.desktop.kt Desktop actual uses TCP + WebSocket transport factories.
sample/src/iosMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.ios.kt iOS actual uses TCP + WebSocket transport factories.
sample/src/wasmJsMain/kotlin/org/meshtastic/mqtt/sample/PlatformTransport.wasmJs.kt wasmJs actual uses WebSocket-only transport factory (no TCP on browser).
sample/src/commonMain/kotlin/org/meshtastic/mqtt/sample/MqttSampleViewModel.kt Switches client config to use platformTransportFactory() instead of directly referencing TCP/WS factories in common code.
sample/README.md Documents the new PlatformTransport.kt in the module layout.
kotlin-js-store/wasm/yarn.lock Regenerated lockfile for wasm build (adds @js-joda/core).

@jamesarich
jamesarich merged commit 825ee2f into main Jul 26, 2026
14 checks passed
@jamesarich
jamesarich deleted the fix/sample-wasmjs branch July 26, 2026 18:52
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.

2 participants