From b3342b2c38ec5dd273107e2f731d57920884a1ed Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Thu, 20 Aug 2026 23:42:45 -0700 Subject: [PATCH 1/4] Install the General registry unpacked, so Julia 1.7 can read it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `test_julia_versions.jl:Julia 1.7 platform` fails on the rc and beta legs on Linux and macOS, and passes there on 1.12 and on Windows. The cause is not our code: Julia 1.7's bundled 7z cannot decompress zstd — 7z only learned that in v17.6 — and it shares this depot with the Julia that drives the run. From 1.13 on, Pkg asks the package server for a zstd compressed registry. It already skips zstd for registries on Windows for exactly this reason, quoting the same 7z version in `Pkg/src/PlatformEngines.jl`, but that carve-out keys off the platform rather than off what else lives in the depot. So on Linux and macOS a `General.tar.zst` lands in the shared depot, and every 1.7 test process then dies on `julia-1.7.3/libexec/7z x ~/.julia/registries/General.tar.zst -so`. An unpacked registry is a plain folder that every version reads, and it survives later `Pkg.Registry.update()`s. The job prep script already installs the Julia versions this suite runs against, so it is also the place to leave the registry in a shape all of them can read. Verified locally: converting a packed depot leaves Pkg reporting an unpacked registry, and Julia 1.7 resolves and installs a package against it. Co-Authored-By: Claude Opus 5 --- scripts/install_julia_versions.jl | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/scripts/install_julia_versions.jl b/scripts/install_julia_versions.jl index 71c9947..ac3419b 100644 --- a/scripts/install_julia_versions.jl +++ b/scripts/install_julia_versions.jl @@ -1,5 +1,31 @@ +using Pkg + for minor in 0:13 version = "1.$minor" println("Installing Julia $version...") run(ignorestatus(`juliaup add $version`)) end + +# Every version installed above shares this depot, and Julia 1.7's bundled 7z cannot +# decompress zstd — 7z only learned that in v17.6. Pkg asks the package server for a zstd +# compressed registry from Julia 1.13 on, everywhere except Windows, where it skips zstd +# for exactly this reason (`Pkg/src/PlatformEngines.jl`). That carve-out is by platform +# rather than by what else lives in the depot, so on Linux and macOS a `General.tar.zst` +# lands here and `check_julia_version("1.7")` fails on it, while the same test passes on +# Windows. An unpacked registry is a plain folder that every version reads, so install the +# registry that way before any test process needs it. +registries = joinpath(first(DEPOT_PATH), "registries") +packed = isdir(registries) && any(i -> startswith(i, "General.tar"), readdir(registries)) + +if packed || !isdir(joinpath(registries, "General")) + println("Installing the General registry unpacked, so that Julia 1.7 can read it...") + + # Removing the packed registry has to happen outside the `withenv` below: with + # `JULIA_PKG_UNPACK_REGISTRY` set, Pkg looks for unpacked registries only and reports + # the packed one it is standing on as not installed. + packed && Pkg.Registry.rm("General") + + withenv("JULIA_PKG_UNPACK_REGISTRY" => "true") do + Pkg.Registry.add("General") + end +end From 5d34a6ea3a18e83806e69c5818213a324ac8690b Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 21 Aug 2026 04:40:35 -0700 Subject: [PATCH 2/4] Keep the registry unpacked for the rest of the job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Converting the registry that `julia-buildpkg` installed is not enough on its own: on the first run of this the 1.7 leg still died on a `General.tar.zst`, which means something later in the job put a packed registry back — the run itself, or a test process resolving an environment against the shared depot. Export `JULIA_PKG_UNPACK_REGISTRY` into `GITHUB_ENV` as well, so every later step in the job installs and refreshes the registry unpacked rather than only the copy this script converted. Co-Authored-By: Claude Opus 5 --- scripts/install_julia_versions.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/install_julia_versions.jl b/scripts/install_julia_versions.jl index ac3419b..3d0c47a 100644 --- a/scripts/install_julia_versions.jl +++ b/scripts/install_julia_versions.jl @@ -29,3 +29,15 @@ if packed || !isdir(joinpath(registries, "General")) Pkg.Registry.add("General") end end + +# Converting what is here now is not enough: anything later in this job that installs or +# refreshes the registry — the run itself, or a test process resolving an environment — +# would put a packed one back. Setting the variable for the rest of the job keeps every +# such download unpacked too. +github_env = get(ENV, "GITHUB_ENV", nothing) + +if github_env !== nothing + open(github_env, "a") do io + println(io, "JULIA_PKG_UNPACK_REGISTRY=true") + end +end From 505ed6bd580c3ae03f6d8fb9b1fb4b1357947631 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 21 Aug 2026 07:42:02 -0700 Subject: [PATCH 3/4] Only unpack the registry where the zstd problem exists Unpacking on Windows made things worse rather than better: Pkg's replace-on-write dance there leaves `$XXXX.pid.deleted` entries in `registries`, and the concurrent test processes trip over them with IOError: stat("...\.julia\registries\$M3WH.pid.deleted"): permission denied 21 test items failed on the `windows-latest, rc~x64` leg because of it, on a leg that was green before. Windows never had the problem being fixed: Pkg already refuses zstd for registries there, for the same 7z reason. Restrict the whole thing to the platforms where a `General.tar.zst` can actually appear. Co-Authored-By: Claude Opus 5 --- scripts/install_julia_versions.jl | 47 +++++++++++++++++-------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/scripts/install_julia_versions.jl b/scripts/install_julia_versions.jl index 3d0c47a..accb164 100644 --- a/scripts/install_julia_versions.jl +++ b/scripts/install_julia_versions.jl @@ -12,32 +12,37 @@ end # for exactly this reason (`Pkg/src/PlatformEngines.jl`). That carve-out is by platform # rather than by what else lives in the depot, so on Linux and macOS a `General.tar.zst` # lands here and `check_julia_version("1.7")` fails on it, while the same test passes on -# Windows. An unpacked registry is a plain folder that every version reads, so install the -# registry that way before any test process needs it. -registries = joinpath(first(DEPOT_PATH), "registries") -packed = isdir(registries) && any(i -> startswith(i, "General.tar"), readdir(registries)) +# Windows. An unpacked registry is a plain folder that every version reads. +# +# Only where the problem exists, though: on Windows the registry is already gzip, and an +# unpacked one there makes Pkg's replace-on-write dance leave `*.pid.deleted` entries that +# the concurrent test processes then trip over with `stat: permission denied`. +if !Sys.iswindows() + registries = joinpath(first(DEPOT_PATH), "registries") + packed = isdir(registries) && any(i -> startswith(i, "General.tar"), readdir(registries)) -if packed || !isdir(joinpath(registries, "General")) - println("Installing the General registry unpacked, so that Julia 1.7 can read it...") + if packed || !isdir(joinpath(registries, "General")) + println("Installing the General registry unpacked, so that Julia 1.7 can read it...") - # Removing the packed registry has to happen outside the `withenv` below: with - # `JULIA_PKG_UNPACK_REGISTRY` set, Pkg looks for unpacked registries only and reports - # the packed one it is standing on as not installed. - packed && Pkg.Registry.rm("General") + # Removing the packed registry has to happen outside the `withenv` below: with + # `JULIA_PKG_UNPACK_REGISTRY` set, Pkg looks for unpacked registries only and + # reports the packed one it is standing on as not installed. + packed && Pkg.Registry.rm("General") - withenv("JULIA_PKG_UNPACK_REGISTRY" => "true") do - Pkg.Registry.add("General") + withenv("JULIA_PKG_UNPACK_REGISTRY" => "true") do + Pkg.Registry.add("General") + end end -end -# Converting what is here now is not enough: anything later in this job that installs or -# refreshes the registry — the run itself, or a test process resolving an environment — -# would put a packed one back. Setting the variable for the rest of the job keeps every -# such download unpacked too. -github_env = get(ENV, "GITHUB_ENV", nothing) + # Converting what is here now is not enough: anything later in this job that installs + # or refreshes the registry — the run itself, or a test process resolving an + # environment — would put a packed one back. Setting the variable for the rest of the + # job keeps every such download unpacked too. + github_env = get(ENV, "GITHUB_ENV", nothing) -if github_env !== nothing - open(github_env, "a") do io - println(io, "JULIA_PKG_UNPACK_REGISTRY=true") + if github_env !== nothing + open(github_env, "a") do io + println(io, "JULIA_PKG_UNPACK_REGISTRY=true") + end end end From b07636442485214ac2ffa7a409d3b2418bcab1c7 Mon Sep 17 00:00:00 2001 From: David Anthoff Date: Fri, 21 Aug 2026 10:36:19 -0700 Subject: [PATCH 4/4] Repair a Windows depot that an earlier run left unpacked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restricting the conversion to Linux and macOS was not enough to make the Windows legs green again, because the damage is cached: `julia-actions/cache` saves the depot, so the unpacked registry an earlier run of this script created comes back on every later Windows run. Pkg then replaces it on the next registry operation, and its replace-on-write leaves `$XXXX.pid.deleted` entries that the concurrent test processes trip over with `stat: permission denied` — 17 items failed that way on `windows-latest, rc~x64` even with the conversion switched off. Put a packed registry back on Windows and sweep up the leftovers, so one run repairs the cached depot instead of every run rediscovering it. Co-Authored-By: Claude Opus 5 --- scripts/install_julia_versions.jl | 34 +++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/scripts/install_julia_versions.jl b/scripts/install_julia_versions.jl index accb164..247a77e 100644 --- a/scripts/install_julia_versions.jl +++ b/scripts/install_julia_versions.jl @@ -13,15 +13,13 @@ end # rather than by what else lives in the depot, so on Linux and macOS a `General.tar.zst` # lands here and `check_julia_version("1.7")` fails on it, while the same test passes on # Windows. An unpacked registry is a plain folder that every version reads. -# -# Only where the problem exists, though: on Windows the registry is already gzip, and an -# unpacked one there makes Pkg's replace-on-write dance leave `*.pid.deleted` entries that -# the concurrent test processes then trip over with `stat: permission denied`. -if !Sys.iswindows() - registries = joinpath(first(DEPOT_PATH), "registries") - packed = isdir(registries) && any(i -> startswith(i, "General.tar"), readdir(registries)) +registries = joinpath(first(DEPOT_PATH), "registries") +entries = isdir(registries) ? readdir(registries) : String[] +packed = any(i -> startswith(i, "General.tar"), entries) +unpacked = isdir(joinpath(registries, "General")) - if packed || !isdir(joinpath(registries, "General")) +if !Sys.iswindows() + if packed || !unpacked println("Installing the General registry unpacked, so that Julia 1.7 can read it...") # Removing the packed registry has to happen outside the `withenv` below: with @@ -45,4 +43,24 @@ if !Sys.iswindows() println(io, "JULIA_PKG_UNPACK_REGISTRY=true") end end +elseif unpacked && !packed + # Windows never had the zstd problem — Pkg refuses zstd for registries there, for the + # same 7z reason — and an unpacked registry actively hurts: Pkg replaces it on the next + # registry operation, and its replace-on-write leaves `$XXXX.pid.deleted` entries that + # the concurrent test processes then trip over with `stat: permission denied`. The + # depot is cached between runs, so one unpacked registry would keep breaking every + # later Windows run. Put a packed one back, and sweep up what was left behind. + println("Restoring a packed General registry, which is what Windows wants...") + + Pkg.Registry.rm("General") + Pkg.Registry.add("General") + + for i in readdir(registries) + endswith(i, ".pid.deleted") || continue + try + rm(joinpath(registries, i); recursive=true, force=true) + catch err + @warn "Could not remove a leftover registry entry" entry = i err + end + end end