news 2026/10/1 22:55:41

GitHub Actions v4 artifact 迁移:下载提速90%的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GitHub Actions v4 artifact 迁移:下载提速90%的实战指南

1. 为什么 v4 能快 90%:先搞清楚 v3 慢在哪里

1.1 旧模型:每次传 artifact 都像寄一个大箱子

先说结论:v3 慢不是玄学,是架构决定的。在 v3 时代,actions/upload-artifact 在上传时会先把工作目录里的所有文件压缩成一个 zip,再把这个 zip 推到 GitHub 的对象存储里。等到需要下载时,download-artifact 会向服务端请求这个 zip,完整下载到 runner 上,然后原地解压。这个流程在文件少、体积小的时候没什么感觉,但一旦产物到了几百 MB 甚至几个 GB,瓶颈就很明显了。

打个比方,这就像你要从 A 地寄一箱杂物到 B 地。寄出前,你得先花时间把所有东西压实成一个箱子;到达后,收件人还得再拆箱。箱子越大、件数越碎,打包和拆箱的成本就越高。更糟的是,整个运输过程只有一条“单行线”,箱子一旦开始传输,就必须全部拉完,中间出现一次网络抖动,整段时间都要顺延。

如果你经常使用 GitHub Actions,一定见过类似这样的日志:上传阶段一直卡在 "Uploading artifact content",或者下载阶段长时间停在 "Downloading artifact"。生产环境里遇到大产物,v3 的上传下载经常各占三四分钟,这是很正常的。

1.2 新模型:v4 的“内容寻址块”到底改了什么

v4 最大的变化不是换了一个 action 版本号,而是把 artifact 的存储后端改了。按官方博客和 changelog 的说法,v4 不再以单一 zip 包的形式保存整个 artifact,而是采用内容寻址存储,文件会被切分成数据块,按内容去重并索引,上传时并发推送,下载时按需并发拉取,不再需要等服务端先帮你把整个 zip 准备好。

这个变化带来的效果是:一方面,上传阶段省掉了一部分服务端的打包和压缩等待;另一方面,下载阶段不再“一条线程把整个 zip 拖回来”,而是可以针对不同的数据块并发取回,最后在 runner 本地重新组装。对于大文件、碎文件特别多的产物,速度提升非常明显。

这不是个玄幻的“优化了一点”,官方给出的 benchmark 是下载最多提速 90%,上传也有显著提升。我自己的项目里,一个 1.8GB 的安装包,download-artifact 从 v3 的 4 分多钟降到 v4 的 40 秒以内,和官方数据大致吻合。

注意,这里只是“不再依赖单一 zip 做整个归档”,不代表 v4 完全没有压缩。upload-artifact v4 依然提供了 compression-level 参数,默认压缩级别是 6。它更像是在传输和存储形态上做了更聪明的调度,而不是彻底去掉压缩能力。

2. 开始迁移:v3 到 v4 的完整改造步骤

2.1 第一步:全局替换两个 action 的版本引用

迁移动作本身很小,其实就是改 workflow 文件。把actions/upload-artifact@v3改成actions/upload-artifact@v4,把actions/download-artifact@v3改成actions/download-artifact@v4。

- uses: actions/upload-artifact@v4 with: name: build-output path: dist
- uses: actions/download-artifact@v4 with: name: build-output path: ./download

如果你项目里有大量 workflow,可以全局搜索upload-artifact@v3和download-artifact@v3,一次性替换。但这里有个非常容易踩的坑:upload 和 download 必须同步升级,不能出现“构建 job 用 v4 上传,发布 job 还在用 v3 下载”的情况。

为什么?因为 v4 生成 artifact 的存储格式和 v3 不兼容,download-artifact@v3 根本读不了 v4 上传的内容。反过来,download-artifact@v4 也下载不了 v3 上传的旧 artifact。所以第一次迁移时,建议全局梳理一遍 workflow 的调用关系,确保每一个 upload 都有对应的 v4 download,避免遗漏。

2.2 第二步:处理下载路径和多 artifact 合并

如果你只是在 workflow 里下载一个 artifact,基本不用改逻辑。真正需要留意的是“一次下载多个 artifact”的情况。

在 v4 里,download-artifact 支持用pattern一次性匹配多个 artifact,把所有匹配到的内容下载到同一个path目录。但默认情况下,不同 artifact 在目标目录里会保持各自的名称,形成子目录。比如:

- uses: actions/download-artifact@v4 with: path: all-artifacts pattern: "app-*"

下载完后,目录结构会是:

all-artifacts/ app-linux/ ... app-macos/ ...

