Repository navigation
[BUG]: For a while after a release, a bare major such as java@21-tem can install a build that vfox search does not list yet #113
Description
Version
vfox-java main (b635aaa), vfox 1.0.13
OS
Linux
Describe the bug
vfox search java <distribution> asks Foojay for every package of the distribution, but a bare major asks another question: java@21-tem asks for version=21&latest=available, and java@23-mandrel for distribution_version=23:
Line 247 in b635aaa
| local latest = version:match("^%d+$") and "&latest=available" or "" |
Lines 281 to 282 in b635aaa
| local query = version ~= "" and "&distribution_version=" .. encode(version) or "" | |
| for _, package in ipairs(request("", query) or {}) do |
Line 297 in b635aaa
| local result = request(version, latest) |
Foojay's answers come through Cloudflare, which caches each URL on its own, so the two questions get answers of different ages:
$ curl -sS -D - -o /dev/null 'https://api.foojay.io/disco/v3.0/packages/jdks?version=&distribution=mandrel&architecture=amd64&archive_type=tar.gz&operating_system=linux&lib_c_type=glibc&directly_downloadable=true' | grep -i -E '^(age|last-modified|cf-cache-status):'
age: 1321
last-modified: Tue, 20 Oct 2026 17:31:11 GMT
cf-cache-status: HIT
$ curl -sS -D - -o /dev/null 'https://api.foojay.io/disco/v3.0/packages/jdks?version=&distribution=mandrel&architecture=amd64&archive_type=tar.gz&operating_system=linux&lib_c_type=glibc&directly_downloadable=true&distribution_version=23' | grep -i -E '^(age|last-modified|cf-cache-status):'
age: 93
last-modified: Tue, 20 Oct 2026 17:51:40 GMT
cf-cache-status: HIT
$ curl -sS -D - -o /dev/null 'https://api.foojay.io/disco/v3.0/packages/jdks?version=&distribution=temurin&architecture=amd64&archive_type=tar.gz&operating_system=linux&lib_c_type=glibc&directly_downloadable=true' | grep -i -E '^(age|last-modified|cf-cache-status):'
age: 1341
last-modified: Tue, 20 Oct 2026 17:30:53 GMT
cf-cache-status: HIT
$ curl -sS -D - -o /dev/null 'https://api.foojay.io/disco/v3.0/packages/jdks?version=21&distribution=temurin&architecture=amd64&archive_type=tar.gz&operating_system=linux&lib_c_type=glibc&directly_downloadable=true&latest=available' | grep -i -E '^(age|last-modified|cf-cache-status):'
age: 632
last-modified: Tue, 20 Oct 2026 17:42:42 GMT
cf-cache-status: HIT
So for a while after Foojay adds a release, vfox install can take it while vfox search does not list it yet. That failed E2E on #111 on 2026-10-20, on the GraalVM Community rows of ubuntu-latest, at 16:22 UTC, minutes after Oracle GraalVM 25.0.5 reached Foojay, and again in the next run half an hour later. checkGraalVMBareMajor fakes the builds of 25 that vfox search java graal lists as installed, so that vfox install java@25-graal finds one of them, but the install took 25.0.5, which the search did not list, and downloaded it (https://github.com/version-fox/vfox-java/actions/runs/39456445454/job/118744465851, https://github.com/version-fox/vfox-java/actions/runs/39460751060/job/118759263303):
Error: "Preinstalling java@25.0.5-graal...\nVerifying checksum ...\nWARNING: Checksum is not provided, skip verify...\nUnpacking /root/.vfox/cache/java/graalvm-jdk-25.0.5_linux-x64_bin.tar.gz...\nInstall java@25.0.5 [...]
Test: TestE2E/main-graalce
Messages: vfox install java@25-graal must take 25.0.4.1.1-graal, the newest build that is no feature release
#111 then made Oracle GraalVM and GraalVM Community ask what the search asks. Two checks on the Temurin rows, which run on every runner, compare the search with a bare major the same way and can fail the same way: checkOwnNumbers with java@23-mandrel and java@23-nik, as Mandrel and Liberica NIK put out a 23.1 release every quarter, and checkNameOnly with the newest major of Eliya, OpenLogic and Semeru certified, which still release:
vfox-java/tests/e2e/linux/setup.go
Lines 142 to 196 in b635aaa
| func checkNameOnly(ctx context.Context, t *testing.T, ctr tc.Container, platform string) { | |
| t.Helper() | |
| names := common.NameOnlyDistributions(platform) | |
| var dirs []string | |
| for _, name := range names { | |
| search := "vfox search java " + name | |
| out := execRetry(ctx, t, ctr, search, search) | |
| spec, newest, ok := common.NewestBareMajor(common.SearchedVersions(out), name) | |
| require.Truef(t, ok, "%s lists no newest version that a bare major names\n--- output ---\n%s", search, out) | |
| dir := `"${VFOX_HOME:-$HOME/.vfox}"/cache/java/` + shQuote("v-"+newest) | |
| dirs = append(dirs, dir) | |
| execOK(ctx, t, ctr, "mkdir --parents "+dir+"/"+shQuote("java-"+newest)) | |
| out = execRetry(ctx, t, ctr, "vfox install java@"+spec, "vfox install java@"+spec) | |
| require.Containsf(t, common.StripANSI(out), "java@"+newest+" is already installed", | |
| "vfox install java@%s must take %s, the newest version %s lists", spec, newest, search) | |
| } | |
| if len(dirs) > 0 { | |
| execOK(ctx, t, ctr, "rm --recursive "+strings.Join(dirs, " ")) | |
| } | |
| t.Logf("PASS %d distributions go by name on %s: %s", len(names), platform, strings.Join(names, ", ")) | |
| } | |
| // checkOwnNumbers proves Mandrel and Liberica NIK go by the GraalVM numbers | |
| // they carry (see common.OwnNumberedDistributions): `vfox search java | |
| // <short>` lists the release the suite names under its number, and with it | |
| // and the newest release of its major faked as installed, `vfox install | |
| // java@<long>-<release>` and `vfox install java@<major>-<short>` find those | |
| // installed (see common.OwnNumberSpecs and common.NewestOfMajor), so nothing | |
| // downloads. | |
| func checkOwnNumbers(ctx context.Context, t *testing.T, ctr tc.Container, platform string) { | |
| t.Helper() | |
| names := common.OwnNumberedDistributions(platform) | |
| for _, name := range names { | |
| search := "vfox search java " + name | |
| out := execRetry(ctx, t, ctr, search, search) | |
| searched := common.SearchedVersions(out) | |
| spec, installed, bare := common.OwnNumberSpecs(name) | |
| require.Containsf(t, searched, installed, "%s must list %s\n--- output ---\n%s", search, installed, out) | |
| newest, ok := common.NewestOfMajor(searched, bare) | |
| require.Truef(t, ok, "%s lists no release that %s names\n--- output ---\n%s", search, bare, out) | |
| var dirs []string | |
| for _, version := range []string{installed, newest} { | |
| dir := `"${VFOX_HOME:-$HOME/.vfox}"/cache/java/` + shQuote("v-"+version) | |
| dirs = append(dirs, dir) | |
| execOK(ctx, t, ctr, "mkdir --parents "+dir+"/"+shQuote("java-"+version)) | |
| } | |
| for _, c := range []struct{ spec, want string }{{spec, installed}, {bare, newest}} { | |
| out = execRetry(ctx, t, ctr, "vfox install java@"+c.spec, "vfox install java@"+c.spec) | |
| require.Containsf(t, common.StripANSI(out), "java@"+c.want+" is already installed", | |
| "vfox install java@%s must take %s, which %s lists", c.spec, c.want, search) | |
| } | |
| execOK(ctx, t, ctr, "rm --recursive "+strings.Join(dirs, " ")) | |
| t.Logf("PASS java@%s takes %s and java@%s %s", spec, installed, bare, newest) | |
| } | |
| } |
My guess is that a bare major should ask for every package, as the search does, and take the newest release of the major itself, as #111 does for GraalVM. I compared that with latest=available for every bare major of the other 27 distributions on Foojay, on Linux x64 and arm64, Linux x64 with musl, macOS x64 and arm64 and Windows x64 and arm64, and got the same release everywhere. Only Dragonwell 11 on Windows x64 and Linux x64 with musl changes file, from the Standard to the Extended build of 11.0.32, which java@11.0.32-albba already installs.
Found while working on #105.
Activity
linghengqian commentedon Oct 20, 2026
I am working on the current issue.