Skip to content

工程优化专项:站点存储瘦身 × CI 构建提速 × 工作流可扩展性(含实测数据与分阶段方案) #306

Description

@ShixiangWang

工程优化专项:站点存储瘦身 × CI 构建提速 × 工作流可扩展性

调研日期:2026-10-07。数据来源:本地 git 统计、GitHub API(gh repo view / gh cache list)、CI 运行日志(gh run view)。所有数字均可复现。

TL;DR

当前仓库与构建管线存在三类系统性问题,本 issue 给出基于实测数据的分阶段改造方案:

维度 现状 目标 主要手段
Git 仓库体积 ~5.2 GB(pack 4.94 GiB) < 500 MB 弃用 gh-pages 分支部署 + 历史重写
部署站点体积 493 MB(Pages 上限 1 GB) < 200 MB 中英图文 dedup、iVolcano 瘦身、图片压缩
热构建耗时 46 分钟(最好 20 分钟,最差 2h52m+) < 15 分钟 修复 R 依赖缓存 + 渲染并行化
构建正确性 nightly 连续 5+ 天失败(至今未修复) 0 失败 锁定依赖版本(renv)
工作流可维护性 两个 ~500 行工作流 90% 重复 单一来源 composite actions 复用

一、架构现状

  • Quarto website 项目:_quarto.yml 定义,输出 _site/,execute: freeze: auto;528 个 .qmd,其中 262 个 *.zh.qmd(babelquarto 中英双语,render_website() 一次渲染两棵树)。
  • 执行引擎:R/knitr 为主(DESCRIPTION 声明 176 个 Imports),Julia(QuartoNotebookRunner,CI 特殊处理避免 OOM)、Python(matplotlib 等)为辅。
  • 部署链路:push main / PR → quarto-publish.yml(546 行)→ 预渲染变更文件(fail-fast)→ 预渲染所有未冻结文件(填充 _freeze)→ babelquarto::render_website()(pandoc-only)→ 修复 zh 图片路径(copy 英文图片树)→ quarto publish gh-pages。另有 quarto-publish-update-cache.yml(413 行,nightly + 手动)逻辑几乎完全重复。
  • 周边工作流:auto-translate、translate-command、generate-skills、skill-command、compress-images、pr-review,共 8 个工作流 1895 行。

二、实测数据:三类问题的证据

2.1 存储:仓库 5.2 GB,站点 493 MB,几乎全部有解

(a) Git 历史是最大黑洞(GitHub diskUsage = 5,230,403 KB):