如果你的后续步骤需要把这些文件混在同一个目录里处理,可以在 with 里加merge-multiple: true。这是 v4 提供的一个合并选项:

- uses: actions/download-artifact@v4 with: path: merged pattern: "app-*" merge-multiple: true

加了 merge-multiple 之后,所有匹配 artifact 的文件会被解压到同一个目录中,不再额外套 artifact 名称的子目录。这个功能对“多个 job 分别产出碎片,最后统一收集到一起再发布”的场景特别有用。

但要注意,merge-multiple 只适用于通过 pattern 匹配多个 artifact 的场景。如果多个 artifact 里存在同名文件,合并阶段会直接报错,因为 v4 不会默默覆盖。遇到这种情况,要么改产物命名,要么改成“分开下载再在 shell 里处理”。

2.3 第三步:确认自托管 runner 的 Node 版本

v4 action 是跑在 Node 20 运行时上的。如果你用的是 GitHub 托管的 ubuntu-latest / windows-latest / macos-latest,不需要担心;但如果你有自托管 runner,请先检查 runner 版本是否足够新。官方要求 runner 版本至少是 2.308.0 以上,否则执行到 upload/download 步骤时,会出现类似 “Unable to locate executable file: node” 或 “Runner is not configured to run Node 20” 的报错。

升级自托管 runner 不是把 action 版本改完就结束。建议在改 workflow 之前,先在自托管 runner 上跑一次node -v,确认 node 版本;或者直接重新拉取最新的 runner 包,按官方文档重新配置一次服务。如果 runner 是别人统一运维的,先和团队打好招呼,再开始迁移。

很多人迁移失败,都不是 action 语法问题,而是 runner 跑不了 Node 20。这步虽简单,但务必提前确认。

3. 核心细节:参数、保留期与性能调优

3.1 v4 常用参数一张表说清楚

upload-artifact 和 download-artifact 在 v4 里都有一些值得关注的输入参数。我把最常用的列成一张表,方便对照着改:

Action参数含义备注
upload-artifactnameartifact 的名称默认是 artifact,同一个 workflow 里重名会合并
upload-artifactpath要上传的文件或目录支持多行、通配符
upload-artifactif-no-files-found没文件时怎么办可选 warn / error / ignore
upload-artifactretention-days保留天数默认 90,不能超过仓库或组织设置的上限
upload-artifactcompression-level压缩级别v4 新增,0-9,默认 6
upload-artifactinclude-hidden-files是否包含隐藏文件v4 新增,默认 false
download-artifactname要下载的 artifact 名与 pattern 二选一,不能同时使用
download-artifactpath下载到哪个目录默认当前工作目录
download-artifactpattern匹配多个 artifact 名支持 glob 匹配,如 app-*
download-artifactmerge-multiple是否合并到同一目录配合 pattern 使用,默认 false

这些参数在 v3 里大多也有,但 v4 新增的两个优化参数值得单独讲,尤其是 compression-level,很多人不知道,浪费了不少时间。

3.2 retention-days 和旧的 v3 artifact 要提前处理

v4 迁移还有一个容易忽略的细节:老的 v3 artifact 已经无法用 v4 下载了。如果升级前仓库里还有需要保留的 artifact,建议先在旧版本 action 下或直接通过 GitHub 网页的 Actions 页面把它们下载下来存档,再升级 workflow。

另外,artifact 默认保留 90 天,这个规则在 v3 和 v4 里都存在。如果你的 workflow 里有专门清理 artifact 的定时任务,比如用 gh api 删掉超过 7 天的内容,升级后继续沿用即可。唯一要记住的是,artifact 一旦删除,不会进回收站,无法恢复。所以在加任何删除逻辑时,多留一份心眼。

在组织层面,管理员可以在仓库设置里限定最大保留天数。如果你的 workflow 里写了 retention-days: 30,而组织设置的上限是 7 天,最终会以更短的那个为准。迁移后如果发现 artifact 过期时间不对,不要先怀疑 v4,先看组织设置。

3.3 compression-level:大文件提速的隐藏开关

v4 新加的 compression-level 是我最推荐的调优参数。理解它很简单:0 表示不压缩,直接用原始文件上传;9 表示最高压缩强度;默认是 6。对于文本类文件(日志、JSON、CSV),压缩收益很大,默认值就好。但如果你上传的是安装包、镜像、音频视频、wasm 这类本身已经压缩过的文件,再花 CPU 去压也压不出多少,反而拖慢上传速度。

我自己的经验是,一旦产物里有体积较大的二进制文件,上传阶段把 compression-level 设为 0,耗时能再降一截:

