Overhaul the managed JETLS installation and bump the pin to 2026-08-29 - #77
Open
aviatesk wants to merge 5 commits into
Open
Overhaul the managed JETLS installation and bump the pin to 2026-08-29#77aviatesk wants to merge 5 commits into
aviatesk wants to merge 5 commits into
Conversation
aviatesk
force-pushed
the
avi/fix-managed-installation
branch
from
August 29, 2026 23:47
c86fe21 to
9beb2c6
Compare
JETLS releases since 2026-08-23 report themselves as `jetls version <revision>, julia version <version>`, while `is_pinned_jetls_version` only accepted the pre-2026-08-23 `JETLS version <revision> ...` line. Bumping the pin past that release would therefore make every fresh installation fail its post-install verification and leave the managed installation permanently broken. This change bumps the pin to the latest release (2026-08-29) and rewrites the parser for the new format, mirroring the semantics of the jetls-vscode client: the output must contain exactly one `jetls version ` line, and its comma- or whitespace-terminated revision token must equal the pin. The old format is now rejected, so a stale pre-2026-08-23 installation triggers a reinstall as intended. The pinned release declares `julia = "1.12.2 - 1.13"` compat, matching the existing version bounds, so they stay unchanged. The tests cover the new format and the rejection of the old format, foreign revisions, and outputs with multiple version lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Julia version bounds in `src/julia.rs` must mirror the `julia` compat entry declared by the pinned JETLS release's Project.toml, but that sync was only guarded by a source comment. Bumping the pin while leaving the bounds stale would ship an extension that admits Julia versions the pinned server does not support, or rejects ones it does. This change ports the bounds check of the jetls-vscode client: `scripts/check-julia-bounds.sh` extracts the `JETLS_REPOSITORY`, `JETLS_REVISION`, and bound constants from `src/julia.rs`, reads the pinned revision's Project.toml through the GitHub contents API via `gh api`, and fails unless the compat entry equals `<lower> - <upper>` exactly. A new `check-julia-bounds` CI job runs the script on every push and pull request. The constants stay in `src/julia.rs` as the single source of truth; the script requires exactly one match per constant, so drift in the declarations themselves also fails the check rather than being silently misread. The check passes for the current 2026-08-29 pin, and the mismatch and unknown-revision failure paths were exercised manually. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Pkg.Apps-generated shim exports a hardcoded `JULIA_DEPOT_PATH` containing only the managed depot, so the server never saw the user depot: packages and precompile caches in `~/.julia` (or a user-set `JULIA_DEPOT_PATH` chain) were invisible, workspace dependencies had to be re-fetched and re-precompiled into the managed depot (failing offline), and any user depot configuration was clobbered. This change stops launching through the shim and spawns `julia -m JETLS` directly, mirroring the jetls-vscode extension's `serverLaunchEnvironment`: `JULIA_DEPOT_PATH` places the managed depot first, then the user's own chain (falling back to `~/.julia` via `HOME`/`USERPROFILE`, with a trailing empty entry appending the bundled system depots), and `JULIA_LOAD_PATH` pins the managed app environment. Writes stay in the managed depot while user-depot packages and caches are reused for analysis. The shim's argument protocol (arguments before `--` go to `julia`, the rest to the app) is reproduced, so existing `binary.arguments` settings keep their meaning, and the version check runs through the same direct launch path it verifies. The shim file now only marks a completed installation; the install and gc environments also append the bundled depots so stdlib caches are reused. As a side effect, Windows no longer launches through `jetls.bat`, removing the batch intermediary that could orphan the child `julia` process. `JULIA_APPS_JULIA_CMD` is still honored for selecting the Julia executable but is no longer pinned into the launch environment. Unit tests cover the depot chain construction and the argument protocol, and the direct launch was verified end-to-end against an existing managed depot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Updates rewrote the single managed depot in place while a server from another window could still be running from it, and then collected the superseded packages immediately with `Pkg.gc(; collect_delay=Day(0))`. A failed or interrupted installation left that depot broken, retries reused the broken state, and the only recovery was the error-message hint to delete the depot manually. Runtime depots for a Julia the user stopped using were also kept forever. This change adopts the generation scheme of the jetls-vscode extension. `jetls-depots/<runtime-key>` becomes a container of immutable generation directories plus a `current` JSON pointer that is published through a uniquely named temp file and a rename, so readers never see torn content and the last of concurrent publishers wins. Resolution reads the pointer and probes that generation with the per-start `jetls version` check as before; a pin mismatch or breakage installs into a fresh generation, verifies it, writes an `install-stamp.json`, and only then publishes the pointer. The published generation is never modified, so a failed installation strands only its own unpublished directory and a retry starts clean. `Pkg.gc` is replaced by whole-generation cleanup driven by `last-used` markers touched on every start: unpublished generations are reclaimed after 24 hours, superseded published generations after 7 days, and runtime containers of an unused Julia after 30 days. The sweep refuses to run outside a `jetls-depots` directory, and depots from the pre-generation layout age out through the same policy. Deliberate deviations from jetls-vscode: no install lock (concurrent installs merely duplicate work and the last publish wins), no install stamp fast path (the extension cannot observe serve failures to invalidate a stamp, so the per-start probe keeps corruption self-healing), and synchronous cleanup (extensions have no resident process). Unit tests cover pointer publish/resolve and validation, the grace policy, and the cleanup keep-set; the README tip now describes atomic updates and retention-based cleanup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Runtime containers under `jetls-depots` were named by an opaque 16-hex-digit hash of the Julia executable path and minor version (e.g. `60a6946f0a0c5f8f`), which made the storage layout inscrutable when inspecting it or reclaiming disk space manually. This change adopts the `runtimeKey` naming of the jetls-vscode extension: the container name spells out the Julia minor version and hashes only the executable path, e.g. `v1.12-d46d6d4d`. The FNV-1a hash is kept (it stays stable across extension builds) and truncated to eight hex digits, matching the length vscode uses. The rationale comment is ported alongside: different installations of the same Julia version are different builds whose precompile caches must not share a depot, and the patch version deliberately stays out of the key so a patch update re-precompiles within the existing generation instead of reinstalling into a fresh container. Containers under the old hash-only names are no longer referenced; the stale-runtime sweep reclaims them after the runtime retention. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aviatesk
force-pushed
the
avi/fix-managed-installation
branch
from
August 30, 2026 02:36
9beb2c6 to
f0b5282
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR ports the stabilization work from the jetls-vscode client's managed installation (which itself started as a port of this extension's) back to zed-julia, and bumps the pinned JETLS release.
Server pin
jetls version <revision>, julia version <version>output format used by JETLS releases since 2026-08-23. Without this, any pin bump past that release would make every fresh installation fail its post-install verification and permanently break the managed installation.scripts/check-julia-bounds.sh) that verifies the Julia version bounds insrc/julia.rsagainst thejuliacompat declared by the pinned release's Project.toml, so a future pin bump cannot silently ship stale bounds.Server launch
julia -m JETLSdirectly instead of going through thePkg.Apps-generated shim. The shim exports a hardcodedJULIA_DEPOT_PATHcontaining only the managed depot, so the server never saw the user depot: workspace dependencies had to be re-fetched and re-precompiled into the managed depot (failing offline), and a user-set depot chain was clobbered.JULIA_DEPOT_PATH, falling back to~/.julia), then the bundled system depots, and pinsJULIA_LOAD_PATHto the managed app environment: writes stay in the managed depot while user-depot packages and precompile caches are reused for analyzing workspace dependencies.---separated argument protocol forbinary.argumentsis preserved, so existing launch configurations keep working.Installation updates
Pkg.gc; a failed or interrupted installation left the depot broken, with manual deletion as the only recovery.currentpointer only after the pinned version is verified, so a failed or interrupted update never breaks the installation in use and a retry starts from a clean slate.Pkg.gcis replaced by retention-based cleanup driven by last-used markers: unpublished generations are reclaimed after 24 hours, superseded generations after 7 days, and runtime containers of a Julia no longer in use after 30 days. Depots from the old layout age out through the same policy.v<minor>-<hash>(e.g.v1.12-d46d6d4d) instead of an opaque 16-hex-digit hash, making the storage layout inspectable.Notes
jetls-depotsremains safe at any time.jetls versionprobe keeps corruption self-healing), and synchronous cleanup (extensions have no resident process).