From 389acb30eeff86c05a68b63390e71f33fc85c557 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Tue, 16 Jun 2026 09:16:25 +0800 Subject: [PATCH] Fix offline installer release lookup --- docs/OFFLINE_AI_WORKSPACE_INSTALLER.md | 7 +++-- scripts/setup-ai-workspace-all-in-one.sh | 40 +++++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/docs/OFFLINE_AI_WORKSPACE_INSTALLER.md b/docs/OFFLINE_AI_WORKSPACE_INSTALLER.md index c77c05a..5d197c5 100644 --- a/docs/OFFLINE_AI_WORKSPACE_INSTALLER.md +++ b/docs/OFFLINE_AI_WORKSPACE_INSTALLER.md @@ -46,10 +46,13 @@ prepared. The default package source is: ```text -https://github.com/ai-workspace-lab/xworkspace-console/releases/latest/download/ai-workspace-all-in-one-offline---.tar.gz +https://github.com/ai-workspace-lab/xworkspace-console/releases/download//ai-workspace-all-in-one-offline---.tar.gz ``` -The latest release tag follows the `offline-ai-workspace-*` pattern. +When `AI_WORKSPACE_OFFLINE_RELEASE_TAG=latest`, the bootstrap asks GitHub for +the newest non-draft release that actually contains the matching tarball asset, +so it will skip a `releases/latest` target if that release is missing the file. +Pinned release tags still work as before. For private mirrors or pinned releases, use: diff --git a/scripts/setup-ai-workspace-all-in-one.sh b/scripts/setup-ai-workspace-all-in-one.sh index be93b39..88ac44b 100755 --- a/scripts/setup-ai-workspace-all-in-one.sh +++ b/scripts/setup-ai-workspace-all-in-one.sh @@ -394,6 +394,15 @@ detect_offline_target() { printf '%s %s %s\n' "$distro" "$version" "$arch" } +github_api() { + local path=$1 + local headers=(-H "Accept: application/vnd.github+json") + if [ -n "${GH_TOKEN:-${GITHUB_TOKEN:-}}" ]; then + headers+=(-H "Authorization: Bearer ${GH_TOKEN:-${GITHUB_TOKEN}}") + fi + curl -fsSL --retry 5 --retry-all-errors "${headers[@]}" "https://api.github.com${path}" +} + offline_package_filename() { local target=$1 # shellcheck disable=SC2086 @@ -401,9 +410,38 @@ offline_package_filename() { printf 'ai-workspace-all-in-one-offline-%s-%s-%s.tar.gz\n' "$1" "$2" "$3" } +resolve_offline_release_tag() { + local filename=$1 + local repo="${AI_WORKSPACE_OFFLINE_REPO:-ai-workspace-lab/xworkspace-console}" + local requested_tag="${AI_WORKSPACE_OFFLINE_RELEASE_TAG:-latest}" + local tag="" + + if [ "$requested_tag" != "latest" ]; then + printf '%s\n' "$requested_tag" + return + fi + + tag="$( + github_api "/repos/${repo}/releases?per_page=100" | + jq -r --arg name "${filename}" ' + [ .[] + | select(.draft == false) + | select(any(.assets[]?; .name == $name)) + | .tag_name + ][0] // empty + ' + )" + + [ -n "$tag" ] && printf '%s\n' "$tag" +} + offline_release_url() { local filename=$1 - local tag="${AI_WORKSPACE_OFFLINE_RELEASE_TAG:-latest}" + local tag + tag="$(resolve_offline_release_tag "$filename")" + if [ -z "$tag" ]; then + tag="${AI_WORKSPACE_OFFLINE_RELEASE_TAG:-latest}" + fi if [ "$tag" = "latest" ]; then printf 'https://github.com/%s/releases/latest/download/%s\n' "$AI_WORKSPACE_OFFLINE_REPO" "$filename" else