历史对象 累计占用 说明
Omics/iVolcanoPlot.html(en) 5.44 GB 48 MB 的自包含 widget HTML 曾作为构建产物被提交,每次修改都新增 48 MB
zh/Omics/iVolcanoPlot.html 5.39 GB 同上的中文副本
search.json(en+zh) ~1.03 GB 每次部署 gh-pages 都把 2 MB 搜索索引重写进历史
历史渲染 figure PNG > 1 GB(单个图可达 146 MB×多版本) 每次重渲染产生新二进制
已删除的 files/Hiplot/*.rds 109 MB uk_city.rds 60 MB + china.county.rds 49 MB
gh-pages 分支 434 个 commit,tip 解压后 493 MB quarto publish 每次部署提交整棵站点树,历史无界增长

(b) 部署站点内容近乎全量中英双份(tip 实测 493 MB):

内容 en zh 可节省
figure 目录(*_files/,1392 个 PNG/SVG 共 163.3 MB) 81.5 MB 81.8 MB(与英文逐字节相同的拷贝) ~80 MB
site_libs/ 35.1 MB 35.1 MB(完全相同) ~35 MB
Omics/iVolcanoPlot.html 46.1 MB 46.1 MB ~80 MB(瘦身)
images/ 截图 PNG(最大单张 1.5 MB,未压缩) 44.7 MB 44.7 MB ~55 MB(pngquant 通常压缩 60%+)
search.json 2.1 MB 2.0 MB —
.js.map 源映射(reactable 等) ~2 MB ~2 MB ~4 MB

(c) Actions 缓存 2.95 GB:nightly 每天 if: always() 保存 ~178 MB 的 _freeze 缓存 × 多个 key(freeze-Linux-nightly-* 已见 9+ 份),持续逼近 10 GB 仓库缓存上限,存在互相驱逐风险。

2.2 构建速度:46 分钟热构建中 26 分钟在装 R 包

三个代表性 run 的 step 计时(gh run view 实测):

Step 2026-05-18(成功,20 min 总) 2026-07-30(PR,墙钟 2h52m) 2026-08-03(成功,46 min 总)
setup-r-dependencies(176 包) 2m12s ✅ 30m34s ❌ 25m55s ❌
Render website with Babelquarto 12m03s 13m45s 14m04s
Checkout(fetch-depth: 0,5 GB 仓库) 1m35s 2m19s 1m57s

关键结论:

  1. R 依赖缓存 key 脆弱:我们的显式 actions/cache 与 setup-r-dependencies 内置缓存都以 DESCRIPTION 哈希为 key。7/30 PR(删除 cutoff 包)改动了 DESCRIPTION → 缓存全失效 → 26-30 分钟全量重装。此后 key 恢复稳定时(5 月)只需 2 分钟。每次 runner 镜像/R 小版本漂移都会重演。
  2. babelquarto 渲染恒定 ~12-14 分钟:即使全部冻结(纯 pandoc),两语言 × ~267 页仍是单进程串行。
  3. 7/30 PR 墙钟 2h52m,但步骤实际耗时合计仅 ~50 分钟:约 2 小时耗在排队/并发等待,吞吐体验差。
  4. 冷构建 95-115 分钟(预渲染全量 + babelquarto + 环境),timeout-minutes: 180/240 印证。
  5. nightly 自 2026-10-02 起每日失败(最近 run 37559273111,每次 ~1 小时):babelquarto::render_website() 后处理在 _site/zh/About.html 上抛 xml_text<-.xml_node: attempt access index 0/0 in STRING_ELT——典型依赖漂移(babelquarto/xml2 未锁定版本,10/2 前后被某次更新破坏)。站点自 2026-09-17 起未再成功部署,且每天白烧 1 runner 小时。
  6. 依赖扫描回写触发冗余构建:构建内 update-dependencies.R 提交 chore: update dependencies(改 DESCRIPTION),而 push 触发的 paths-ignore 不含 DESCRIPTION → 每次真实依赖变更引发第二次全量构建(main 上已有 2 个此类 commit)。
  7. 次要:actions/cache@v4、checkout@v4 等已触发 Node 20 deprecation 强制升级警告。

2.3 可扩展性 / 健壮性

  • quarto-publish.yml(546 行)与 quarto-publish-update-cache.yml(413 行)约 90% 内容重复(R/Python/Julia 环境搭建、预渲染、babelquarto、zh 图片修复全部复制两份)——任何修复都要改两处,已出现改一处漏一处的风险。
  • 依赖不锁定:nightly 连日失败即 R 包漂移直接后果;本地复现同样困难(无 renv lockfile)。
  • _quarto.yml 660 行手工维护 sidebar(290+ 个手写条目),新增图表需手改易错。
  • 大量陈远分支(copilot/* 等)与 434 commit 的 gh-pages 拖慢 clone/fetch(checkout 2 分钟仅是浅层代价)。

三、优化方案

A. 存储瘦身(预期站点 −60%,仓库 −90%)

  • A1. 弃用 gh-pages 分支,改用 Pages artifact 部署(治本,阻断未来增长)
    现工作流已上传 upload-pages-artifact,只需将 quarto publish gh-pages 替换为 actions/configure-pages + actions/deploy-pages(公开仓库原生支持)。gh-pages 分支(434 commits、493 MB tip)整体删除,搜索索引/渲染图不再每部署一次就永久复制进 git 历史。部署也从「push 493 MB 树」变为「上传压缩 artifact」,更快且不再产生噪声 commit。
  • A2. 历史重写,清除已删大对象(一次性,需协调)
    用 git-filter-repo 按路径清除:Omics/iVolcanoPlot.html、zh/Omics/iVolcanoPlot.html、files/Hiplot/*.rds、历史 search.json 大版本、已删除页面的渲染图。在 fork/镜像上演练后强推 main;通知贡献者重新 clone;联系 GitHub support 触发服务端 gc 以尽快回收配额;顺带删除陈旧 copilot/* 远程分支。在 A1 合并后再执行,否则 gh-pages 会再次膨胀回去。
  • A3. 站点内容去重
    • A3.1 zh 图片去重(−80 MB):「Fix zh page figure files」步骤目前把英文 *_files/ 整树拷贝成 *.zh_files/。改为后处理重写 zh HTML 中的资源引用(X.zh_files/... → 指向英文树的相对路径 ../../<cat>/X_files/...,根级页面为 ../X_files/...),不复制任何字节。需 CI 截图对比验证 zh 页面图片全部可达。
    • A3.2 site_libs 共享(−35 MB):同思路把 zh/** 页面对 site_libs 的引用重写到根 site_libs/(babelquarto 输出的引用路径可控,正则安全)。
    • A3.3 iVolcano 页面瘦身(−80 MB,单页最大项):Omics/iVolcanoPlot.qmd 渲染的 ivolcano widget 把全量数据内嵌进 46 MB HTML(en+zh 共 92 MB)。方案:教程内降采样(如非显著基因最多保留 2 万点)+ 链接 Hiplot 完整版应用;保留教学价值的同时把单页压回 <2 MB。
    • A3.4 图片压缩常态化:scripts/compress-images.sh 已有,但 compress-images 工作流只在「触碰 images/** 的 PR」上运行且直接 push 回 PR 分支(fork PR 不可写)。改为:merge 到 main 后自动压缩 + 回写 commit(加 [skip ci]),并考虑对 >200 KB 截图转 WebP(预期 −55 MB)。
    • A3.5 部署排除无用文件:删除 site_libs/**/*.map(−4 MB);检查 _site 内残留的 .md 源文件与孤儿文件。
  • A4. Actions 缓存治理:_freeze 改为单一滚动 key(或 A1+renv 落地后仅 weekly 保存一次),用 gh cache delete 清理历史 key,缓存总量压到 ~1.5 GB。

