ci(wine): add verified archive mirror fallback

This commit is contained in:
Tianyi Cui
2026-08-09 19:58:29 +08:00
parent a8daedc1d9
commit 548726eede
4 changed files with 20 additions and 10 deletions

View File

@@ -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: a1f294b2b9e73a5d14a00780c7b0adfaf58e4702 2026-08-08-native-windows-pull-request-ci.md: 258bca96db04c44ca2a3509c297028e31ef5375e
2026-08-08-native-windows-pull-request-ci.zh.md: 2c91c21118f5ebbd9f0e341f7d31ec71481db4dc 2026-08-08-native-windows-pull-request-ci.zh.md: dd0031630eea9bb09a4a4db0125933ba0c7bac2f

View File

@@ -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 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. 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; when nodejs.org stalls on the large archive, a range-capable transport mirror resumes the same bytes, but nodejs.org remains the version and SHA-256 authority and the archive is never promoted before that checksum passes. 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.

View File

@@ -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)。Node 分发文件传输采用有界重试,使停滞的下载在耗尽作业超时前失败或恢复。稳定的 `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 分发文件传输采用有界重试;nodejs.org 的大文件传输停滞时,由支持范围请求的传输镜像续传相同字节,但版本和 SHA-256 权威仍属于 nodejs.org,归档通过该校验前绝不会投入使用。稳定的 `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` 之外:聚合流程既不等待它,也不会因它改变结论;原生作业则保留自身未被掩盖的成功或失败结果。

View File

@@ -77,22 +77,32 @@ mkdir -p "$cache_dir" "$scratch/logs"
curl_metadata_args=( curl_metadata_args=(
--fail --silent --show-error --location --fail --silent --show-error --location
--retry 3 --retry-all-errors --retry-delay 2 --retry 3 --retry-all-errors --retry-delay 2
--connect-timeout 10 --max-time 30 --retry-max-time 120 --http1.1 --connect-timeout 10 --max-time 30 --retry-max-time 120
) )
download_node_archive() { download_node_archive() {
local url="$1" output="$2" attempt status=0 local version="$1" output="$2" attempt status=0
local archive="node-$version-win-x64.zip"
local primary_url="https://nodejs.org/dist/$version/$archive"
local mirror_url="https://npmmirror.com/mirrors/node/$version/$archive"
if curl --fail --silent --show-error --location --http1.1 \
--connect-timeout 10 --max-time 300 --speed-limit 1024 --speed-time 30 \
-o "$output" "$primary_url"; then
return 0
fi
echo 'wine-windows-gates: nodejs.org archive transfer stalled; resuming from the checksum-untrusted transport mirror' >&2
for attempt in 1 2 3; do for attempt in 1 2 3; do
if curl --fail --silent --show-error --location \ if curl --fail --silent --show-error --location --http1.1 \
--continue-at - --connect-timeout 10 --max-time 300 \ --continue-at - --connect-timeout 10 --max-time 300 \
--speed-limit 1024 --speed-time 30 \ --speed-limit 1024 --speed-time 30 \
-o "$output" "$url"; then -o "$output" "$mirror_url"; then
return 0 return 0
else else
status=$? status=$?
fi fi
(( attempt < 3 )) || break (( attempt < 3 )) || break
echo "wine-windows-gates: Windows Node archive transfer failed (exit $status) on attempt $attempt; resuming partial download" >&2 echo "wine-windows-gates: mirror transfer failed (exit $status) on attempt $attempt; resuming partial download" >&2
done done
return "$status" return "$status"
} }
@@ -109,7 +119,7 @@ provision_node() {
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
download_node_archive "https://nodejs.org/dist/$version/node-$version-win-x64.zip" "$zip.tmp" download_node_archive "$version" "$zip.tmp"
local expected local expected
expected="$(curl "${curl_metadata_args[@]}" "https://nodejs.org/dist/$version/SHASUMS256.txt" \ expected="$(curl "${curl_metadata_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 }')"