Skip to content

Bundle a Temurin JRE in the VS Code extension - #11

Merged
lwrage merged 1 commit into
2445_add_ba_editor_servicesfrom
bundle_jre_in_vscode_extension
Sep 21, 2026
Merged

lwrage merged 1 commit into
2445_add_ba_editor_servicesfrom
bundle_jre_in_vscode_extension

Conversation

@lwrage

@lwrage lwrage commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Stacked on #10: this branch builds on its commits (the advanced OSATE pin and its
scripts/build-test-release changes). Retarget to main once #10 merges.

Why

The extension shipped no Java. It declared redhat.java as an extensionDependency
and launched the server with that extension's tooling JRE, which made our server's
runtime someone else's implementation detail — a change to
javaRequirement.tooling_jre breaks us, and the Java version was outside our
control. The integration tests had to install redhat.java from the Marketplace
just to activate, so the activation suite was this.skip()-gated and passed
silently whenever that failed.

What

  • Bundle an Eclipse Temurin 21 JRE and run only that. No discovery, no
    JAVA_HOME/PATH fallback, no override setting. JAVA_TOOL_OPTIONS,
    _JAVA_OPTIONS and JDK_JAVA_OPTIONS are stripped from the server's
    environment — bundling a runtime and then letting the machine inject agents into
    it defeats the point.
  • One VSIX per platform (aadl2-<target>-<version>.vsix) for darwin-x64,
    darwin-arm64, linux-x64, linux-arm64, win32-x64 and win32-arm64. A bundled
    runtime cannot be universal. vsce.package.targets selects the set: host by
    default, all for a release.
  • One shared download helper, scripts/lib/temurin.sh, used by both bundling
    paths. It adds checksum verification against Adoptium's published digest, which
    the osate-cli path never had.
  • Activation no longer rejects when the runtime cannot start; it reports the
    failure, so a package installed for the wrong platform says so instead of
    appearing as a generic activation error.
  • The release workflow validates all six packages — plug-in count, bundled
    runtime, declared target platform, pre-release marker — before publishing
    anything, and publishes them in a single vsce publish. Marketplace versions are
    immutable, so a partial publish would strand platforms on different versions.

Trade-offs

  • Each VSIX grows from ~78 MB to ~121 MB.
  • Alpine, 32-bit ARM and web clients are offered no package, because no untargeted
    fallback is published. Documented in the README, CHANGELOG and RELEASING.

Verified locally

  • ./scripts/build-test-release --skip-osate --skip-cli green, with 29
    integration tests passing on the bundled JVM under --disable-extensions
    —
    that suite previously skipped in its entirety.
  • All six targets stage with the right architecture; darwin-x64 is Mach-O
    x86_64, win32-* get java.exe.
  • code --install-extension into a clean profile: runtime/bin/java and
    lib/jspawnhelper keep mode 755 and the JRE runs, so nothing relies on a
    chmod at startup.
  • The release workflow's check step, extracted and run against real VSIXs: passes,
    and fails correctly on a missing target and on a pre-release mismatch.
  • osate-cli packaging still produces a working bundled-runtime tarball.

Two traps worth knowing, both documented in the code: maven-clean follows the
runtime symlink and deletes the cached JRE even with followSymlinks=false, and
unzip -l | grep -q fails under pipefail because the SIGPIPE kills unzip.

🤖 Generated with Claude Code

The extension had no Java of its own: it declared redhat.java as an extension
dependency and launched the server with that extension's tooling JRE. Our
server's runtime was therefore somebody else's implementation detail, a Red Hat
change to javaRequirement.tooling_jre would break us, and the integration tests
had to install redhat.java from the Marketplace just to activate - so the
activation suite skipped itself, silently, whenever that failed.

Bundle an Eclipse Temurin 21 JRE and run only that. There is no discovery, no
JAVA_HOME or PATH fallback and no override setting, because one supported runtime
is what makes a user's failure reproducible. JAVA_TOOL_OPTIONS, _JAVA_OPTIONS and
JDK_JAVA_OPTIONS are dropped from the server's environment for the same reason:
bundling a runtime and then letting the machine inject agents into it would
defeat the point.

A bundled runtime is platform-specific, so there is no longer a universal
package. vsce packages one VSIX per platform - macOS, Linux and Windows on x64
and arm64 - and the Marketplace serves the matching one. Clients on a platform we
do not build for, meaning Alpine, 32-bit ARM and the web, are offered nothing;
that is a deliberate trade for not shipping six runtimes to every user.

osate-cli already bundled these runtimes, so the download, checksum verification
and unpacking now live in one shared helper. The osate-cli path gains the
checksum verification it never had.

Notes on two things that bite:

- maven-clean follows the runtime symlink and deletes the cached JRE's contents
  even with followSymlinks=false, because the fileset directory is the link, so
  runtime/ is deliberately not cleaned.
- unzip -l piped into grep -q fails under pipefail: grep exits at the first match
  and the SIGPIPE kills unzip, which reported a missing runtime that was present.
  The content checks use grep -c.

Activation no longer rejects when the runtime cannot start. It reported nothing
but a generic activation failure, which is no way to discover that a package was
built for another platform.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lwrage
lwrage merged commit dd6dcb3 into 2445_add_ba_editor_services Sep 21, 2026
3 checks passed
@lwrage
lwrage deleted the bundle_jre_in_vscode_extension branch September 21, 2026 23:28
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