Bläddra i källkod

ci(wine): bound Node distribution downloads

Tianyi Cui 1 månad sedan
förälder
incheckning
9b686a4203

+ 2 - 2
.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md
-2026-08-08-native-windows-pull-request-ci.md: 4e2ea07e90656f212f0613ffa17184ff2c3c8c45
-2026-08-08-native-windows-pull-request-ci.zh.md: 306243af3f3e0b280dd25caa5c99df2176590f3b
+2026-08-08-native-windows-pull-request-ci.md: a1f294b2b9e73a5d14a00780c7b0adfaf58e4702
+2026-08-08-native-windows-pull-request-ci.zh.md: 2c91c21118f5ebbd9f0e341f7d31ec71481db4dc

+ 1 - 1
.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.md

@@ -10,7 +10,7 @@ The required pull-request Windows verdict needs a fast win32 toolchain signal wi
 
 
 ## Decision
 ## Decision
 
 
-The required `windows` job in [ci.yml](../../../../.github/workflows/ci.yml) remains `windows node 24 / wine blocking` on `ubuntu-latest`. It retains the checksum-verified Windows Node, Wine apt and pnpm caches, a hoisted install confined to a workspace snapshot, and the [shared Wine gate script](../../../../scripts/wine-windows-gates.sh) that run the workspace build and production site. The stable `windows` job id remains a dependency of `all checks passed`. The [archived Wine experiment](../../archived/process/2026-07-27-wine-windows-gates-experiment.md) preserves its measured trade-offs, while this note owns the current dual topology.
+The required `windows` job in [ci.yml](../../../../.github/workflows/ci.yml) remains `windows node 24 / wine blocking` on `ubuntu-latest`. It retains the checksum-verified Windows Node, Wine apt and pnpm caches, a hoisted install confined to a workspace snapshot, and the [shared Wine gate script](../../../../scripts/wine-windows-gates.sh) that runs the workspace build and production site. Node distribution transfers use bounded retries so a stalled download fails or recovers before consuming the job timeout. The stable `windows` job id remains a dependency of `all checks passed`. The [archived Wine experiment](../../archived/process/2026-07-27-wine-windows-gates-experiment.md) preserves its measured trade-offs, while this note owns the current dual topology.
 
 
 Every pull request also starts an independent `windows-native` job named `windows node 24 / native complete` on GitHub's standard `windows-2025` image. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. The job is deliberately absent from `all-checks-passed.needs`: the aggregate neither waits for it nor changes conclusion because of it, while the native job retains its own unmasked success or failure result.
 Every pull request also starts an independent `windows-native` job named `windows node 24 / native complete` on GitHub's standard `windows-2025` image. It enables Developer Mode for workspace symlinks, provisions the repository-pinned pnpm through `pnpm/action-setup`, performs an immutable install without a transferred store archive, and runs `pnpm run check:ci:windows-complete` under native PowerShell. The job is deliberately absent from `all-checks-passed.needs`: the aggregate neither waits for it nor changes conclusion because of it, while the native job retains its own unmasked success or failure result.
 
 

+ 1 - 1
.agents/notes/implemented/process/2026-08-08-native-windows-pull-request-ci.zh.md

@@ -10,7 +10,7 @@ Status: implemented
 
 
 ## 决策
 ## 决策
 
 