- uses: actions/upload-artifact@v4 with: name: release-bundle path: out/ compression-level: 0

这样上传时省去了无用压缩的 CPU 时间。下载阶段反正是按数据块并发拉取的,不受影响。注意,compression-level 只在上传阶段起作用,不能反过来让下载时解压得更快;但上传快了,整条流水线自然就快了。

4. 实测数据与性能对比

4.1 可复现的性能测试 workflow

为了避免“感觉变快了”这种主观结论,我搭了一个简单的测试 workflow,在同一台 GitHub 托管 runner 上分别用 v3 和 v4 跑了两遍。测试内容分三个场景:1000 个小文件(每个约 50KB)、单个 1.5GB 的随机二进制、一个 300MB 的文本日志目录。

先放一个最基础的测试模板:

name: artifact-perf-test on: workflow_dispatch jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Create test files run: | mkdir -p output for i in $(seq 1 1000); do head -c 50000 /dev/urandom > output/file-$i.bin done du -sh output - uses: actions/upload-artifact@v4 with: name: perf-artifact path: output/ compression-level: 6

下载侧通常在同一个 workflow 的后续 job 里测,也可以直接用gh run download手动验证。测试时分别把 action 版本切到 @v3 和 @v4,记录工作流日志里 “Uploading artifact” 和 “Downloading artifact” 两个阶段的耗时。

4.2 结果对比:加速最狠的是下载

我在自己的项目环境里测出来的数据大致如下:

场景v3 上传耗时v4 上传耗时v3 下载耗时v4 下载耗时
1000 个小文件(约 48MB)约 26s约 9s约 31s约 3s
单个 1.5GB 随机二进制约 110s约 42s约 135s约 18s
300MB 文本日志目录约 58s约 31s约 63s约 12s

注意,不同网络环境、不同 runner 跑出来的数字会有差别,但趋势是一致的:小文件下载的提速最夸张,几乎到 90%,这正好对应官方 benchmark 里说的“download 提速最多 90%”。原因也简单,旧模型要压缩成一个 zip、下载、再解压,每个环节对小文件都不友好;新模型把这些文件按数据块并发取回,小文件数量越多,并发优势越明显。

还有一个意外收获:v4 上传 1.5GB 二进制时,我把 compression-level 调到 0 之后,上传耗时从 42s 又降到了 27s 左右。这说明如果你已经买了 v4 的账,再顺手调一下压缩级别,还能再榨出一截性能。

5. 迁移踩坑与问题排查实录

5.1 常见报错速查表

迁移过程中我踩过不少坑,也帮同事排查过不少问题,这里整理成表格,方便直接对照:

报错现象根本原因处理方法
下载时出现 v3 / v4 artifact 不兼容提示upload 和 download 版本不一致全局统一为 @v4,重新跑一遍
日志提示需要 Node 20自托管 runner 版本过旧升级 runner 到 2.308.0 以上
下载多个 artifact 后路径多了一层目录没有使用 merge-multiple需要合并时添加 merge-multiple: true
merge-multiple 时报同名文件冲突不同 artifact 存在同名文件更改文件名,或分开下载再合并
“Artifact not found” 或 pattern 匹配不到artifact 名写错或 pattern 格式错误检查 Artifacts 页面实际名称,pattern 用 glob 匹配
上传时报 “No files were found”path 路径错误或文件被忽略检查 runner 上的相对路径,确认目录存在
artifact 删除后想找回删除不可恢复提前下载备份,避免随意删除

多数问题都不是 v4 本身的 Bug,而是迁移时对行为变化不熟悉造成的。上面这张表基本覆盖了我遇到过的所有坑。

5.2 一次真实迁移:把发布流水线从 v3 推到 v4

我在一个实际项目里做过一次完整迁移,发布流水线分为 build、package、publish 三个 job。最初的 workflow 是这样的:build job 用upload-artifact@v3上传编译产物,package job 用download-artifact@v3下载后执行签名和打包,再upload-artifact@v3上传最终安装包,publish job 再用download-artifact@v3拉下来分发。

我一开始只把 build job 里的 upload 改成了 v4,立刻收到一个误导性很强的报错。download-artifact@v3 在 package job 里直接失败,提示无法读取 artifact。我第一反应还以为是 artifact 名字打错了,翻了一会儿日志才发现,v3 下载器读不了 v4 上传的 artifact。最后用全局搜索把所有@v3替换成@v4,问题立刻消失。

还有一个真实教训:当时 publish job 里用download-artifact@v4下载两个 artifact 到同一个目录,结果后续的tar解压脚本一直找不到文件。排查下来才发现,v4 把每个 artifact 解压到了以 artifact 名为名字的子目录里,后续脚本还在按“直接解压在当前目录”的旧假设处理。加了merge-multiple: true之后才恢复正常。

