Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/font-urls.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# CJK 字体下载 URL, 每行一个. _test-package.yml 的 "Install Noto fonts" step
# 逐行 curl, 同时这个文件的 hash 作为字体 cache key 的依据 —— URL 变才让
# cache invalidate, 不会被 yml 其它字段改动连带掀掉.
# 行首 # 是注释, 空行被忽略.
https://github.com/notofonts/noto-cjk/releases/download/Sans2.004/03_NotoSansCJK-OTC.zip
https://github.com/notofonts/noto-cjk/releases/download/Serif2.002/04_NotoSerifCJKOTC.zip
97 changes: 84 additions & 13 deletions .github/workflows/_test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ on:
description: 'TeX Live 版本 (例 "2026"). 由 test.yml 顶层 env TL_VERSION 透传.'
required: true
type: string

env:
NOTO_SANS_URL: https://github.com/notofonts/noto-cjk/releases/download/Sans2.004/03_NotoSansCJK-OTC.zip
NOTO_SERIF_URL: https://github.com/notofonts/noto-cjk/releases/download/Serif2.002/04_NotoSerifCJKOTC.zip
tl-cache-week:
# ISO 年-周 (例 "2026-W26"), 用作 TL bypass cache key 的时间维度.
# 周内 cache hit, 跨周翻新. 由 changes job 在 ubuntu runner 上算
# 一次, 透传给所有 caller × 3 OS 保证 key 一致.
description: 'ISO 年-周字符串 (例 2026-W26). 由 test.yml changes job 计算.'
required: true
type: string

jobs:
run:
Expand All @@ -47,15 +50,24 @@ jobs:
font-dir: /usr/share/fonts/truetype
shell: bash
tl-pkgs: ""
tl-bin-platform: x86_64-linux
tlmgr-exe: tlmgr
- os: macos-latest
font-dir: /Library/Fonts
shell: bash
tl-pkgs: ""
tl-bin-platform: universal-darwin
tlmgr-exe: tlmgr
- os: windows-latest
font-dir: /c/Windows/Fonts
shell: C:\msys64\usr\bin\bash.exe -e {0}
# for `unzip` shipped with texlive
tl-pkgs: wintools.windows
tl-bin-platform: windows
# Windows 上 tlmgr 实际是 tlmgr.bat. msys2 bash 不按 PATHEXT
# 补后缀, sanity check 直调必须显式写出. 测试阶段不影响 — l3build
# 调的是 latex/xelatex/luatex 这些 .exe, 走 PATH 没问题.
tlmgr-exe: tlmgr.bat

# workflow_call 触发时, 整个 reusable workflow 在 caller 视角显示为
# 一个 check, 名字 = "<caller_job_id> / <reusable_job_id> (<matrix>)".
Expand All @@ -71,6 +83,44 @@ jobs:
steps:
- uses: actions/checkout@v7

# TL bypass cache: warmup-tl 已经把 update 后的整个 TEXDIR 保到这个
# key. caller restore 这份 cache + 把 bin/<platform> 加入 PATH, 完全
# 不跑 setup-texlive-action, 不联网, 秒过.
#
# cache miss (例 weekly 边界 + push race, 或 cache eviction): fallback
# 到 setup-texlive-action (下面 try 1/2 + verification). 保险但慢.
- name: TL bypass cache (caller restore)
id: bypass-cache
uses: actions/cache@v6
with:
path: ${{ runner.temp }}/setup-texlive-action/${{ inputs.tl-version }}
key: tl-bypass-${{ runner.os }}-${{ inputs.tl-version }}-${{ inputs.tl-cache-week }}

# cache hit fast path. sanity check 用 `continue-on-error: true` 兜底 cache
# 真损坏的极端情况 (理论极少 — warmup 验证过才 save). 失败时
# step.outcome == 'failure', 下面所有 fallback step 的 if 都同时 OR 这个
# outcome, 让 setup-texlive fallback 自动接管.
#
# Windows: tlmgr 是 tlmgr.bat, msys2 bash 不按 PATHEXT 补后缀, 所以 matrix
# 里给出显式 tlmgr-exe (windows 用 tlmgr.bat, ubuntu/macos 用 tlmgr) — 不靠
# continue-on-error 兜 Windows, 否则 Windows 每次都假阳 fallback 退化成跟没
# bypass cache 一样慢.
- name: Export PATH (cache hit fast path, skip setup-texlive)
id: export-path
if: steps.bypass-cache.outputs.cache-hit == 'true'
continue-on-error: true
run: |
TL_BIN="${{ runner.temp }}/setup-texlive-action/${{ inputs.tl-version }}/bin/${{ matrix.tl-bin-platform }}"
echo "$TL_BIN" >> "$GITHUB_PATH"
echo "Added to PATH: $TL_BIN"
# 不联网, 用 cache 内的本地 db 简单 sanity check.
"$TL_BIN/${{ matrix.tlmgr-exe }}" version

# ────────────────────────────────────────────────────────────────────
# 以下是 cache miss 的 fallback 路径. 触发条件: cache miss, 或 cache hit
# 但 export-path sanity check 失败 (cache 损坏 / Windows tlmgr 路径问题).
# ────────────────────────────────────────────────────────────────────