-[ci.yml](../../../../.github/workflows/ci.yml) 中必需的 `windows` 作业仍是在 `ubuntu-latest` 上运行的 `windows node 24 / wine blocking`。它保留经过校验和验证的 Windows Node、Wine apt 与 pnpm 缓存、仅限工作区快照的 hoisted 安装,以及运行工作区构建与生产网站的[共享 Wine 门禁脚本](../../../../scripts/wine-windows-gates.sh)。稳定的 `windows` 作业 ID 仍是 `all checks passed` 的依赖项。[已归档的 Wine 实验](../../archived/process/2026-07-27-wine-windows-gates-experiment.md)保留其实测取舍,而本文负责当前双通道拓扑。
+[ci.yml](../../../../.github/workflows/ci.yml) 中必需的 `windows` 作业仍是在 `ubuntu-latest` 上运行的 `windows node 24 / wine blocking`。它保留经过校验和验证的 Windows Node、Wine apt 与 pnpm 缓存、仅限工作区快照的 hoisted 安装,以及运行工作区构建与生产网站的[共享 Wine 门禁脚本](../../../../scripts/wine-windows-gates.sh)。Node 分发文件传输采用有界重试,使停滞的下载在耗尽作业超时前失败或恢复。稳定的 `windows` 作业 ID 仍是 `all checks passed` 的依赖项。[已归档的 Wine 实验](../../archived/process/2026-07-27-wine-windows-gates-experiment.md)保留其实测取舍,而本文负责当前双通道拓扑。
 
 
 每个拉取请求还会在 GitHub 标准 `windows-2025` 镜像上启动一个独立的 `windows-native` 作业,名称为 `windows node 24 / native complete`。该作业为工作区符号链接启用开发人员模式,通过 `pnpm/action-setup` 提供仓库固定版本的 pnpm,在不传输 store 归档的情况下执行不可变安装,并在原生 PowerShell 下运行 `pnpm run check:ci:windows-complete`。该作业被刻意排除在 `all-checks-passed.needs` 之外:聚合流程既不等待它,也不会因它改变结论;原生作业则保留自身未被掩盖的成功或失败结果。
 每个拉取请求还会在 GitHub 标准 `windows-2025` 镜像上启动一个独立的 `windows-native` 作业,名称为 `windows node 24 / native complete`。该作业为工作区符号链接启用开发人员模式,通过 `pnpm/action-setup` 提供仓库固定版本的 pnpm,在不传输 store 归档的情况下执行不可变安装,并在原生 PowerShell 下运行 `pnpm run check:ci:windows-complete`。该作业被刻意排除在 `all-checks-passed.needs` 之外:聚合流程既不等待它,也不会因它改变结论;原生作业则保留自身未被掩盖的成功或失败结果。
 
 

+ 12 - 4
scripts/wine-windows-gates.sh

@@ -74,19 +74,27 @@ trap cleanup EXIT
 mkdir -p "$cache_dir" "$scratch/logs"
 mkdir -p "$cache_dir" "$scratch/logs"
 
 
 # ---- provision Windows Node, boot Wine, snapshot + install concurrently ----
 # ---- provision Windows Node, boot Wine, snapshot + install concurrently ----
+curl_download_args=(
+  --fail --silent --show-error --location
+  --retry 3 --retry-all-errors --retry-delay 2
+  --connect-timeout 10 --max-time 90 --retry-max-time 240
+)
+
 provision_node() {
 provision_node() {
   # Latest release of the primary line, checksum-verified against the same
   # Latest release of the primary line, checksum-verified against the same
-  # dist directory. Offline runs fall back to the newest cached zip, loudly.
+  # dist directory. Bound and retry every transfer so a stalled nodejs.org
+  # response cannot consume the entire CI job. Offline runs fall back to the
+  # newest cached zip, loudly.
   local version zip
   local version zip
-  version="$(curl -fsSL --max-time 30 https://nodejs.org/dist/index.json 2> /dev/null \
+  version="$(curl "${curl_download_args[@]}" https://nodejs.org/dist/index.json 2> /dev/null \
     | node -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{const v=JSON.parse(d).find(r=>r.version.startsWith('v$node_major.'));if(v)console.log(v.version)})" \
     | node -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{const v=JSON.parse(d).find(r=>r.version.startsWith('v$node_major.'));if(v)console.log(v.version)})" \
     || true)"
     || true)"
   if [ -n "$version" ]; then
   if [ -n "$version" ]; then
     zip="$cache_dir/node-$version-win-x64.zip"
     zip="$cache_dir/node-$version-win-x64.zip"
     if [ ! -f "$zip" ]; then
     if [ ! -f "$zip" ]; then
-      curl -fsSL -o "$zip.tmp" "https://nodejs.org/dist/$version/node-$version-win-x64.zip"
+      curl "${curl_download_args[@]}" -o "$zip.tmp" "https://nodejs.org/dist/$version/node-$version-win-x64.zip"
       local expected
       local expected
-      expected="$(curl -fsSL "https://nodejs.org/dist/$version/SHASUMS256.txt" \
+      expected="$(curl "${curl_download_args[@]}" "https://nodejs.org/dist/$version/SHASUMS256.txt" \
         | awk -v a="node-$version-win-x64.zip" '$2 == a { print $1; exit }')"
         | awk -v a="node-$version-win-x64.zip" '$2 == a { print $1; exit }')"
       [ -n "$expected" ] || { echo "wine-windows-gates: no SHASUMS256 entry for node-$version-win-x64.zip" >&2; exit 1; }
       [ -n "$expected" ] || { echo "wine-windows-gates: no SHASUMS256 entry for node-$version-win-x64.zip" >&2; exit 1; }
       verify_sha256 "$expected" "$zip.tmp"
       verify_sha256 "$expected" "$zip.tmp"