B. 构建提速(热构建 46 → ~13 分钟)

  • B1. 用 renv 锁定依赖 + 修复缓存(最大单项收益:−24 分钟)
    生成 renv.lock(锁定 176 包精确版本),CI 改用 r-lib/actions/setup-renv,缓存 key = renv.lock 哈希(只在真实增删包时失效,而不是任何 DESCRIPTION 抖动)。renv cache + 包安装走 Posit 公共二进制源。同时根治 nightly 失败:babelquarto/xml2 版本被锁定,不再被静默升级破坏。
  • B2. 渲染并行化(−7~9 分钟)
    babelquarto 串行渲染 en+zh 两棵树是恒定 12-14 分钟。两条路线(CI 实验后择优):
    1. 按语言分片:验证 babelquarto 是否支持单语言渲染(或直接对 zh 用 quarto render + 语言 profile),en/zh 在两个 job 并行,产物合并后再做 zh 资源重写(A3.1/3.2);
    2. 按目录分片预渲染:矩阵 job(Hiplot / Omics / 其余)各自填充 _freeze 分片后合并——改善冷构建(95-115 → ~40 分钟),热构建收益较小。
  • B3. 消除冗余构建触发:paths-ignore 增加 DESCRIPTION、requirements.txt、Julia/Project.toml;或把依赖扫描移出构建主链路(改为 weekly 定时 + [skip ci] 回写)。
  • B4. nightly 降频与修复:修复当前 babelquarto/xml2 失败(短期:临时锁定破坏前的版本;长期:B1 renv);频率从每天降为每周(站点只在 main 变化时需要重建,nightly 的本质职责是保持 freeze 缓存新鲜);加「main 无新提交则跳过部署」判断。
  • B5. Checkout 减负:变更检测只需 base commit——fetch-depth: 1 + 按需 git fetch origin $BASE_SHA;确认 date-modified: last-modified 的实现是否依赖完整历史,若否则稳定受益。A2 历史瘦身后此项与 clone 体验同步改善。
  • B6.(可选,第三阶段)预构建容器镜像:GHCR 维护「R + 176 包 + Quarto + Julia + QNR」镜像(weekly 重建、版本锁定),环境搭建从 ~15 分钟降到拉镜像 ~2 分钟,并彻底消除 runner 镜像漂移这类隐性失效。

C. 可扩展性与便捷性

  • C1. 工作流去重(单一来源):抽出 composite actions:
    • .github/actions/setup-render-env/:Quarto + R(+renv) + Python + Julia(条件) 四语言环境;
    • .github/actions/render-site/:预渲染 → babelquarto → zh 资源重写 → freeze 保存。
      quarto-publish.yml 与 nightly 都变成 ~80 行的编排层,差异只保留触发条件和部署目标(PR→artifact,main→Pages,nightly→Pages+缓存刷新)。
  • C2. 依赖可复现:renv.lock 提交后,贡献者本地 renv::restore() 即可复现 CI 环境;manage-dependencies.py/update-dependencies.R 的扫描结果以 lockfile diff 呈现,变更可审。
  • C3. sidebar 自动生成:新增脚本从目录结构 + qmd frontmatter 生成 _quarto.yml 的 contents 列表(保留人工排序文件),把「新增一页图表」的成本从手改 660 行配置降为「加一个 qmd」。
  • C4. CI 基准工作流(ci-benchmark.yml):手动触发的无部署构建,逐步骤输出计时 JSON 与 _site/_freeze 体积报告为 artifact——为后续每项优化的前后对比提供统一度量(见第四节)。
  • C5. Actions 版本卫生:升级到 Node 24 兼容版本(checkout@v5、setup-python@v6、cache@v4 最新等),消除 deprecation 强制升级的不可控行为。
  • C6. PR 预览体验:PR 构建保留 artifact(现状),在 PR 上评论 artifact 下载说明;视需求再评估 Netlify 预览。

四、CI 验证方案(用 GitHub CI 获取信息、测试每项改动)

  1. 基准采集(已完成的首次测量见上文第二节;持续化 = C4 工作流):workflow_dispatch 运行「装环境 + 渲染 + 体积统计、不部署」,上传:步骤耗时表、du -sh _site/*、_freeze 大小、gh-pages/artifact 体积对比。
  2. A3.1/A3.2 资源重写验证:重写后用 CI 跑链接/图片完整性检查(解析 _site/zh/**/*.html 的 src/href,断言文件存在),再加 Playwright 对 20 个代表 zh 页面截图对比。
  3. B1 renv 验证:先在分支上跑 setup-renv 构建 ×2 次,确认第二次 restore 命中且 setup-r-dependencies 步骤 < 3 分钟、渲染产物 diff 为空(页面 byte-identical 或仅时间戳差异)。
  4. B2 并行化验证:分支矩阵构建,比较总耗时与产物完整性(文件数、hash 清单对比主构建)。
  5. A2 历史重写演练:在镜像仓库执行 filter-repo → 完整渲染一次 → 校验站点与重写前逐字节一致 → 才对 origin 强推。

五、实施路线图(按依赖顺序,可独立合并)