# caller 端 setup-texlive 也得 retry 换 mirror — 即便 cache hit, setup-texlive
# 在 'Updating packages' 阶段仍会联网拉 tlmgr db checksum 判断要不要 update.
# PR #899 实测 windows ctan.math.illinois.edu 网络抖动时 "Unable to download
Expand All @@ -83,7 +133,8 @@ jobs:
# mirror.ctan.org 全球自动重定向 (而非 pin illinois 一个单点), GH runner
# 网络好时它会自动选最快/最稳的 mirror. illinois pin 给 try 2 兜底
# (mirror.ctan.org 极端不可用时).
- name: Install TeX Live (try 1, ctan.org auto-redirect)
- name: Install TeX Live (try 1, ctan.org auto-redirect, fallback)
if: steps.bypass-cache.outputs.cache-hit != 'true' || steps.export-path.outcome == 'failure'
id: tl1
continue-on-error: true
timeout-minutes: 15
Expand All @@ -98,9 +149,12 @@ jobs:
# 70s 是 setup-texlive cache 设计的固有代价 (同 primaryKey 不覆写),
# 实测无合理方案绕开. 见 _test-package.yml head 注释.
update-all-packages: true
# 关掉 setup-texlive 内部 cache, 我们自己用 bypass-cache.
cache: false

- name: Install TeX Live (try 2, illinois mirror)
if: steps.tl1.outcome == 'failure'
- name: Install TeX Live (try 2, illinois mirror, fallback)
if: (steps.bypass-cache.outputs.cache-hit != 'true' || steps.export-path.outcome == 'failure') && steps.tl1.outcome == 'failure'
id: tl2
timeout-minutes: 15
uses: TeX-Live/setup-texlive-action@v4
with:
Expand All @@ -109,15 +163,20 @@ jobs:
packages: ${{ matrix.tl-pkgs }}
repository: https://ctan.math.illinois.edu/systems/texlive/tlnet
update-all-packages: true
cache: false

# 验证 setup-texlive 真的 update 到了最新 TLnet, 而非 tlmgr 在 mirror
# 不通时 silent fallback 用本地老 db. PR #899 实测 ubuntu 上 tlmgr 在
# "Unable to download the checksum" 时 silent 用 local, setup-texlive
# 退码 0 看不出来, caller cache 是数月前的 TL → 跟仓库 .tlg baseline 不一致.
# 这里 tlmgr update --self --list 强制访问 remote, grep 输出验证 "Unable
# to download" 不出现; 出现就 exit 1 强 fail, 让 rerun --failed 在 GH
# Actions UI 上可手动重跑.
- name: Verify TL mirror reachable (no silent fallback to local db)
# Actions UI 上可手动重跑. 仅在 cache miss 走 fallback 路径时跑.
#
# 触发条件除了 "走 fallback 路径", 还要 tl1 或 tl2 真装上了 — 否则
# tlmgr 不在 PATH, 这里报 "command not found" 噪音掩盖真正的 install fail.
- name: Verify TL mirror reachable (fallback path only)
if: (steps.bypass-cache.outputs.cache-hit != 'true' || steps.export-path.outcome == 'failure') && (steps.tl1.outcome == 'success' || steps.tl2.outcome == 'success')
run: |
out=$(tlmgr update --self --list 2>&1) || true
echo "$out"
Expand All @@ -131,8 +190,10 @@ jobs:
uses: actions/cache@v6
with:
path: ${{ github.workspace }}/.font-cache
# hashFiles 取本 yml hash (URL 改了 → key 变 → 重 download).
key: ctex-kit-fonts-${{ runner.os }}-${{ hashFiles('.github/workflows/_test-package.yml') }}-v1
# font-urls.txt 列了所有字体 URL, 它变才让 cache key 变. 用 yml hash
# 会被 caller / matrix 这类无关改动连带掀翻 cache, 害每 PR 重 download
# 5 caller × 3 OS × ~170MB.
key: ctex-kit-fonts-${{ runner.os }}-${{ hashFiles('.github/font-urls.txt') }}-v1

- name: Install Noto fonts
run: |
Expand All @@ -142,8 +203,18 @@ jobs:
mkdir -p "$FONT_CACHE"
if [ ! -f "$FONT_CACHE/.done" ]; then
cd "$FONT_CACHE"
curl -LO "${{ env.NOTO_SANS_URL }}"
curl -LO "${{ env.NOTO_SERIF_URL }}"
# 从 .github/font-urls.txt 逐行读 URL (# 注释行 / 空行忽略). 跟
# cache key 的 hashFiles 同源, 保证 "URL 改 → cache invalidate +
# 实际重 download" 完全同步.
#
# Windows checkout 把 LF 转 CRLF, 这里 `tr -d '\r'` 把行尾 CR 干
# 掉, 否则 curl 拿到 "URL\r" 报 "Failed to extract a filename".
# `|| [ -n "$url" ]` 防 trailing-newline 缺失时 read 丢最后一行.
while IFS= read -r url || [ -n "$url" ]; do
url="$(printf '%s' "$url" | tr -d '\r')"
case "$url" in ''|'#'*) continue ;; esac
curl -LO "$url"
done < "${{ github.workspace }}/.github/font-urls.txt"
for f in *OTC.zip; do unzip -ojd . "$f" "*.ttc"; done
# zip 解压完就没用了 (~200MB), 删掉减小 cache 体积
rm -f *.zip
Expand Down
Loading
Loading