diff --git a/.gitea/workflows/deploy-client.yml b/.gitea/workflows/deploy-client.yml index 45bcc62..39b7688 100644 --- a/.gitea/workflows/deploy-client.yml +++ b/.gitea/workflows/deploy-client.yml @@ -62,6 +62,14 @@ jobs: GOPROXY: https://goproxy.cn,direct PUB_HOSTED_URL: https://pub.flutter-io.cn FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn + # 境内镜像:GitHub release 资产在国内被 GFW 限速 → windows runner(LAN 内)下 + # sing-box.exe / wintun.zip 超时。改从 NAS Gitea generic 包镜像拉, + # fetch-desktop-bin.sh 命中镜像后照样验 SHA256,失败则回退官方源。 + # ⚠️ 基址含 sing-box 版本目录(v1.13.12)——升级 app/kernel/VERSION 的 + # SINGBOX_VERSION 时,须把新版 zip 重新 PUT 到对应版本目录并同步改这里。 + DESKTOP_BIN_MIRROR: http://192.168.3.200:3000/api/packages/wangjia/generic/desktop-bin/v1.13.12 + # 包默认可匿名读,token 非必需;带上以防将来把包设为私有(未设/为空则匿名 GET)。 + DESKTOP_BIN_MIRROR_TOKEN: ${{ secrets.FORGEJO_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 diff --git a/app/kernel/fetch-desktop-bin.sh b/app/kernel/fetch-desktop-bin.sh index 3a35a87..1e9194a 100644 --- a/app/kernel/fetch-desktop-bin.sh +++ b/app/kernel/fetch-desktop-bin.sh @@ -20,6 +20,15 @@ # 提取对应 arch 的 wintun.dll 到产物目录。 # # 幂等: 产物已存在且 SHA256 校验通过则跳过下载(传 --force 强制重下) +# +# 境内镜像(可选,解决 CI 从 GitHub release 被 GFW 限速的问题): +# DESKTOP_BIN_MIRROR 镜像基址;设了则 archive 与 wintun.zip 先试 +# ${DESKTOP_BIN_MIRROR}/<文件名>,命中即用,失败/未设 +# 则回退官方 GitHub / wintun.net。镜像下载的文件照样走 +# 下面的 SHA256 校验(防投毒/损坏)。 +# 例:http://192.168.3.200:3000/api/packages/wangjia/generic/desktop-bin/v1.13.12 +# DESKTOP_BIN_MIRROR_TOKEN 可选;镜像需鉴权时作 `Authorization: token <值>`。 +# 不设则匿名 GET(NAS Gitea generic 包默认可匿名读)。 set -euo pipefail @@ -116,6 +125,36 @@ _sha256() { fi } +# ── 下载助手:镜像优先,回退官方源 ───────────────────────────────────────────── +# 用法: _download_with_mirror <文件名> <官方回退URL> <输出路径> +# 若设了 DESKTOP_BIN_MIRROR:先试 ${DESKTOP_BIN_MIRROR}/<文件名>(带可选 token +# header),命中即返回;未设 / 镜像失败则回退官方 <回退URL>。 +# SHA256 校验由调用方在下载后统一执行——镜像来的文件同样要过校验。 +_download_with_mirror() { + local filename="$1" fallback_url="$2" out="$3" + + if [[ -n "${DESKTOP_BIN_MIRROR:-}" ]]; then + local mirror_url="${DESKTOP_BIN_MIRROR%/}/${filename}" + local -a auth=() + if [[ -n "${DESKTOP_BIN_MIRROR_TOKEN:-}" ]]; then + auth=(-H "Authorization: token ${DESKTOP_BIN_MIRROR_TOKEN}") + fi + printf '==> [mirror] 尝试 %s…\n' "${mirror_url}" + # ${auth[@]+...} 兜住空数组 + set -u:macOS bash 3.2 下 "${auth[@]}" 在数组 + # 为空时会报 "unbound variable",此写法数组空则整体展开为空。 + if curl -fSL --retry 5 --retry-delay 3 --retry-all-errors --connect-timeout 15 \ + ${auth[@]+"${auth[@]}"} -o "${out}" "${mirror_url}"; then + printf ' ✓ [mirror] 命中\n' + return 0 + fi + printf ' ! [mirror] 未命中,回退官方源\n' >&2 + fi + + printf '==> 下载 %s…\n' "${fallback_url}" + curl -fSL --retry 8 --retry-delay 5 --retry-connrefused --retry-all-errors --connect-timeout 20 \ + -o "${out}" "${fallback_url}" +} + # ── 幂等检查(已有产物则跳过;--force 强制重下)──────────────────────────────── if [[ "${FORCE}" == false && -f "${OUT_BIN}" ]]; then printf '✓ %s 已存在,跳过下载\n' "${OUT_BIN}" @@ -138,11 +177,8 @@ if [[ -z "${EXPECTED_HASH}" ]]; then exit 1 fi -# ── 下载二进制压缩包 ────────────────────────────────────────────────────────── -printf '==> 下载 %s…\n' "${ARCHIVE_FILE}" -curl -fSL --retry 8 --retry-delay 5 --retry-connrefused --retry-all-errors --connect-timeout 20 \ - -o "${ARCHIVE_CACHE}" \ - "${ARCHIVE_URL}" +# ── 下载二进制压缩包(镜像优先,回退 GitHub Release)────────────────────────── +_download_with_mirror "${ARCHIVE_FILE}" "${ARCHIVE_URL}" "${ARCHIVE_CACHE}" # ── SHA256 校验(对压缩包,比对内置 pin)────────────────────────────────────── printf '==> 校验 SHA256…\n' @@ -197,9 +233,8 @@ if [[ "${TARGET_OS}" == "windows" ]]; then if [[ "${FORCE}" == false && -f "${WINTUN_OUT}" ]]; then printf '✓ wintun.dll 已存在,跳过(传 --force 重新下载)\n' else - curl -fSL --retry 8 --retry-delay 5 --retry-connrefused --retry-all-errors --connect-timeout 20 \ - -o "${WINTUN_ZIP_CACHE}" \ - "${WINTUN_URL}" + # 镜像优先,回退 wintun.net + _download_with_mirror "${WINTUN_ZIP_NAME}" "${WINTUN_URL}" "${WINTUN_ZIP_CACHE}" printf '==> 校验 wintun.zip SHA256…\n' WINTUN_ACTUAL="$(_sha256 "${WINTUN_ZIP_CACHE}")"