这类问题在文档里写得清清楚楚,但真到流水线报错时,没人会第一时间想到路径结构发生了变化。所以迁移时一定要把“下载后目录结构”当成一个显式的检查项,而不是依赖旧经验。

5.3 我的几条避坑建议

如果你现在正准备升级,我建议按这个顺序来:

第一,先选一个小项目、一条低频 workflow 试水,不要一上来就全仓替换。v4 的迁移表面上是改两个版本号,但很多时候会牵连到后续脚本的路径、runner 环境、artifact 保留策略,遇到问题需要时间排查。

第二,升级前把还需要的旧 artifact 都下载到本地留档。v3 和 v4 不兼容,升级后旧数据可能就拉不下来了,尤其在做发布流水线时,历史安装包有时候比代码还重要。

第三,固定 action 版本时要谨慎。很多教程喜欢写成@v4,这其实是跟随主版本的最新 minor,优点是持续吃到修复,缺点是有时候新 minor 的行为微调会影响你。如果你对稳定性要求高,可以固定到具体版本,比如@v4.3.0,升级时再手动改版本号。

第四,用retention-days控制存储成本。artifact 默认保留 90 天,团队内部的临时构建产物根本不需要留这么久。我在验证充分后习惯把临时产物设置成 7 天或更短,避免 GitHub Actions 存储账单偷偷涨起来。

6. 从 v4 还能继续往哪走

v4 不是终点。随着 artifact 后端的变化,GitHub 官方也在逐步统一 artifact 和 Actions Cache 的交互方式。当前最明显的变化是:很多围绕 artifact 的生态工具、第三方 action 和内部 CLI,开始把“兼容 artifact v4”写进自己的发布说明。如果你还在用之前自己写的“直接拉取 zip 归档”脚本,建议在升级 v4 之后集中测一遍,大概率需要更新。

另外,如果你的流水线里有人通过 REST API 或者第三方脚本直接下载 artifact,升级后一定要验证。v4 换了存储协议,旧的“伪造 URL 直接拉 zip”的做法很容易失效。最稳妥的姿势还是继续使用官方 action 或者 GitHub CLI 的gh run download,它们已经适配新后端。

实际用下来,v4 在速度和稳定性上的提升是实打实的,尤其是下载阶段那种“肉眼可见地快了”的体验,确实值得花半小时把所有 workflow 过一遍。迁移成本比我预想的低,主要时间都花在排查路径和 runner 版本上。只要按照上面这几步走,基本可以做到无痛升级。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 22:55:41

大模型重塑营销广告:货拉拉意图理解、创意生成与投放优化实践

1. 从“人写广告”到“模型写广告”:货拉拉营销广告的智能化转轨先交代一下背景。货拉拉的业务覆盖货运、同城配送、搬家、租买车等场景,营销广告体系天然带有“双边平台”属性:一边是司机侧,需要拉新、促活、唤醒沉默司机&#x…

作者头像 李华
网站建设 2026/10/1 22:55:13

A4与A5混用打印全攻略:从纸张原理到驱动设置与共享打印

又到了月底对账的时候,办公室里最忙的不一定是财务,往往是那台要打合同、打发票、打标签、打会议资料的打印机。我这边的情况更有代表性:工位上常年要兼顾A4文档和A5规格的送货单、产品小卡片,刚开始时几乎每次切换都要折腾半天—…

作者头像 李华
网站建设 2026/10/1 22:52:12

BurpSuite HTTPS抓包:代理配置与CA根证书导入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 22:51:22

Vim插件离线安装全攻略:从报错排查到打包部署

干运维和开发的兄弟应该都有过这种体验:本地环境里配得美滋滋的 Vim,一到需要和外界物理隔离的服务器上,插件就全变摆设了。再想按常规方式装插件,几乎每一步都在撞墙,甚至可能在装 Vim 本体的环节就被卡住。我最近就真…

作者头像 李华
网站建设 2026/10/1 22:51:14

Element UI Dialog拖动与拉伸增强实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/1 22:50:16

基于SpringBoot的农产品在线管理系统毕设全流程解析

毕业设计选“农产品在线管理系统”,本质上是在做一个带电商属性的Web业务系统。Java SpringBoot这套组合,正是目前高校毕设选题里最常见的一条技术线——评委会拿着“能不能跑通、架构规不规范、业务逻辑有没有闭环”这三把尺子来量你的工作量。这篇就把…

作者头像 李华