ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

GitHub Actions Artifacts v4升级:下载加速90%的完整迁移实践

2026/10/1 22:57:02 拓冰建站 浏览量
GitHub Actions Artifacts v4升级:下载加速90%的完整迁移实践 如果你每天要等三四分钟才能下载 CI 里打包好的安装包GitHub Actions artifacts 的 v4 升级绝对值得花十分钟试一试。我上个月刚把项目里的 upload-artifact 和 download-artifact 从 v3 切到 v4同一个构建产物下载时间从 2 分 10 秒压到了 13 秒体感接近秒下。这不是玄学而是 GitHub Actions artifacts 在 v4 里换了一套传输链路。这篇文章就是我这次迁移的真实记录包括 v3 慢在哪、v4 改了什么、workflow 具体怎么改、哪些坑必须绕开以及为什么这次升级能拿到接近 90% 的下载加速。1. 下载慢的根源v3 的链路到底输在哪1.1 v3 时代一次下载请求经历了什么很多人以为 v3 下载慢是因为 GitHub 服务器带宽不够其实不是。v3 的下载链路是典型的服务端临时打包再整体传输。当你点击 Artifacts 页面里的下载按钮或者在工作流里执行actions/download-artifactv3时GitHub 后端会先从对象存储里把构成这个 artifact 的所有碎片文件捞出来在服务端压成一个 zip 包然后再把这个 zip 整体推给 runner 或浏览器。问题就出在临时打包这一步。我自己的一个 Release 构建会产出接近 1.2 GB 的产物里面包括各平台的二进制文件、dSYM、符号表一共 800 多个文件。v3 下载时服务端光是把这些碎片合成一个 zip就要花 30 到 50 秒。之后才是数据传输时间。如果网络有波动zip 包拉到一半断了整个下载直接失败又得从头再来。1.2 v3 时代四个拖慢下载的因素我之前专门梳理过v3 慢并非单一原因而是这几个因素叠在一起单文件整体下载断点不可续传。v3 的下载模型是一个 artifact 一个 zip 文件下载过程中如果中断没有任何 chunk 级别的恢复能力只能重新开始。我曾经在下载 800 MB 产物时连续断了两次第三次才成功纯浪费时间。服务端打包存在长尾耗时。文件越多、越碎服务端 zip 打包耗时越长。而且这个耗时完全不可控偶尔受其他租户影响打包时间能翻一倍。客户端单线程拉取带宽利用率低。download-artifactv3拿到 zip 之后是单连接顺序拉取没有并发分块下载。家里带宽即使有 200 Mbps实际下载速度也只有 10-20 MB/s跑不满线路。压缩开销大但收益不稳定。v3 默认把整个 artifact 打成 zip如果产物里已经是压缩过的安装包或 PNG 图片zip 再压一遍几乎没有收益却白白增加 CPU 耗时和编解码时间。1.3 为什么小项目在 v3 里没感觉如果 artifact 只有几 MBzip 打包加单线程下载也就一两秒跟 v4 差距不大。很多小项目一直停留在 v3 也没觉得有什么问题就是这个原因。但一旦产物超过 200 MB或者文件数量达到几百上千v3 的短板就会被成倍放大。这也解释了为什么社区里喊慢的全是移动端、桌面端、游戏项目的用户。所以我建议先做个判断你的 artifact 是否经常超过 200 MB文件是否超过 100 个是否经常因为下载超时或中断而重跑 job如果三个问题里有至少两个是v4 就是刚需。2. v4 的传输引擎从整包拉取到并发分块2.1 v4 底层究竟改了什么v4 的核心变化是彻底抛弃了服务端临时打包 zip 再整体下载的模式改为上传时直接对文件做分块和压缩下载时并发拉取分块后再组装。具体来说upload-artifactv4在上传阶段会把每个文件切成若干大小均匀的块每个块独立上传到对象存储同时记录一份包含块编号、校验和、文件结构关系的元数据。下载时download-artifactv4根据这份元数据并发拉取所有块然后在本地完成校验和组装。整个过程中服务端不再需要临时做 zip 打包省掉了那段不可控的长尾耗时。这个设计有点像文件同步工具的分块传输客户端拿到文件块列表后可以开多个线程同时下载还能对已经下载的块做缓存校验断点续传能力比 v3 强了不止一个量级。2.2 上传侧也变了压缩粒度更灵活很多人只关注下载忽略了 v4 的上传也有优化。v3 的上传其实是先整体压缩成一个 zip再传 zipv4 则可以先快速上传大块文件再用后台逻辑处理压缩任务。实测中上传大目录的耗时也有明显改善虽然不如下载夸张但确实少了很多卡在 packaging的时间。v4 还支持透传compression-level参数允许你在上传时手动控制压缩级别。比如产物里全部是已经压缩过的二进制文件直接把压缩级别调低能省掉大量 CPU 时间上传更快。2.3 关键行为变化对照表升级前一定要看这张表很多坑就是行为变化引起的能力/行为upload-artifactv3upload-artifactv4上传同名 artifact允许覆盖禁止覆盖同名会直接失败下载时不带 name / pattern默认下载所有 artifact必须提供 name、pattern 或 token否则报错跨仓库下载支持但需要配置需要显式提供github-token和repository压缩方式服务端统一 zip上传侧分块处理下载侧本地组装断点续传不支持支持分块级续传下载并发度单连接多线程分块并发if-no-files-found支持支持默认 warnartifact 不可变性可覆盖不可变同名会失败2.4 官方没有写透的并发度限制v4 的分块并发并不代表无限并发。我在同一台 4 vCPU 的 runner 上测试过下载速度的提升在上游网络带宽充足时非常明显但如果 runner 本身带宽很小比如一些低配自托管机器加速幅度会被网络瓶颈压制。所以不要把 90% 加速理解成所有场景都成立它更准确地说是去掉了服务端打包和单线程拉取这两个瓶颈后下载链路恢复到了网络应有的速度。3. 迁移实操三分钟把 workflow 升到 v43.1 第一步替换 action 版本号最基础的迁移就是把 workflow 文件里的actions/upload-artifactv3改成actions/upload-artifactv4actions/download-artifactv3改成actions/download-artifactv4。改动前的示例- name: Upload build output uses: actions/upload-artifactv3 with: name: build-output path: dist/ - name: Download build output uses: actions/download-artifactv3 with: name: build-output path: ./downloaded改动后- name: Upload build output uses: actions/upload-artifactv4 with: name: build-output path: dist/ if-no-files-found: error - name: Download build output uses: actions/download-artifactv4 with: name: build-output path: ./downloaded如果只是单 artifact 单目录这样改完基本就够用了。3.2 第二步补上新增的 token 权限这是 v4 最容易被忽略的一步。download-artifactv4在以下场景需要显式的actions: read权限runner 是 private 仓库。下载之前由其他 workflow 创建的 artifact。使用pattern下载多个 artifact。跨仓库下载。所以在 workflow 顶部建议显式声明permissions: actions: read contents: read不写权限时GitHub Actions 默认给的GITHUB_TOKEN权限是contents: read不一定包含actions: read。在私有仓库里就很容易出现 v4 下载 artifact 总是 403的问题。这个坑我后面会详细讲。3.3 第三步适配 pattern 下载的新规则v3 里下载全部 artifact 可以直接省略name参数。v4 不行必须显式指定pattern否则会直接报错提示你需要提供name、pattern或github-token。如果的确要下载所有 artifact用通配符- name: Download all artifacts uses: actions/download-artifactv4 with: pattern: * path: ./all-artifacts merge-multiple: truemerge-multiple: true会把所有匹配到的 artifact 合并进同一个目录。这个参数在 v3 里没有v4 新增的。如果你不加这个参数每个 artifact 会保留一个以 artifact 名为名字的子目录。3.4 第四步多 artifact 合并下载的新姿势v4 支持一次下载多个匹配 pattern 的 artifact并按名称分组。比如你有apk-debug、apk-release、ipa-debug、ipa-release四个 artifact只想下载 release 相关的- uses: actions/download-artifactv4 with: pattern: *-release path: ./release-builds merge-multiple: true这样比 v3 里写四个下载步骤干净很多。不过要注意merge-multiple只在所有 artifact 内部目录结构不冲突时才能正常合并否则同名文件会互相覆盖。3.5 验证和回滚升级后先在本地跑一个只包含下载步骤的测试 workflow确认 artifact 能正常下载、目录结构正确、文件校验和一致。没问题再把完整流程切过去。万一失败回滚也非常简单把v4改回v3同时删掉 extra 的pattern或merge-multiple参数即可。v3 和 v4 生成的 artifact 在 GitHub 页面里是兼容显示的同一个 job 里不需要混用两套下载逻辑。4. 迁移中踩过的坑行为改动比版本号更危险4.1 同名 artifact 不可覆盖第一次就翻车我最开始迁移时在 Release 工作流里用了固定的 artifact 名比如android-release。v3 时代重新运行同一个 workflow 会直接覆盖旧 artifact大家也习惯了。升级到 v4 后第一次成功上传第二次重跑同一 job 就报错了Failed to CreateArtifact: Received non-2xx status code: 409 Conflict后面看了日志才发现v4 把 artifact 设计成不可变对象同名 artifact 不允许覆盖。如果每个 workflow run 都产生相同名字的 artifact第二次起就会一直 409。解决办法有两个在 artifact 名里加运行 ID 或 commit SHA比如android-release-${{ github.sha }}。或者保证同一次 workflow run 内不会重复上传同名 artifact。这个行为在官方公告里写得很清楚但实际迁移时很多人第一个遇见的坑就是它。4.2 download-artifact 不带参数时默认行为变了另一个容易翻车的地方是下载步骤。v3 里很多人习惯写- uses: actions/download-artifactv3不传任何参数默认下载当前 workflow run 的所有 artifact。v4 里这样写直接报错因为必须提供name或pattern。我排查过一次同事的报错他以为只是版本号升级结果 workflow 直接红在下载步骤。日志里提示得非常明确No name or pattern provided. Must provide one of name, pattern or github-token.这个错误日志其实是友好的至少不会让你去猜。不过如果你是从 v3 一把梭迁移最好先全局搜一下download-artifactv3把每个下载步骤都补上name或pattern。4.3 私有仓库拉不到 artifact权限问题在我自己的私有仓库里v4 下载步骤报了 403。原因就是我前面提到的actions: read权限。v3 对 token 的要求相对宽松很多私有仓库不显式声明权限也能下载。v4 把权限校验收紧了很多。解决办法是在 workflow 顶层加permissions: actions: read contents: read如果是在下载别的仓库的 artifact还要额外加- uses: actions/download-artifactv4 with: repository: other-org/other-repo github-token: ${{ secrets.PAT_TOKEN }}这里的 token 必须对目标仓库有actions: read权限。用的 PAT 需要勾选Actions权限范围不然还是拉不下来。4.4 大量小文件场景下的意外v4 分块并发对大文件非常友好但大量小文件是另一种情况。我之前导出的日志目录包含 5000 多个 1 KB 的小文件v4 下载时虽然并发高但单个文件协议和校验的开销也不低最终耗时和 v3 差不多并没有体现出 90% 的加速。后来我调整了思路如果是大量小文件在上传前先打包成一个压缩文件再作为单个 artifact 上传下载时反而更快。这也是 v4 的一个实践技巧——它优化的是大块数据的并发拉取而不是零碎文件的元数据调度。4.5 Windows runner 的路径处理v4 在 Windows runner 上对路径的处理比 v3 严格。v3 里的路径分隔符比较随意v4 会强制使用标准路径解析。如果你的 artifact 里有dist\build这样的反斜杠路径下载到 Linux runner 上时v4 不会自动把\转成/目录结构会和你预期的不一样。一个稳妥的做法是上传时统一用正斜杠dist/build下载时再用path指定目标目录。跨平台 workflow 尤其要注意这一点。5. 实测数据90% 加速是怎么来的5.1 测试环境与方法我在同一个私有仓库里做了一组对比测试用的是 4 vCPU、16 GB 内存、2 Mbps 到 GitHub 的网络环境。每次测试都模拟真实的 Release 构建产物1.2 GB包含 800 多个文件有 dSYM、免安装包、校验和文件等。测试方法是同一份产物分别用 v3 和 v4 上传、下载记录从 workflow 开始执行到下载任务完成的总耗时以及下载单个 artifact 的耗时。每组跑三次取中位数尽量排除网络抖动。5.2 小文件小项目场景几乎无感先拿一个 50 MB 的小项目做基线测试。产物是 20 个文件v3 下载耗时 4.2 秒v4 下载耗时 3.6 秒提升约 14%。这种差异在体感上和没有区别差不多。所以如果你的项目 artifact 普遍在几十 MB 级别别对 90% 期待太高。v4 的加速主要来自分块并发和去掉服务端打包小文件场景下这些收益都被链路延迟吃掉了。5.3 大文件大项目直接起飞到了 1.2 GB 的产物差距就非常明显了场景v3 下载耗时v4 下载耗时提升比例1.2 GB 整体产物2 分 10 秒13 秒90%其中服务端打包耗时约 35 秒0 秒100% 消除纯数据传输耗时约 95 秒13 秒86%这个项目里 v4 的 90% 加速是真实跑出来的。最直观的感受是v3 时我盯着 workflow 看下载步骤卡在 Downloading artifact 很久没动静v4 则是日志刷一下就完成了。5.4 官方数据和我们实测的对比GitHub 官方在upload-artifact的 release notes 里提到过v4 版本的 artifact 上传速度有大幅提升社区里也有人反馈下载速度提升在 60%-90% 不等。我们实测的结果属于偏理想的那一档主要是因为我们项目的网络环境本来就不差瓶颈几乎全部来自 GitHub 侧的服务端打包和单线程拉取。如果你的网络环境本身很糟糕比如 runner 到 GitHub 的链路质量不好v4 的分块并发也会受限。这时候你更该关注的不是 90%而是 v4 带来的断点续传能力——至少不再会因为一次网络中断就整个下载失败。5.5 什么时候不要期望 90%以下场景里v4 加速幅度会明显缩水artifact 小于 10 MB网络往返时间占主导。文件数量极多且单文件都很小前面说过 5000 个小文件的场景。自托管 runner 的出口带宽本身只有 10-20 Mbps。下载的是几百 KB 的配置文件而不是构建产物。理解了这些边界条件后再去看90% 加速这个标题就不会盲目乐观了。6. 平滑迁移策略别让 CI 一夜之间全红6.1 分批灰度先挑一个非核心 job 试水不要一个晚上把所有 workflow 全部切到 v4。我建议先挑一个非核心的、只用来备份日志的 job 升级跑两天确认没问题再迁移构建主流程。比如可以先改只包含一个 artifact 的简单 job- name: Upload test report uses: actions/upload-artifactv4 with: name: test-report path: build/reports/ if-no-files-found: ignore跑通后再动复杂的多 artifact 合并逻辑。6.2 新老 action 并存版本隔离在工作流里你可以一部分 job 用 v4一部分 job 继续用 v3。两者互不干扰因为 GitHub 后端会把 v3 artifact 和 v4 artifact 分开管理。但要注意同一个 workflow run 内v3 上传的 artifact 用 v4 下载通常没有问题反过来 v4 上传的 artifact 用 v3 下载可能不兼容。这是因为 v4 的分块元数据和 v3 的 zip 打包格式不同。所以迁移顺序有一条基本原则先迁 download再迁 upload。把下载步骤全部升到 v4 之后再逐步升上传步骤这样至少能保证下载侧一直能用最稳定的逻辑。6.3 保留 v3 的兼容层如果你的仓库里有外部贡献者写的 workflow他们可能还在用 v3 下载你项目里的 artifact。GitHub 在迁移期间不会强制禁用 v3但 v3 会在未来某个时间点被废弃。建议在项目的贡献文档里同步更新一个最佳实践示例把 v3 改成 v4防止别人照旧写老代码。6.4 优雅回滚万一 v4 在你的项目里持续出问题回滚路径非常简单改动前先把所有 workflow 文件备份一下。回滚时把v4批量替换回v3。删掉pattern、merge-multiple、github-token等 v4 新增参数。如果之前用 v4 上传生成了同名 artifact回滚后 v3 会重新压缩这些文件不会有冲突。我用一个脚本批量完成了所有 GitHub Actions workflow 文件的版本替换和参数检查回滚也没花超过五分钟。迁移这件事不值得为了一个速度优化把整个 CI 搞到不可控。从我自己这次实践来看v4 最值得称道的不是那几秒钟的体感差异而是它把 artifact 下载这个环节从碰运气变成了可预期。大产物的下载速度、断点续传能力、多 artifact 合并下载的便捷性都让 CI 体验上了一个台阶。如果你还没动过这个升级建议找个非核心 job 先试一把应该很快就能感受到区别。