From a0e0bf65ff1c5c430c4ffb4ca55307c6d476b9a6 Mon Sep 17 00:00:00 2001 From: Junker der Provinz <133605895+junkerderprovinz@users.noreply.github.com> Date: Fri, 17 Jul 2026 14:53:01 +0200 Subject: [PATCH] fix(releases): let LinuxServer.io version filters find older releases via GitHub (#6376) --- .../request-handler/src/release-providers.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/packages/request-handler/src/release-providers.ts b/packages/request-handler/src/release-providers.ts index 5bfde69b9..b70136631 100644 --- a/packages/request-handler/src/release-providers.ts +++ b/packages/request-handler/src/release-providers.ts @@ -745,6 +745,19 @@ const linuxServerIOReleasesSchema = z.object({ }), }); +// Parse a github.com project URL (as returned by the LSIO registry) into an +// "owner/repo" identifier, or null if it is not a github.com repository URL. +const parseGithubRepo = (url: string): string | null => { + try { + const parsed = new URL(url); + if (parsed.hostname !== "github.com") return null; + const [owner, repo] = parsed.pathname.replace(/^\/+/, "").split("/"); + return owner && repo ? `${owner}/${repo}` : null; + } catch { + return null; + } +}; + const getLinuxServerIOReleaseAsync = async ( baseUrl: string, identifier: string, @@ -774,6 +787,29 @@ const getLinuxServerIOReleaseAsync = async ( error: { code: "noReleasesFound", message: `Image "${parsed.name}" not found in LinuxServer.io registry` }, }; + // LSIO's /api/v1/images only exposes the single latest version, so a version + // filter can never surface an older release (#4351). When the image has a GitHub + // repository, delegate to the GitHub release provider to fetch the real release + // history and apply the filter, while keeping LSIO's own image metadata. Any + // GitHub failure (no repo, no releases, rate limit) falls back to the LSIO latest. + const githubRepo = parseGithubRepo(release.github_url); + if (githubRepo) { + const githubResult = await getGithubReleaseAsync(getReleaseProviderDefaultUrl("github"), githubRepo, versionRegex); + if (githubResult.success) { + return { + success: true, + data: { + ...githubResult.data, + projectUrl: release.github_url, + projectDescription: release.description, + isArchived: release.deprecated, + starsCount: release.stars, + createdAt: release.initial_date ?? githubResult.data.createdAt, + }, + }; + } + } + const regex = compileVersionRegex(versionRegex); if (versionRegex && !regex) { return {