确认是不是 Release 资产问题

把「GitHub 打不开」「仓库 clone 慢」和「Release 某个文件下不来」分开。Release 页面上通常同时有维护者上传的 asset,以及 GitHub 自动生成的 Source code zip / tar.gz。前者可能是 .dmg.exe.tar.gzSHA256SUMS,后者只是某个 tag 的源码快照。

# 只看响应头和跳转,不下载大文件
curl -I -L --connect-timeout 10 --max-time 30 \
  https://github.com/OWNER/REPO/releases/download/v1.2.3/app-macos.tar.gz

# 用 GitHub CLI 下载指定 release 的资产
gh release download v1.2.3 -R OWNER/REPO -p '*.tar.gz' -D ./dist-cache

# 下载 source archive,而不是维护者上传的 asset
gh release download v1.2.3 -R OWNER/REPO --archive=zip -D ./src-cache

如果 source archive 能下,某个 asset 失败,重点查资产大小、文件名、跳转和发布状态。如果所有 GitHub release 链接都失败,再看 DNS、代理、公司网络和 GitHub Status。

现象更可能的原因做什么
Source code zip 可下,.dmg.exe 超时asset 体积、跳转链路、公司网关拦截curl -I -L 看 302 和最终响应
浏览器可下,CI 失败runner 出口、无登录态、latest 变化固定 tag、加 token、记录 runner 地区
curl 立即 404文件名、tag、私有仓库权限用 API 列出 assets,不手拼 URL
curl 卡到 error 28DNS、TCP/TLS、代理或总超时拆开 --connect-timeout--max-time

Release asset 和 source archive 差在哪?

GitHub 文档说明,Release 绑定 Git tag;页面上的 zip 和 tarball 是从 tag 生成的源码归档。仓库管理员还可以决定 Git LFS 对象是否进入这些自动归档。它适合给用户拿源码,不适合承诺「可安装产物」。

Release asset 是维护者上传的文件。GitHub 文档给出的限制是单个 release 最多 1000 个 assets,单文件小于 2 GiB,release 总大小和带宽没有固定上限。这个 2 GiB 限制很关键:出海工具如果把模型、浏览器内核、多个平台安装包全塞进一个文件,下载失败时很难定位。

REST API 里,asset 会有 browser_download_urlcontent_typesizedownload_countstatedigest 等字段。digest 字段可能为空,所以不要把它当成所有项目都有的校验入口。更稳的发布方式是同时上传 SHA256SUMS、签名文件和安装包。

浏览器能下,curl 为什么会超时?

浏览器会帮你处理重定向、Cookie、下载恢复和企业安全策略提示。curl 默认不会替你判断这些上下文;GitHub Release asset API 在二进制下载时还可能返回 200 或 302,客户端要能跟随跳转。

# 公共 asset:跟随跳转,限制连接阶段和总耗时
curl -L --fail \
  --connect-timeout 10 \
  --max-time 300 \
  --retry 4 \
  --retry-delay 0 \
  --retry-max-time 900 \
  -o app-macos.tar.gz \
  https://github.com/OWNER/REPO/releases/download/v1.2.3/app-macos.tar.gz

# 私有仓库 asset:先通过 API 拿资产,Accept 用 octet-stream
curl -L --fail \
  -H "Accept: application/octet-stream" \
  -H "Authorization: Bearer $GITHUB_TOKEN" \
  -o app-macos.tar.gz \
  https://api.github.com/repos/OWNER/REPO/releases/assets/ASSET_ID

curl 文档把 --connect-timeout 限定在 DNS、TCP、TLS/QUIC 连接阶段,--max-time 是单次操作总时间。超时常见退出码是 28。--retry 会重试 timeout 以及 HTTP 408、429、500、502、503、504 等临时失败;--retry-max-time 控制整个重试窗口。

DNS、代理和公司网络怎么分层查?

公司网络里的 release 下载失败常常不是「GitHub 慢」四个字能解释。TLS 检查、下载类型限制、私有 DNS、代理 PAC、EDR 扫描大文件,都可能让二进制 asset 比 source archive 更容易失败。

# 解析和连接基线
nslookup github.com
nslookup objects.githubusercontent.com
curl -I -L https://github.com --connect-timeout 10 -m 30

# 看当前 shell 是否带代理变量
env | grep -i '_proxy'

# 临时指定代理测试,避免改全局配置
HTTPS_PROXY=http://127.0.0.1:7890 \
  curl -L --fail --connect-timeout 10 --max-time 120 \
  -o /tmp/release-test.bin "$ASSET_URL"

如果团队成员分布在共享办公、酒店网络和云桌面,最好把 GitHub、GitHub Actions、Cloudflare、Stripe Dashboard 的访问路径写进 runbook。先记录谁在哪条网络下载失败,再决定是改 curl 参数、补校验文件,还是处理办公网络。

CI/CD 里怎么做 fallback?

CI 里最怕裸写 releases/latest/download/app.tar.gz。latest 是移动目标,今天指向 v1.2.3,明天可能变成 v1.2.4。失败时你连重放同一个输入都困难。

发布链路推荐做法不推荐做法
依赖第三方 CLI固定 tag、asset 文件名和 SHA-256每次从 latest 拉最新包
自家工具分发Release asset + SHA256SUMS + 签名只上传一个大压缩包
GitHub Actions缓存下载目录,失败保留 curl 日志日志里只打印「download failed」
自建 runner记录出口 IP、DNS、代理和时间把本机成功当作 runner 成功

一个可落地的 fallback 是:主路径从 GitHub Releases 下载固定版本;失败后从内部对象存储或私有 registry 拉同一文件;两条路径都必须用同一份 SHA-256 校验。这样你换的是下载来源,不是换文件内容。

shasum -a 256 app-macos.tar.gz
# Linux runner 可用 sha256sum app-macos.tar.gz

什么时候该做内部镜像?

不是每个项目都要镜像 Release。个人开源工具每月几百次下载,GitHub Release 足够;真正该做内部镜像的,是构建链路、客户交付或安装脚本已经依赖这个文件。

可以用三个条件判断:第一,CI 每天重复下载同一资产超过 20 次;第二,单个资产超过 300 MB,失败一次就拖慢整条流水线;第三,企业客户在公司网络下经常无法下载 .exe.pkg 或压缩包。满足两个,就该把发布资产同步到内部对象存储、GHCR、私有 npm 包或企业文件服务。

镜像不是改名重传。保留原始文件名、版本号、SHA-256、发布日期和 GitHub release URL,才能在安全审计和客户支持时说清楚「这个内部文件对应哪个上游发布」。

还没恢复时的升级证据

升级给同事或平台支持前,把证据收敛成一页,不要只贴最后一行错误。

证据记录方式
失败 URLasset URL、tag、文件名、是否 private
资产元信息API 返回的 sizecontent_typestatedigest
下载命令完整 curl 参数、GitHub CLI 命令、是否带 token
网络环境本地、公司网、云服务器、GitHub Actions runner
时间窗口UTC 时间、GitHub Status 是否有 API 或 Git Operations 事件

GitHub Status 没有单独的 release-assets 组件,排查时看 API Requests、Git Operations、Packages 和 Past Incidents。若 status 正常且只有你的某个文件失败,优先回到文件大小、文件名、权限、跳转、代理和校验。

如果团队还要同时处理 GitHub Actions、Cloudflare、Stripe Dashboard 等后台,且故障集中在酒店、共享办公或云桌面网络,可以用海外服务跑 GitHub Actions / Cloudflare 的稳定线路承载后台操作;它解决访问路径抖动,不替代 curl 参数、校验和 CI 缓存。

相关阅读