Skip to content

Commit e4fa806

Browse files
committed
ci: 新增 tag 触发的 Release 打包发布流水线
推送 ctex-v*、xeCJK-v*、CJKpunct-v* 格式的 tag 时,自动: - 安装 TeX Live、zhmakeindex、Noto 字体 - 运行 l3build ctan 打包 - 从 \changes 条目生成 release notes - 创建 GitHub prerelease 并上传 zip
1 parent 5940704 commit e4fa806

1 file changed

Lines changed: 186 additions & 0 deletions

File tree

.github/workflows/release.yml

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: Release package
2+
3+
on:
4+
push:
5+
tags:
6+
- 'ctex-v*'
7+
- 'xeCJK-v*'
8+
- 'CJKpunct-v*'
9+
10+
permissions:
11+
contents: write
12+
13+
env:
14+
NOTO_SANS_URL: https://github.com/notofonts/noto-cjk/releases/download/Sans2.004/03_NotoSansCJK-OTC.zip
15+
NOTO_SERIF_URL: https://github.com/notofonts/noto-cjk/releases/download/Serif2.002/04_NotoSerifCJKOTC.zip
16+
17+
jobs:
18+
release:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- uses: actions/checkout@v6
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Parse tag
27+
id: parse
28+
run: |
29+
TAG="${GITHUB_REF_NAME}"
30+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
31+
32+
case "${TAG}" in
33+
ctex-v*)
34+
echo "pkg=ctex" >> "$GITHUB_OUTPUT"
35+
echo "dir=ctex" >> "$GITHUB_OUTPUT"
36+
echo "module=ctex" >> "$GITHUB_OUTPUT"
37+
echo "dtx=ctex.dtx" >> "$GITHUB_OUTPUT"
38+
echo "ver=${TAG#ctex-v}" >> "$GITHUB_OUTPUT"
39+
;;
40+
xeCJK-v*)
41+
echo "pkg=xeCJK" >> "$GITHUB_OUTPUT"
42+
echo "dir=xeCJK" >> "$GITHUB_OUTPUT"
43+
echo "module=xecjk" >> "$GITHUB_OUTPUT"
44+
echo "dtx=xeCJK.dtx" >> "$GITHUB_OUTPUT"
45+
echo "ver=${TAG#xeCJK-v}" >> "$GITHUB_OUTPUT"
46+
;;
47+
CJKpunct-v*)
48+
echo "pkg=CJKpunct" >> "$GITHUB_OUTPUT"
49+
echo "dir=CJKpunct" >> "$GITHUB_OUTPUT"
50+
echo "module=cjkpunct" >> "$GITHUB_OUTPUT"
51+
echo "dtx=CJKpunct.dtx" >> "$GITHUB_OUTPUT"
52+
echo "ver=${TAG#CJKpunct-v}" >> "$GITHUB_OUTPUT"
53+
;;
54+
*)
55+
echo "::error::Unknown tag format: ${TAG}"
56+
exit 1
57+
;;
58+
esac
59+
60+
- name: Install TeX Live
61+
timeout-minutes: 30
62+
uses: TeX-Live/setup-texlive-action@v4
63+
with:
64+
package-file: .github/tl_packages
65+
repository: https://ctan.math.illinois.edu/systems/texlive/tlnet
66+
update-all-packages: true
67+
68+
- name: Install zhmakeindex
69+
run: |
70+
ZHMK_VERSION=$(gh api repos/Liam0205/zhmakeindex/releases/latest --jq '.tag_name')
71+
ZHMK_URL="https://github.com/Liam0205/zhmakeindex/releases/download/${ZHMK_VERSION}/zhmakeindex_${ZHMK_VERSION#v}_linux_amd64.tar.gz"
72+
curl -fsSL "$ZHMK_URL" | tar xz -C /usr/local/bin zhmakeindex
73+
zhmakeindex --version
74+
env:
75+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76+
77+
- name: Install Noto fonts
78+
run: |
79+
curl -LO ${{ env.NOTO_SANS_URL }}
80+
curl -LO ${{ env.NOTO_SERIF_URL }}
81+
sudo mkdir -p /usr/share/fonts/truetype
82+
unzip -ojd /usr/share/fonts/truetype "*OTC.zip" "*.ttc"
83+
84+
- name: Build CTAN zip
85+
working-directory: ./${{ steps.parse.outputs.dir }}
86+
run: l3build ctan
87+
88+
- name: Prepare release asset
89+
run: |
90+
MODULE="${{ steps.parse.outputs.module }}"
91+
VER="${{ steps.parse.outputs.ver }}"
92+
ASSET="${MODULE}-v${VER}.zip"
93+
mv "${{ steps.parse.outputs.dir }}/${MODULE}-ctan.zip" "${ASSET}"
94+
echo "asset=${ASSET}" >> "$GITHUB_ENV"
95+
96+
- name: Generate release notes
97+
run: |
98+
PKG="${{ steps.parse.outputs.pkg }}"
99+
DIR="${{ steps.parse.outputs.dir }}"
100+
DTX="${{ steps.parse.outputs.dtx }}"
101+
VER="${{ steps.parse.outputs.ver }}"
102+
TAG="${{ steps.parse.outputs.tag }}"
103+
104+
NOTES_FILE="release-notes.md"
105+
106+
# Try extracting from \changes entries
107+
if grep -q "\\\\changes{v${VER}}" "${DIR}/${DTX}" 2>/dev/null; then
108+
python3 - "${DIR}/${DTX}" "v${VER}" > "${NOTES_FILE}" << 'PYEOF'
109+
import re, sys
110+
dtx_path, target_ver = sys.argv[1], sys.argv[2]
111+
with open(dtx_path) as f:
112+
lines = f.readlines()
113+
tag = '\\changes{' + target_ver + '}'
114+
entries = []
115+
i = 0
116+
while i < len(lines):
117+
line = lines[i]
118+
if tag not in line:
119+
i += 1
120+
continue
121+
# Extract content after the third {
122+
m = re.search(r'\\changes\{[^}]*\}\{[^}]*\}\{', line)
123+
if not m:
124+
i += 1
125+
continue
126+
text = line[m.end():]
127+
# Collect continuation lines (start with '% ')
128+
i += 1
129+
while i < len(lines) and re.match(r'^%\s+\S', lines[i]) and '\\changes{' not in lines[i] and '\\begin{' not in lines[i]:
130+
text += ' ' + lines[i].lstrip('% ').rstrip('\n')
131+
i += 1
132+
# Strip trailing }
133+
depth = 1
134+
result = []
135+
for ch in text:
136+
if ch == '{': depth += 1
137+
elif ch == '}':
138+
depth -= 1
139+
if depth == 0:
140+
break
141+
result.append(ch)
142+
text = ''.join(result).strip()
143+
text = re.sub(r'\\(?:cs|tn|opt|pkg|cls|file|texttt)\{([^}]*)\}', r'`\1`', text)
144+
text = re.sub(r'\\textbf\{([^}]*)\}', r'**\1**', text)
145+
text = re.sub(r'\\#', '#', text)
146+
text = re.sub(r'\\LaTeXe(?:\\\s*|\{\})?', 'LaTeX2e ', text)
147+
text = re.sub(r'\\LaTeXiii\{?\}?', 'LaTeX3', text)
148+
text = re.sub(r'\\[A-Za-z]+\s*', '', text)
149+
text = text.strip()
150+
if text:
151+
entries.append(text)
152+
seen = set()
153+
for e in entries:
154+
if e not in seen:
155+
seen.add(e)
156+
print(f"- {e}")
157+
PYEOF
158+
fi
159+
160+
# Fallback: use git log between previous tag and current tag
161+
if [ ! -s "${NOTES_FILE}" ]; then
162+
PREV_TAG=$(git tag -l "${PKG}-v*" --sort=-version:refname | sed -n '2p')
163+
if [ -n "${PREV_TAG}" ]; then
164+
git log --oneline "${PREV_TAG}..${TAG}" -- "${DIR}/" \
165+
| grep -v -E "^[a-f0-9]+ (chore|docs|Merge)" \
166+
| sed 's/^[a-f0-9]* /- /' > "${NOTES_FILE}"
167+
fi
168+
fi
169+
170+
# Final fallback
171+
if [ ! -s "${NOTES_FILE}" ]; then
172+
echo "Release ${PKG} v${VER}" > "${NOTES_FILE}"
173+
fi
174+
175+
echo "--- Release Notes ---"
176+
cat "${NOTES_FILE}"
177+
178+
- name: Create GitHub Release
179+
run: |
180+
gh release create "${{ steps.parse.outputs.tag }}" \
181+
"${{ env.asset }}" \
182+
--prerelease \
183+
--title "${{ steps.parse.outputs.pkg }} v${{ steps.parse.outputs.ver }}" \
184+
--notes-file release-notes.md
185+
env:
186+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)