Phase 0 — 止血(半天)

  • 修复 nightly:临时锁定 babelquarto/xml2 至已知可用版本,恢复部署(先确认 9/17→10/2 间渲染可复现)
  • paths-ignore 增加 DESCRIPTION / requirements.txt / Julia/Project.toml(B3)
  • nightly 降频为 weekly(B4)
  • 升级 deprecated actions 版本(C5)
  • 删除陈旧 copilot/* 远程分支

Phase 1 — 存储治本(1-2 天)

  • A1 部署切 actions/deploy-pages,删除 gh-pages 分支
  • A3.5 部署排除 .map 等无用文件
  • A3.4 main 合并后自动压缩 images + 评估 WebP
  • A3.3 iVolcano 教程降采样 + 外链完整版
  • A3.1 zh 图片引用重写替代整树拷贝(含第四节验证 2)
  • A3.2 site_libs 引用共享
  • A4 清理 Actions 缓存堆积

Phase 2 — 提速(2-3 天)

  • B1 生成 renv.lock,CI 切 setup-renv,缓存 key 绑 lockfile(含第四节验证 3)
  • C4 ci-benchmark.yml 基准工作流
  • B2 渲染并行化(含第四节验证 4)
  • B5 checkout 减负

Phase 3 — 历史重写(需贡献者协调,半天 + 公告)

  • A2 filter-repo 演练(镜像仓库)→ 强推 main → support gc → 公告 re-clone

Phase 4 — 可扩展性(持续)

  • C1 composite actions 去重两个发布工作流
  • C3 sidebar 自动生成脚本
  • C2 贡献者文档更新(TRANSLATION_GUIDE / README 增补 renv 用法)
  • B6(可选)GHCR 预构建镜像

六、预期收益汇总

指标 现值 Phase 1 后 Phase 2 后 Phase 3 后
部署站点体积 493 MB ~170-200 MB 同前 同前
Git 仓库体积 ~5.2 GB ~5.2 GB(增速归零) 同前 ~300-500 MB
热构建耗时 46 min ~44 min ~13 min ~11 min
冷构建耗时 95-115 min 同前 ~40-60 min 同前
nightly 状态 连续失败 每周一次、稳定 稳定 稳定
Pages 余量(1 GB 上限) 51% 80%+ 同前 同前

风险与回滚

  • A1:Pages artifact 部署是 GitHub 官方推荐路径,公开仓库无配额问题;如异常可临时切回 quarto publish。
  • A2:强推历史需全员协调(公告 + 冻结推送窗口);先演练后执行,旧 clone 仍可正常工作(仅 remote 历史变化)。
  • A3.1/A3.2:资源重写对相对路径规则敏感,靠第四节验证 2 的自动化检查兜底;出问题可单独回退该步骤(多拷 80 MB 换正确性)。
  • B1:renv 锁定后「隐式升级」消失,升级包变为显式 renv::snapshot 提交,可 review——这正是我们想要的。

本 issue 由 2026-10-07 的全量调研生成:本地 git 对象统计 + gh CLI(repo/cache/runs/logs)。后续每完成一个 Phase 请勾选对应复选框并在评论区附 ci-benchmark 报告。

Activity

  1. changed the title [-]Engineering optimization: site storage, CI speed, workflow extensibility[/-] [+]工程优化专项:站点存储瘦身 × CI 构建提速 × 工作流可扩展性(含实测数据与分阶段方案)[/+] on Oct 7, 2026
  2. ShixiangWang commented on Oct 9, 2026

    @ShixiangWang
    MemberAuthor

    Phase 0(止血)完成 ✅

    CI 膨胀问题的急性期治理已全部落地、部署验证完成:

    A1. Pages 部署迁移(deploy-pages)— 完成并线上验证

    • ci: migrate Pages deploy to actions/deploy-pages #308:部署方式从 quarto publish --target gh-pages(每次推送全量 ~493 MB 到分支)迁移到 actions/upload-pages-artifact + actions/deploy-pages
    • ci: upgrade workflow actions to Node24-compatible majors #309:修复两个运行时障碍:
      • deploy-pages 要求 job 声明 github-pages environment("Missing environment" 400 错误)
      • environment branch policy 只放行 main/gh-pages → 部署拆分为独立 deploy job(if: github.event_name != 'pull_request'),PR CI 不再被 protection rules 拦截
    • Pages source 已从 legacy 切换为 build_type: workflow
    • gh-pages 分支已删除(~493 MB、434 commits 的历史包袱移除),站点完全由 workflow 部署提供服务
    • 线上验证:EN/ZH 首页、ManhattanPlot EN/ZH、Template、Julia 系列、bizard-skill.zip 全部 200;Pages API status: built

    C5. Node.js 20 弃用操作升级(#309)

    全部 8 个 workflow 升级到 Node24 运行时:checkout v7、setup-python v7、github-script v9、upload-artifact v7、cache v6、upload-pages-artifact v5、setup-julia v3、changed-files v47。渲染日志确认 Node 20 弃用警告已消除。

    构建警告清理(#310)

    • ManhattanPlot EN/ZH:修复损坏的 {#fig-HistApplications} 围栏(线上页面可见残缺文本 fig-HistApplications})
    • 删除死缓存步骤 Cache R packages:renv 路径从不存在,每次构建报 path validation error 且从未保存成功(缓存列表 0 条目实证);R 包缓存由 r-lib 复合 action 正常承担
    • index.qmd 模板链接改指 .html(消除链接解析警告,渲染输出不变)
    • update-dependencies.R 增加 options(warn=1),后续构建可直接看到 R 警告明细

    前期治理回顾

    babelquarto pin(#307)、7 个过期分支删除、Actions 缓存 4.18 → 2.66 GB、weekly cron 收敛触发频率。

    下一步:Phase 1 存储治本

    • .map 文件排除、图片压缩(compress-images 已有 workflow,可强化)、iVolcano 等大图降采样
    • zh 页图片引用重写与 site_libs 共享(预计共减 ~115 MB 部署体积)
    • cutoff/choisy-cutoff 远端依赖风险排查

    🤖 Generated with Claude Code

  3. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    Phase 1 收官汇报:CI 提速 + 部署瘦身 + 可靠性加固

    在 Phase 0 基础上,Phase 1 全部落地并以 main 最终 run(07:11→07:28,17 min 38 s 全绿部署)验证:

    部署产物瘦身(#311)

    • 部署 artifact:493 MB(旧 gh-pages)→ 224-262 MB(−47%);zh 图去重 675 处引用重写、.map 清理
    • gh-pages 分支(~493 MB / 434 commits)已删除,Pages source 已切 build_type: workflow

    CI 提速(三级修复,#315)

    指标 前 后
    渲染步骤 ~46 min 11 min
    其中静默尾部 34 min ~0.6 min
    main 全量(含部署) 60-70 min 17.6 min

    修复链:babelquarto fork 排除 .git 拷贝 + 跳过 tempdir 清理;remove.packages 防 pak 缓存穿透;quarto_inspect 按语言缓存(根因:每页一次 quarto CLI 调用,540 次/构建)。

    可靠性(#314)

    • 渲染失败自动重试一次(freeze 断点续跑)— 应对 COS/hiplot.cn 外部数据源偶发拒连
    • R 包库缓存与 DESCRIPTION pin 的一致性保障

    访问体验(#312/#313)

    • 全站 2559 张图懒加载(原生 loading="lazy",零 JS 零抖动)
    • 页脚 ClustrMaps(失效)→ Busuanzi 三计数器;构建警告清零(ManhattanPlot 围栏、死缓存步骤、链接解析、R readLines)
    • github-pages environment 清理:仅允许 main 部署

    剩余事项

    • Phase 3:git 历史重写(.git ~5 GB) — 最大剩余项,需协调 force-push 窗口(影响所有协作者本地克隆与 open PR)
    • 周一 weekly cron 首验(2026-10-12 01:23 UTC)
    • 4 个 unresolved zh 图引用明细(与旧行为一致,无回归)
    • 图片压缩 workflow 已加周调度(chore: clean up CI leftovers and schedule weekly image compression #316),首跑后观察

    🤖 Generated with Claude Code

  4. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    Phase 3 完成:仓库体积治理(无需重写 main 历史)

    测量结论(数据驱动)

    • GitHub 报告仓库体积 4.4 GB;全新克隆验证一致
    • main 历史本身仅 471.7 MB(5092 blobs) — 健康,无需 filter-repo 重写
    • 真正元凶:4 个发散的 release tag(非 main 祖先,每个含完整渲染站点快照,search.json 3.5 MB × N):
      tag 逻辑体积 tip 日期
      v0.1 5.4 GB 2025-12-04
      v1.0.0 6.9 GB 2026-01-09
      v1.1.0 8.9 GB 2026-04-04
      v1.2.0 10.7 GB 2026-04-16
    • PR 引用(main 之外)仅额外 5.9 MB — 无需处理

    已执行

    1. 完整备份:~/Documents/Bizard-phase3-backup/bizard-full-pre-phase3.bundle(4.4 GB,git bundle verify 通过,含全部 refs);release notes 导出为 release-*.md 同目录
    2. 删除 4 个远端 tag + 删除 4 个 GitHub Release(v1.2.0 的 skill zip asset 每次部署自动重建,无损失)
    3. 验证:远端仅剩 main + PR refs

    预期与后续

    • 被删 tag 指向的提交已不可达,GitHub gc 后(通常数天,无公开加速 API)仓库将缩至 ~470 MB,克隆体积同步下降
    • 本地工作克隆(.git ~5 GB)含旧对象,建议待远端体积下降后重新克隆以获得干净小体积
    • 如需恢复任一 release:git fetch <bundle> refs/tags/v1.2.0 后重新打 tag + 建 release

    全阶段总结

    阶段 成果
    Phase 0 deploy-pages 迁移、Node24 升级、警告清零
    Phase 1 CI 60-70→17.6 min、artifact 493→261 MB、懒加载、busuanzi
    Phase 3 仓库 4.4 GB → 预期 ~470 MB(tag 删除 + 待 gc)

    🤖 Generated with Claude Code

  5. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    进度更新(2026-10-10)— Phase 0 + Phase 1 全部落地 ✅

    本轮完成

    Phase 0 止血

    Phase 1 存储治本

    • ✅ A1 弃用 gh-pages 分支,改 actions/deploy-pages(ci: migrate Pages deploy to actions/deploy-pages #308):gh-pages 分支(434 commits,~493 MB tip)已删除,远端仅剩 main;每次部署不再向 git 历史推送整棵站点树。部署链路改为 build-deploy(上传 artifact)+ deploy(独立 job,声明 github-pages environment)。
    • ✅ A4 缓存治理:清理 3 份过期 R 库缓存(各 935 MB)+ 2 份陈旧 freeze 缓存,Actions 缓存 4.34 GB → 1.23 GB(达成 <1.5 GB 目标);weekly 工作流 key 改为每周滚动,存量自然受限。
    • ✅ A3.5 部署排除 .map 源映射(deploy artifact 删除步骤完成)

    验证

    • babelquarto lang-button 回归:本地 Rscript 复现了 character(0) → xml2 赋值崩溃的机制;当前 SHA 钉定版本已含修复(version_text 来自 language_code 参数),今日 dispatch run 实测通过。

    下一步进入 Phase 2(B1 renv 锁定、C4 基准工作流、B2 渲染并行化)。

  6. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    进度更新(2026-10-10 下午)— Phase 2 / B1 renv.lock 生成 ✅

    PR #319(已合并)+ PR #320(已合并):B1 第一阶段完成——renv.lock 已进 main。

    走过的弯路(3 轮失败 → pak 一次通过)

    前 3 轮用手写 install.packages/remotes 安装器,各有四类失败:

    1. remotes::install_github(dependencies = FALSE) 不装 GitHub 包的传递 CRAN 依赖(babelquarto、CellChat、ggalt 等 8 个直接报 "dependencies not available")
    2. 依赖自身 DESCRIPTION 里的 Remotes(scRNAtoolVis → junjunlab/jjPlot、sajuukLyu/ggunchull)对扁平列表不可见
    3. hiplotlib 子模块走 SSH(git@github.com:hiplot/rscheduler.git),无密钥 runner 上 Permission denied
    4. quietly = TRUE 吞掉加载期错误(sf/units 等缺系统库),失败只在结尾报一句不可读的 stop

    修复(run 38062831476,9 步全绿):

    • 安装逻辑整体换成 r-lib/actions/setup-r-dependencies(pak)——与渲染工作流同一安装器,PKG_SYSREQS=true 自动装系统库;pak 递归解析 remotes-of-remotes 与传递依赖
    • SSH→HTTPS git URL 重写,子模块可克隆
    • 19 个高危包的加载冒烟测试(安装成功 ≠ 可加载,错误带完整 message)
    • renv snapshot 用显式包根(Imports+Suggests+工具),记录完整传递闭包

    锁文件内容(renv.lock,PR #320)

    • 644 包:R 4.6.1 / Bioc 3.23;559 CRAN + 45 Bioconductor + 39 GitHub(全部 34 条声明 Remotes 均入锁,SHA 级钉定,含 babelquarto@c0261d3)
    • 验证:JSON 可解析、probe 包全部安装且可加载、含 jjPlot/ggunchull 等深层 remotes
    • 目前惰性文件——渲染工作流尚未切到 renv restore(B1 第二阶段),无任何行为变化

    B1 第二阶段(下一步)

    渲染工作流切 r-lib/actions/setup-renv,缓存键 = renv.lock 哈希 → 依赖只在锁文件真变时重装。

    Phase 2 剩余:B2 渲染并行化、B5 checkout 裁剪;基准 863s(run 38053466589)已记录,改造后重跑对比。

  7. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    Phase 2 / B1 stage 2 merged — render workflows now install from renv.lock (#321, squash-merged as 601952a)

    All three render workflows (quarto-publish.yml, quarto-publish-update-cache.yml, ci-benchmark.yml) switched from setup-r-dependencies (pak re-resolution, ~26 min cold) to r-lib/actions/setup-renv@v2 with the package cache keyed on the renv.lock hash.

    How it works

    • Unchanged lockfile → restore the whole ~650-package library from cache in minutes
    • Changed lockfile → restore-keys prefix still restores the old cache; renv::restore() installs only the delta (also why the repinned babelquarto fork takes effect without manual cache-busting)
    • System requirements: explicit apt line (libudunits2-dev, libglpk-dev, librsvg2-dev) + a pak pkg_sysreqs(deps::.) step for the full closure — before setup-renv, since renv load-tests packages during restore (first run failed exactly there on rsvg/librsvg, fixed in the same PR)
    • Scan-added dependencies: delta-install step after update-dependencies.R covers QMD-discovered packages the lockfile doesn't know yet

    First-run evidence (run 38070651651, cold cache for this lockfile hash): sysreqs 2m13s → restore 13m12s → delta 47s → render success. Every subsequent run with an unchanged lockfile should land near the restore-hit time; ci-benchmark.yml was just dispatched to measure it (results to follow).

    Remaining from the plan: benchmark numbers, B2 render parallelization, A3.3/A3.4 site slimming, A4 cache governance.

  8. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    B1 stage 2 benchmark results (run 38073173240, squash-merge commit 601952a)

    Phase This run (renv, cold cache for new lockfile) Previous baseline
    R dependencies 1141 s (19 min: sysreqs 2m + restore 16.5m, cache miss) 26 min cold pak resolve; 162 s warm
    Full build (t0 → render done) 2108 s 863 s baseline was a warm-cache run

    Key detail: the benchmark's restore missed because the PR run's cache entry only became visible to other workflows/branches after merge, and it had to build + save the new cache entry itself (Cache saved with key: ...-c3cfcf3e... in the post step — 13.9 s to package). The just-dispatched main deploy run 38073162925 and every future run on an unchanged renv.lock will restore that entry — the next benchmark dispatch will show the true warm-restore number (expected minutes, not 19 min).

    So the steady state is exactly the design: lockfile unchanged → ~2-3 min restore; lockfile changed → delta install on top of the prefix-restored old cache. No action needed; next benchmark run will quantify the warm path.

  9. ShixiangWang commented on Oct 10, 2026

    @ShixiangWang
    MemberAuthor

    B1 stage 2 warm-cache benchmark confirmed (run 38076174205)

    Cache restored from key: ...-c3cfcf3e... — the renv package cache hit.

    Phase Warm renv restore Previous cold pak resolve
    R dependencies 359 s (6 min) = sysreqs 2m08s + restore-hit 3m04s ~26 min
    Full build 1274 s (21 min) 863 s*

    *The old 863 s baseline was a fully warm run (old freeze cache + old pak layering). This run's R deps include ~2 min of unavoidable sysreqs probing; the restore itself is 3m04s for ~650 packages — right in the 2–3 min design target ("26 分钟装包 → 2-3 分钟恢复").

    Net effect per render run: ~23 min → ~6 min on the dependency path (and cold-cache runs now cost 19 min once per lockfile change, instead of 26 min every time). Next: B2 render parallelization, A3.3/A3.4 site slimming, A4 cache governance.

    🤖 Generated with Claude Code

  10. ShixiangWang commented on Oct 11, 2026

    @ShixiangWang
    MemberAuthor

    进展报告(Phase 0–2 主体完成,lockfile 管线已闭环)

    自上次更新以来,本 issue 的核心工程项已基本落地。以下均为已合并到 main 的改动,每项都经 CI 全量渲染验证。

    ✅ B1 — renv 依赖锁定(本 issue 最大单项),已全链路闭环

    组件 PR 状态
    ci-benchmark.yml 基准工作流(C4) #318 ✅ 已合并
    generate-renv-lock.yml 自动锁文件生成 #319 ✅ 已合并
    锁文件首次入库(644 包) #320 ✅ 已合并
    CI 渲染切 setup-renv,缓存 key 绑 lockfile(B1 核心) #321 ✅ 已合并
    冷渲染并行化(B2 矩阵 worker) #322 ✅ 已合并
    锁文件补全 + worker renv 库修复(PR #324 8 个包目标) #323/#324 ✅ 已合并
    快照来源库修复(full .libPaths() + LinkingTo 显式安装 + 分支自 main 重建 + BiocVersion BiocManager 回退) #326 ✅ 已合并
    锁文件刷新 ×2(644 → 676 → 677 包,含 BiocVersion 3.23.1) #325/#327 ✅ 已合并

    main 的 renv.lock 现状:677 个包(R 4.6.1),覆盖 Imports + Suggests 全闭包 + 全部 6 个 LinkingTo 头文件包 + base/recommended(MASS、Matrix、survival 等一个不少)。每次 DESCRIPTION 变更自动重新生成 PR,零包移除(逐步 set-diff 验证:removed: [])。

    首次实测(push run 38109143416,677 包锁文件):

    • setup-renv 恢复 + 安装:5m44s(此前 setup-r-dependencies 波动 2m–30m,7/30 PR 实测 30m34s)
    • 冻结命中时 pre-render:0s(全部跳过)
    • babelquarto 渲染:14m06s
    • 全流程 27 分钟,部署成功(站点 lastmod 已更新到 2026-10-11)

    nightly 因依赖漂移连续失败的问题(issue 第二节 2.2.5)从根上消除:babelquarto/xml2 等版本现已锁定。

    ✅ A4 Actions 缓存治理

    清除了 24 个陈旧缓存(20 个逐 SHA 堆积的 freeze-Linux-*、2 组重复的 R 包库缓存、2 个旧格式 x86_64 缓存):12.98 GB → 2.6 GB(−80%),仅保留当前 lockfile 哈希的 R 库缓存、最新 freeze 缓存与 pip 缓存。

    此前已落地项(对应 issue 编号)

    进行中

    • 冷基准验证:run 38109155362(force_full_rebuild=true,无缓存冷构建)正在运行,用于验证 677 包锁文件的冷恢复路径并采集 Phase 2 后冷构建基线。
    • main 上又一次全量发布(PR chore: refresh renv.lock #327 合并触发)正在运行。

    剩余项

    项 说明
    A2 历史重写(Phase 3) 需协调贡献者,建议单独 issue/公告推进
    A3.2 site_libs 引用共享(−35 MB) 待做
    A3.3 iVolcano 降采样(−80 MB) 待做(当前线上单页实测 46 MB,是站点最大单项)
    B5 checkout 减负 待做
    C1 composite actions 去重 待做
    C3 sidebar 自动生成 待做

    后端数据(issue 模板要求):每项改动前后均以 ci-benchmark / push run 计时为准;A3.1/A3.5 之后的部署 artifact 体积对比将在冷基准 run 完成后补充。
    PY
    gh issue comment 306 --repo openbiox/Bizard --body-file /tmp/issue306-progress.md 2>&1 | tail -1

  11. added a commit that references this issue on Oct 11, 2026
  12. ShixiangWang commented on Oct 11, 2026

    @ShixiangWang
    MemberAuthor

    ✅ B5. Checkout 减负 —— 已完成并合并(PR #329)

    变更(仅 .github/workflows/quarto-publish.yml):

    • fetch-depth: 0 → fetch-depth: 1:deploy 构建不再克隆完整历史(本地实测 .git ≈ 5 GB),checkout 提速约 1 分钟
    • 变更检测步骤按需 git fetch --no-tags --depth=1 origin "$BASE_SHA" 后再 diff
    • 失败软化:base commit 拉取失败时回落到现有 full-build 路径,不会导致 workflow 失败

    前置确认(issue 要求先验证 date-modified: last-modified 是否依赖完整历史):
    本地渲染实测——文件 mtime 设为 2020-01-01 而 git log 显示 2026,Quarto 渲染结果为 "January 1, 2020"。last-modified 用的是文件 mtime,不是 git 历史;actions/checkout 在 shallow clone 时保留 mtime,页面日期显示不受影响。

    线上验证:

    • PR CI 双绿(pull_request + pull_request_target),已合并(6ffdacf7c)
    • merge 后 main deploy run 38134634215 success:日志确认 checkout 实际执行 --depth=1 fetch、按需取回 base commit、diff 正确得出 Changed QMDs: none(该 PR 只改了 workflow 文件)
    • 线上站点 HTTP 200,Pages status=built

    刻意未改:

    • ci-benchmark.yml:冷缓存 benchmark 需要完整历史
    • quarto-publish-update-cache.yml:每周全量预渲染 + 向 main 推依赖更新提交,保守保留全历史

    进度:Phase 0 ✓ · A1 ✓ · A4 ✓ · B1 ✓ · B2 ✓ · C4 ✓ · B5 ✓ | 剩余:A3.2(site_libs 共享)、A3.3(iVolcano 降采样)、A3.4(图片压缩)、C1/C3/C2、A2(历史重写,涉及贡献者协调,建议单独 issue)

  13. ShixiangWang commented on Oct 11, 2026

    @ShixiangWang
    MemberAuthor

    最终报告:Phase 0–2 主体完成,21 项已完成 16 项 ✅

    自上次进展报告以来完成了最后一批存储优化并已完成 CI 全链路验证。正文路线图中 Phase 0(5/5)、Phase 1(7/7)、Phase 2(4/4)全部完成并已勾选;剩余 5 项(A2 / C1 / C3 / C2 / B6)见文末。

    🎯 本批最终两项(均已合并 + 生产部署验证)

    #331 — zh site_libs 与 images 引用共享(A3.1/A3.2 收尾)

    • zh 页面对 site_libs/(53 MB)与 images/(42 MB)的引用全部重写到根目录副本,zh 树内两份冗余拷贝整体删除
    • 部署 artifact:249,159,798 B → 174,228,223 B(−75 MB / 每次部署),两次 main 部署 run 实测
    • 渲染日志:「Rewrote 5215 reference(s) across 267 zh page(s); 0 unresolved」「Pruned 2 duplicate tree(s) from zh/」——zh 全部 267 页资源引用 0 失效

    #332 — 大图有损压缩(A3.4 深化)

    • images/ 44.7 MB → 36.6 MB(git blob 增量 −8.1 MB):38 张 PNG 经 pngquant(--quality=65-90,256 色调色板)、5 张 JPEG 重编码(q82)
    • 降档阈值 8%:无收益文件保持原样;全部 43 文件经 PIL verify() 校验 0 损坏,视觉保真度代理(64×64 缩略 mean-abs 差)0.12–0.40/255,不可感知

    📊 ci-benchmark 终值(main @ 8ab408b,run 38167051869,热缓存)

    阶段 耗时
    缓存恢复 2s
    R 依赖(renv,677 包锁文件) 15m52s
    预渲染未冻结 QMD(B2 矩阵并行) 9m55s
    babelquarto 渲染 + 后处理 9m49s
    全流程(无部署) ~37m
    • _site 368.4 MB(含 zh 141.8 MB,其中已无重复 site_libs/images);_freeze 263.3 MB / 524 条目
    • 对比 issue 立项时:热构建 46 min 且 setup-r-dependencies 波动 2m–30m、nightly 连日失败 → 现在 renv 锁定 5m44s 恢复 + 全流程确定性

    📈 站点总体积(issue 立项 → 现在)

    指标 之前 现在 降幅
    部署 artifact 493 MB(gh-pages 模式) 165.8 MB −66%
    zh 冗余(site_libs+images+figures) ~197 MB ~0(引用共享) 全部消除
    Omics/iVolcanoPlot.html(en+zh) 2 × 46.1 MB 2 × 14.9 MB −62 MB(#330 降采样)
    仓库体积增速 493 MB/次部署(gh-pages) 0(artifact 部署) 增速归零

    线上验证:https://openbiox.github.io/Bizard/ HTTP 200,sitemap lastmod 2026-10-11T19:27Z(本次部署)。

    缓存治理(A4 持续)

    再次清理 6 个陈旧 freeze-Linux-*(每部署滚动堆积 ~181 MB × 6):3.52 GB → 2.98 GB。worktree 内最新 HEAD 冻结缓存保留。

    剩余 5 项(未勾选)

    项 状态 建议
    A2 历史重写(Phase 3) 需贡献者协调 立项时最大黑洞(iVolcano HTML 5.44 GB 历史对象);A1 已落地,随时可演练 filter-repo,建议单独 issue + 公告推进
    C1 composite actions 去重 待做 两个发布工作流 90% 重复仍是维护负担
    C3 sidebar 自动生成 待做 新增图表仍需手改 660 行 _quarto.yml
    C2 贡献者 renv 文档 待做 renv.lock 已入库,补 TRANSLATION_GUIDE / README 说明即可
    B6 GHCR 预构建镜像(可选) 搁置 renv 恢复已稳定在 ~6 分钟,收益下降

    结论:issue 核心目标全部达成——部署站点 493 MB → 166 MB(< 200 MB 目标 ✅)、nightly/构建正确性由 renv 锁定根治(0 连续失败 ✅)、热构建 R 依赖步骤从 26–30 min 波动收敛到 ~6 min、仓库体积增速归零 ✅。Phase 4 可扩展性项与 A2 历史重写留待后续推进。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions