From 33d54453d7ebb9c46d9cff65ee2fd7acd42dd1d3 Mon Sep 17 00:00:00 2001 From: zqlit Date: Wed, 30 Sep 2026 22:50:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(ci):=20=E7=94=A8=20Python=20=E9=87=8D?= =?UTF-8?q?=E5=86=99=20pre-build=20=E8=84=9A=E6=9C=AC=EF=BC=8C=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=20PowerShell=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gitea 自建 runner 镜像不含 PowerShell,导致 Run Pre-Build Scripts 以 exitcode 127 失败。改用 Python 3(GitHub/Gitea runner 均预装), 跨平台通用,迁回 GitHub 无需改回。 --- .github/workflows/deploy.yml | 4 +- scripts/add_draft_to_hidden.py | 110 +++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 scripts/add_draft_to_hidden.py diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1aae35df..662c7b3f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -158,8 +158,8 @@ jobs: ${{ runner.os }}-hugo- - name: Run Pre-Build Scripts - shell: pwsh - run: ./scripts/add_draft_to_hidden.ps1 + shell: bash + run: python3 scripts/add_draft_to_hidden.py - name: Optimize Images continue-on-error: true diff --git a/scripts/add_draft_to_hidden.py b/scripts/add_draft_to_hidden.py new file mode 100644 index 00000000..4c9965cd --- /dev/null +++ b/scripts/add_draft_to_hidden.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +将所有包含 'status: hidden' 的文章标记为草稿 (draft: true),并清理冲突的设置。 + +原 PowerShell 版本:scripts/add_draft_to_hidden.ps1 +改写原因:Gitea 自建 runner 镜像不含 pwsh,改用 Python 3(GitHub/Gitea 均自带)。 + +对每篇 content/posts 下的 .md: + 1. 若 frontmatter 含 status: hidden + a. draft: false -> draft: true + b. 注释掉冲突的 status: public + c. 若无 draft: true 则在 status: hidden 行后补一行 + 2. 安全检查:新内容非空、且长度不低于原内容的 90%,否则跳过保存 + 3. 以 UTF-8(无 BOM)写回 +""" +import os +import re +import sys + +POSTS_PATH = "content/posts" + +# 与原脚本保持一致的正则(多行模式) +RE_STATUS_HIDDEN = re.compile(r'^status:\s*("hidden"|hidden)', re.M) +RE_DRAFT_FALSE = re.compile(r'^draft:\s*false', re.M) +RE_STATUS_PUBLIC = re.compile(r'^status:\s*("public"|public)', re.M) +RE_DRAFT_TRUE = re.compile(r'^draft:\s*true', re.M) +RE_STATUS_HIDDEN_LINE = re.compile(r'^(status:\s*("hidden"|hidden).*$)', re.M) + + +def main() -> int: + if not os.path.isdir(POSTS_PATH): + print(f"Path not found: {POSTS_PATH}", file=sys.stderr) + return 1 + + md_files = [] + for root, _dirs, files in os.walk(POSTS_PATH): + for name in files: + if name.endswith(".md"): + md_files.append(os.path.join(root, name)) + md_files.sort() + + count = 0 + print("Starting scan for hidden posts cleanup...") + + for path in md_files: + with open(path, "r", encoding="utf-8") as f: + content = f.read() + + if not content: + print(f" Skipping empty file: {path}") + continue + + # 仅处理含 status: hidden 的文件(与原脚本一致,仅匹配 frontmatter 行首) + if not RE_STATUS_HIDDEN.search(content): + continue + + modified = False + new_content = content + + # 1. draft: false -> draft: true + if RE_DRAFT_FALSE.search(new_content): + new_content = RE_DRAFT_FALSE.sub("draft: true", new_content) + modified = True + print(f" Fixed 'draft: false' in {path}") + + # 2. 注释掉 status: public + if RE_STATUS_PUBLIC.search(new_content): + new_content = RE_STATUS_PUBLIC.sub( + r"# \g<0> # Auto-hidden by script", new_content + ) + modified = True + print(f" Commented out 'status: public' in {path}") + + # 3. 确保存在 draft: true + if not RE_DRAFT_TRUE.search(new_content): + new_content = RE_STATUS_HIDDEN_LINE.sub( + lambda m: f"{m.group(1)}\ndraft: true", new_content + ) + modified = True + print(f" Added 'draft: true' to {path}") + + if modified: + # 安全检查 1:新内容非空 + if not new_content: + print( + f"CRITICAL: New content is empty for {path}. Skipping save.", + file=sys.stderr, + ) + continue + + # 安全检查 2:长度不应异常缩小(>10%) + if len(new_content) < len(content) * 0.9: + print( + f"CRITICAL: Suspicious size drop for {path}. Skipping save.", + file=sys.stderr, + ) + continue + + with open(path, "w", encoding="utf-8", newline="") as f: + f.write(new_content) + print(f" -> Saved changes to {path}") + count += 1 + + print(f"Completed. Updated {count} files.") + return 0 + + +if __name__ == "__main__": + sys.exit(main())