ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

技术博客一键多发实战:基于 GitHub Actions 与双引擎的自动化发布流水线

技术博客一键多发实战:基于 GitHub Actions 与双引擎的自动化发布流水线 技术博客一键多发实战基于 GitHub Actions 与双引擎的自动化发布流水线作为一名技术作者写一篇技术博客然后手动复制到掘金、CSDN、知乎、微信公众号……这种重复劳动正在吞噬你的创作时间。本文将手把手带你搭建一套基于GitHub Actions 文颜 multi-publisher的双引擎自动化发布系统实现git push即全平台上线。本文所有操作基于 GitHub Actions配置简单、生态完善、日志清晰是技术作者的绝佳选择。一、为什么需要双引擎技术作者的发布矩阵通常包含两类平台微信公众号受众精准但格式封闭图片必须上传到自身素材库。技术社区掘金、CSDN、知乎 等开放性较好但 Cookie 维护和反爬策略各不相同。单靠一个工具很难同时兼顾这两类平台的稳定性与覆盖面。文颜在微信公众号的 API 集成上做得非常深入合规且稳定而multi-publisher则能覆盖 20 技术社区实现广度分发。将二者组合为“双引擎”就能在一个 Git 仓库内让每篇文章自动适配不同平台的格式、图片和发布方式真正实现Write once, publish everywhere。二、项目结构与文章规范在动手之前先约定好 Git 仓库的目录结构。清晰的模块划分是自动化流程能被准确触发和追溯的基础。my-blog-workspace/ ├── .github/ # [核心] GitHub Actions 配置目录 │ └── workflows/ │ └── publish.yml # [核心] 流水线配置文件 ├── posts/ # [核心] 存放所有待发布的 Markdown 文件 │ ├── my-new-article.md │ └── another-article.md ├── package.json # [重要] 声明 wenyan 和 multi-publisher 依赖供 CI 安装 ├── .gitignore └── README.md为了让工具自动识别标题、标签、封面以及发布状态每篇 Markdown 文章都必须以YAML Front Matter开头。它是整条流水线的“身份证”。---title:构建个人博客的 CI/CD 自动发布流水线date:2026-08-04tags:[DevOps,CI/CD,自动化]cover:https://your-image-bed.com/cover-image.jpgstatus:# [可选] 记录各平台发布状态zhihu:juejin:csdn:weixin:---title / date / tags会被自动提取并填写到对应平台的编辑框。cover统一使用外链图片建议搭建图床如阿里云 OSS、腾讯云 COS。文章中的图片同样使用外链这样在支持外链的平台可以直接显示公众号等封闭平台则由工具自动下载并转存。status每次发布成功后将平台返回的文章 ID 或链接写回此处避免重复发布。三、本地环境与核心工具安装3.1 准备 Node.js 环境本地计算机需安装Node.js v18.20。在终端中验证node--versionnpm--version3.2 全局安装双引擎本地测试用3.2.1 全局安装双引擎指令# 负责微信公众号稳定发布npminstall-gwenyan-md/cli wenyan--version# 负责其他技术社区广度分发npminstall-gmulti-publisher mpub--version3.2.2 关于package.json的重要说明本地测试时我们使用npm install -g全局安装两个工具所以可以直接在终端运行命令。但在 GitHub Actions 流水线中脚本里执行的是npm ci这是本地安装且严格锁定版本——它读取package-lock.json确保每次 CI 安装的依赖完全一致。这也是为什么必须把package-lock.json一起提交到仓库。因此请务必在项目根目录创建package.json并将两个工具写入devDependencies{name:my-blog-workspace,version:1.0.0,description:自动化发布博客流水线,devDependencies:{wenyan-md/cli:latest,multi-publisher:latest},scripts:{publish:wenyan publish mpub publish}}这样流水线中的npm install就会正确安装依赖虽然package.json中的scripts脚本可以直接调用但在 GitHub Actions 的run步骤中直接执行时建议加上npx前缀如npx wenyan publish以确保 CI 环境能准确找到node_modules/.bin下的可执行文件。3.2.3 关于scripts.publish的说明scripts.publish是本地调试用的快捷命令。当你在本地写完几篇文章想测试一下工具能不能正常工作但不想走git push触发 CI 时可以直接在项目根目录敲npm run publish它会把你posts/目录下所有文章都发一遍前提是你的工具支持默认路径。GitHub Actions 流水线中直接调用带参数的原始命令-f指定具体文件不依赖此脚本。四、获取并配置各平台身份凭据这是整条流水线最关键的一步。不同平台使用不同的认证方式需要逐个配置。首选需要明确这里的身份凭据的含义​ a. 在微信公众号中的身份凭据是其AppID和AppSecret由文颜负责​ b. 其他技术社区的身份凭据形式是Cookie由multi-publisher 负责;4.1 配置微信公众号身份凭据AppIDAppSecret形式由文颜负责文颜使用官方 API 发布到草稿箱因此需要AppID和AppSecret。登录微信公众号后台进入「设置与开发」→「账号设置」→「注册信息」复制 AppID前往微信开发者平台进入「首页」→「公众号」→「开发密钥」→「AppSecret」→「开启」→ 「管理员扫码重置」复制 AppSecret 建议永久保存否则下一次仍需重置在「设置与开发」→「安全中心」→「IP 白名单」页面将 GitHub Actions 运行环境的公网出口 IP 加入白名单否则 API 调用会被拒绝如何获取 GitHub Actions 的 IPGitHub Actions 的 IP 段是动态的官方会定期公布 IP 列表见 meta API。建议先不加白名单运行一次流水线在微信后台的调用日志中会看到被拒绝的 IP再将对应 IP 段加入白名单。4.2 配置其他技术社区身份凭据Cookie形式multi-publisher 负责4.2.1 配置Cookie的指令multi-publisher 通过保存登录后的 Cookie 来模拟用户操作。在本地终端cmd/PowerShell中依次执行mpub login-pzhihu mpub login-pjuejin mpub login-pcsdn# ... 按需登录其他平台每执行一条命令工具会打开浏览器窗口让你完成登录授权如下图登录成功后Cookie 会被安全地加密保存在本地~/.mpub/目录下。接下来我们需要拿到本地生成的 Cookie 字符串然后设置到 GitHub Secret 中以便 GitHub Actions 流水线能顺利获取这些身份凭据详见后面的第五步因此我们接下来的操作的目的是为了第五步做准备的。这一点需要你首先明确。4.2.2 找到本地 Cookie 的存储位置multi-publisher登录成功后会将 Cookie 加密保存在配置文件中实际为明文 JSON但建议不要手动编辑Linux/macOS~/.config/multi-publisher/config.jsonWindowsC:\Users\[你的用户名]\.config\multi-publisher\config.json你可以通过以下命令查看确切的配置文件路径mpub credential--location打开配置文件你会发现cookies字段是一个JSON 对象例如{csrf_session_id:abc, s_v_web_id:xyz}。然而在 CI/CD 环境变量中multi-publisher需要接收的是标准的 HTTP Cookie 字符串即key1value1; key2value2的形式。直接将整个 JSON 对象粘贴到 GitHub Secrets 中是无效的因此我们必须先将本地的 Cookie 转换成这种字符串格式。下面提供两种简单的方法来完成这一转换。4.2.3 将 Cookie 的「 JSON 对象」导出成「标准 HTTP Cookie 字符串」multi-publisher没有内置的导出命令mpub credential export并不支持-p参数但你可以通过读取配置文件来生成符合 HTTP Cookie 规范的字符串。方法1使用 jq 命令格式化 Cookie JSON 对象jq是一款轻量级的命令行 JSON 处理器安装后可以用一条命令直接提取并拼接 Cookie。如果你不想安装jq也可以使用文末的 Node.js 脚本跨平台通用无需额外安装。安装 jq 提示macOSbrew install jqLinux (Debian/Ubuntu)sudo apt install jqWindows可用winget install jqlang.jq或下载可执行文件加入 PATH具体可自行搜索。 macOS / Linuxbash/zsh# 知乎jq-r.zhihu.cookies | to_entries | map(.key .value) | join(; )~/.config/multi-publisher/config.json# 掘金jq-r.juejin.cookies | to_entries | map(.key .value) | join(; )~/.config/multi-publisher/config.json# CSDNjq-r.csdn.cookies | to_entries | map(.key .value) | join(; )~/.config/multi-publisher/config.json Windows CMDWin 用户推荐 使用 Command Prompt而不是 PowerShellREM 知乎 jq -r .zhihu.cookies | to_entries | map(.key \\ .value) | join(\; \) %USERPROFILE%\.config\multi-publisher\config.json REM 掘金 jq -r .juejin.cookies | to_entries | map(.key \\ .value) | join(\; \) %USERPROFILE%\.config\multi-publisher\config.json REM CSDN jq -r .csdn.cookies | to_entries | map(.key \\ .value) | join(\; \) %USERPROFILE%\.config\multi-publisher\config.json执行后终端会输出一行完整的 Cookie 字符串例如csrf_session_idxxx; s_v_web_idyyy; ...直接复制即可。⚠️Win 用户请注意PowerShell 环境下执行jq命令存在引号解析和转义问题强烈建议使用 CMDCommand Prompt 执行以上命令或直接使用下面的 Node.js 脚本跨平台无需关心引号。如果你在 PowerShell 中执行jq遇到syntax error等报错属于正常现象请切换到 CMD 或使用 Node.js 方案。方法2使用 Node.js 脚本格式化 Cookie JSON 对象如果 jq 命令执行报错或你不想额外安装工具可以用 Node.js 脚本因为multi-publisher本身依赖 Node你的电脑一定有 Node 环境。创建一个文件export-cookie.js内容如下constfsrequire(fs);constpathrequire(path);constosrequire(os);constconfigPathpath.join(os.homedir(),.config,multi-publisher,config.json);constconfigJSON.parse(fs.readFileSync(configPath,utf8));constplatformprocess.argv[2]||juejin;// 从命令行参数获取平台名constcookiesconfig[platform]?.cookies;if(!cookies){console.error(平台${platform}未找到请检查配置文件);process.exit(1);}constcookieStringObject.entries(cookies).map(([k,v])kv).join(; );console.log(cookieString);然后执行任何系统终端均可nodeexport-cookie.js juejin输出的 Cookie 字符串同样可直接复制使用无需关心操作系统差异。**注意**无论使用哪种方式将得到的字符串填入 GitHub Secrets 时类型都选择为“Secret”。五、在 GitHub 仓库中配置 Secrets流水线中需要使用的敏感信息如微信 AppID、各平台 Cookie 等不应硬编码在配置文件中而应通过 GitHub 的Secrets功能来管理。现在我们将第四步中得到的微信AppIDAppSecret、其他各平台导出的Cookie字符串填入到 GitHub Secrets 中方便GitHub Actions 流水线使用这些身份凭据。5.1 进入 Secrets 设置页面打开你的 GitHub 代码仓库进入Settings→Secrets and variables→Actions。5.2 添加 Secret点击“New repository secret”按钮按照提示填写Name输入纯英文标识符例如WECHAT_APP_ID。Value粘贴对应的实际凭证内容。5.3 保存并重复点击“Add secret”。重复以上步骤依次添加你在第四节中获取到的所有凭证Secret 名称说明WECHAT_APP_ID微信公众号 AppIDWECHAT_APP_SECRET微信公众号 AppSecretZHIHU_COOKIE知乎平台 CookieJUEJIN_COOKIE掘金平台 CookieCSDN_COOKIECSDN 平台 Cookie 如何为multi-publisher平台准备正确的 Cookie 值在 4.2 节中我们已经介绍了从本地配置文件导出标准 Cookie 字符串的方法。请使用jq 或 Node.js 脚本生成完整的keyvalue; ...字符串然后将其粘贴到对应 Secret 的“Value”框中。切勿直接粘贴 JSON 对象或仅粘贴部分键值对否则multi-publisher将无法正常登录。各平台对应的 Secret 名称如下知乎 →ZHIHU_COOKIE掘金 →JUEJIN_COOKIECSDN →CSDN_COOKIE如果后期 Cookie 过期只需在本地重新登录mpub login -p 平台再次运行导出脚本更新 GitHub Secret 即可流水线配置无需改动。5.4 在流水线中引用 Secret变量添加完成后在 GitHub Actions 的 YAML 中通过${{ secrets.变量名 }}的形式直接引用即可。例如env:WECHAT_APP_ID:${{secrets.WECHAT_APP_ID}}GitHub Actions 在执行流水线时会自动将这些 Secret 注入到运行环境中。六、搭建 GitHub Actions 流水线双引擎实战在编写核心的自动化脚本之前我们需要先在 GitHub 仓库中配置好流水线的运行权限。由于我们的流水线在发布成功后会执行git push将文章状态写回仓库而 GitHub Actions 默认只有只读权限因此需要提前开启写入权限否则流水线会在最后的推送步骤报错退出。6.1 配置 Workflow 写入权限进入你的 GitHub 仓库页面。点击Settings设置。在左侧导航栏找到Actions-General。滚动到页面最下方找到Workflow permissions工作流权限。将默认的Read repository contents and packages permissions修改为Read and write permissions读写权限。点击Save保存。配置完成后流水线就拥有了向仓库提交状态更新的能力。接下来我们开始编写具体的自动化脚本。6.2 创建流水线配置文件GitHub Actions 的配置文件需要放在仓库根目录下的.github/workflows/目录中文件名为publish.yml。在仓库根目录创建.github/workflows/publish.ymlname: 自动发布技术博客 on: push: branches: [main] paths: - posts/*.md workflow_dispatch: inputs: files: description: 要发布的文件空格分隔留空则全部发布 required: false default: jobs: publish: runs-on: ubuntu-latest steps: - name: 检出代码 uses: actions/checkoutv5 with: fetch-depth: 0 - name: 安装 Node.js uses: actions/setup-nodev5 with: node-version: 22 - name: 安装依赖 run: npm ci - name: 安装 Playwright 浏览器 run: npx playwright install chromium --with-deps - name: 获取要发布的文件 id: get-files run: | if [ ${{ github.event_name }} workflow_dispatch ]; then if [ -n ${{ inputs.files }} ]; then FILES${{ inputs.files }} else FILES$(find posts -name *.md | tr \n ) fi else CHANGED_FILES$(git diff --name-only HEAD^ HEAD | grep posts/.*\.md$ | tr \n ) FILES$CHANGED_FILES fi echo files$FILES $GITHUB_OUTPUT - name: 写入 multi-publisher Cookie 配置 env: JUEJIN_COOKIE: ${{ secrets.JUEJIN_COOKIE }} CSDN_COOKIE: ${{ secrets.CSDN_COOKIE }} ZHIHU_COOKIE: ${{ secrets.ZHIHU_COOKIE }} run: | node EOF const fs require(fs); const path require(path); const os require(os); const configDir path.join(os.homedir(), .config, multi-publisher); const configPath path.join(configDir, config.json); fs.mkdirSync(configDir, { recursive: true }); // 解析标准 HTTP Cookie 字符串为 key-value 对象 function parseCookieString(str) { const cookies {}; str.split(;).forEach(part { const t part.trim(); if (!t) return; const i t.indexOf(); if (i -1) return; let k t.slice(0, i).trim().replace(/^|$/g, ); let v t.slice(i 1).trim().replace(/^|$/g, ); cookies[k] v; }); return cookies; } const platforms [csdn, juejin, zhihu]; const config { version: 1 }; for (const platform of platforms) { const envName platform.toUpperCase() _COOKIE; const val process.env[envName]; if (!val) { console.log(⏭ 跳过 ${platform}环境变量 ${envName} 为空); continue; } const cookies parseCookieString(val); const count Object.keys(cookies).length; config[platform] { cookies }; console.log(✅ ${platform} Cookie 已写入${count} 条); } fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); console.log( 配置文件已保存到${configPath}); EOF - name: 发布文章 if: steps.get-files.outputs.files ! env: WECHAT_APP_ID: ${{ secrets.WECHAT_APP_ID }} WECHAT_APP_SECRET: ${{ secrets.WECHAT_APP_SECRET }} run: | FAILED_PLATFORMS for file in ${{ steps.get-files.outputs.files }}; do echo 开始发布$file # 剥离 Front Matter 删 TOC 压缩空行CSDN 用 sed 1{/^---$/!q}; 1,/^---$/d $file | sed /^\[TOC\]$/d | cat -s /tmp/publish-body.md echo 文颜引擎 → 微信公众号 if ! npx wenyan publish -f $file; then FAILED_PLATFORMS$FAILED_PLATFORMS WeChat echo ❌ 文颜引擎发布失败 2 fi echo multi-publisher → 掘金、知乎、CSDN for platform in juejin zhihu csdn; do echo multi-publisher → $platform PUBLISH_FILE$file # 默认用原文件掘金 / 知乎 THEME_ARG case $platform in zhihu) # 知乎mpub publish 不支持自定义 CSS用内置 modern 主题 THEME_ARG-t modern ;; csdn) # CSDN编辑器不识别 Front Matter用剥离后的纯正文 PUBLISH_FILE/tmp/publish-body.md ;; juejin) # 掘金原生样式已足够好不加主题 ;; esac if ! npx mpub publish -f $PUBLISH_FILE -p $platform $THEME_ARG; then FAILED_PLATFORMS$FAILED_PLATFORMS $platform echo ❌ $platform 发布失败 2 fi done echo ✅ 完成发布$file done if [ -n $FAILED_PLATFORMS ]; then echo ⚠️ 警告以下平台发布可能失败$FAILED_PLATFORMS fi - name: 提交状态更新 if: steps.get-files.outputs.files ! run: | git config --global user.name GitHub Actions Bot git config --global user.email actionsgithub.com git add posts/ git commit -m ci: 更新文章发布状态 [skip ci] || echo 没有状态变更 git push配置解读① 触发条件onpush.branches: [main]只有推送到main分支才触发其他分支的改动不会误发。push.paths: posts/*.md只有posts/目录下的 Markdown 变更才触发。这意味着你改 README、改 workflow 文件本身都不会触发发布避免无效运行。workflow_dispatch支持在 GitHub 网页端手动触发可输入files参数指定要发布的文件空格分隔留空则全量发布。适合重发某一篇或补发历史文章的场景。② 运行环境runs-on: ubuntu-latest使用 Ubuntu 最新版运行器。actions/checkoutv5fetch-depth: 0检出完整 Git 历史。fetch-depth: 0是必须的因为后续步骤要用git diff HEAD^ HEAD找出本次推送改动了哪些文件默认的浅克隆会导致这个命令失败。actions/setup-nodev5node-version: 22安装 Node 22。multi-publisher 要求 Node ≥ 18同时选用 LTS 版本以保证长期稳定性。③ 依赖安装npm ci严格按package-lock.json安装依赖比npm install更快、更可复现。只要 lock 文件被提交且与package.json一致就能保证每次 CI 安装的依赖完全相同。npx playwright install chromium --with-deps安装 Playwright 的 Chromium 浏览器与系统依赖。multi-publisher 通过浏览器自动化完成掘金、CSDN、知乎等平台的发布这一步是运行时硬依赖不能省。④ 增量发布逻辑get-filespush 事件通过git diff --name-only HEAD^ HEAD只提取本次提交中改动或新增的posts/*.md实现只发新文章/改过的文章避免全量重发。手动触发如果填写了files参数就用它否则用find posts -name *.md全量发布。结果通过echo files... $GITHUB_OUTPUT写入供后续步骤用${{ steps.get-files.outputs.files }}读取。⑤ Cookie 配置写入 multi-publisher 配置文件从 GitHub Secrets 读取JUEJIN_COOKIE、CSDN_COOKIE、ZHIHU_COOKIE三个环境变量。用一段内联的 Node.js 脚本把标准 HTTP Cookie 字符串key1value1; key2value2解析成 key-value 对象写入~/.config/multi-publisher/config.json。这一步是 multi-publisher 在 CI 环境下的唯一凭据来源。Cookie 过期后需要在本地mpub login重新登录并导出再更新对应的 GitHub Secret。⑥ 双引擎发布核心逻辑流水线同时调用两个工具各自负责不同的平台引擎负责平台认证方式特点文颜wenyan微信公众号AppID AppSecret官方 API合规稳定自动下载图片上传到微信素材库multi-publishermpub掘金、CSDN、知乎Cookie浏览器自动化覆盖 20 社区支持增量发布⑦ 各平台的差异化处理同一个 Markdown 文件在发布到不同平台时走了不同的预处理路径掘金直接使用原始文件$file含 Front Matter。掘金原生识别 Front Matter样式已足够好不需要额外处理。CSDN用sed剥离 Front Matter sed删除[TOC]cat -s压缩连续空行得到纯正文后发布。CSDN 编辑器不识别 Front Matter会把元数据当正文渲染。知乎直接使用原始文件 -t modern。mpub 会自行解析 Front Matter 提取标题并用内置 modern 主题渲染。注意mpub 1.1.4 的publish子命令不支持自定义 CSS因此themes/zhihu.css当前未被引用保留作未来备胎。微信公众号直接使用原始文件由文颜内部处理 Front Matter、图片转存等。⑧ 失败容错每个平台独立 try-catch某一平台失败不会中断其他平台的发布。失败时把平台名追加到FAILED_PLATFORMS变量最后统一打印警告。注意这种设计下即使所有平台都失败workflow 也会显示绿色成功。如果希望在失败时让 workflow 报红可以最后加[ -z $FAILED_PLATFORMS ] || exit 1。⑨ 状态回写git add posts/ git commit -m ci: 更新文章发布状态 [skip ci]用来把发布状态写回仓库例如把文章 ID 填到 Front Matter 的status字段。当前实现里这部分是预留位——workflow 还没有真的修改posts/下的文件所以每次都会走|| echo 没有状态变更分支。未来如果要做防重复发布可以让 workflow 解析每个平台的返回链接写回 Front Matter再提交。[skip ci]标记防止这次回写 commit 再次触发 workflow。6.3 提交并推送配置# 创建 workflows 目录mkdir-p.github/workflows# 将上面的 YAML 内容保存到 .github/workflows/publish.yml# 然后提交并推送gitadd.github/workflows/publish.yml package.json posts/gitcommit-mfeat: 添加 GitHub Actions 自动发布流水线gitpush origin main6.4 验证流水线在 GitHub 仓库页面点击Actions标签页。你会看到名为“自动发布技术博客”的 Workflow。点击“Run workflow”按钮在下拉菜单中可以选择输入files参数留空则发布全部然后点击“Run workflow”手动触发一次。观察构建日志确保所有步骤都成功。6.5 日常使用流程现在你的日常创作流程就简化为了在本地用 Typora、VS Code 或 Obsidian 写文章图片自动上传至图床。填写 Front Matter保存到posts/目录。执行gitaddposts/新文章.mdgitcommit-m新文章: xxxgitpush几秒钟后GitHub Actions 会自动检测到main分支的推送并启动流水线。你可以在Actions页面查看实时构建日志。构建成功后掘金、CSDN图文完整、标签正确知乎标题、正文、代码块正常图片与二级标题格式暂时受 mpub 上游 bug 影响需手动补一次微信公众号需要在微信后台配置 IP 白名单后才能成功手动触发指定文件若你只想发布某几篇文章可以在 Actions 页面点击“Run workflow”在弹出的对话框中填写files参数例如posts/my-new-article.md posts/another.md流水线将只发布这些文件留空则发布全部。七、进阶功能与长期维护7.1 分平台管理文章状态防止重复发布发布成功后建议将返回的文章 ID 写回 Front Matter 的status字段并提交回仓库。例如status:juejin:https://juejin.cn/post/1234567890zhihu:https://zhuanlan.zhihu.com/p/1234567890weixin:https://mp.weixin.qq.com/s/xxxxxx在下次流水线触发时脚本可以增加判断逻辑若对应平台已有 ID则跳过或执行“更新”而非“重新发布”避免产生重复文章。7.2 定时巡检与 Token 有效期维护Cookie 过期是多平台分发的最大敌人。可以通过创建一个定时触发的流水线配合 multi-publisher 的 cookie 相关命令来监控状态具体子命令请通过mpub cookie --help确认。如果检测到凭证失效流水线通过企业微信、钉钉或飞书机器人发送通知提醒你重新登录并更新 Secrets。7.3 发布结果通知在流水线 YAML 的run脚本最后添加一个通知脚本调用你习惯的 IM 工具的 Webhook 接口将发布结果成功或失败及时推送给自己让你能第一时间处理异常。八、常见问题 QAQ1国内访问 GitHub Actions 速度慢怎么办GitHub Actions 的运行器位于海外但执行npm ci时可以使用国内镜像源加速。在package.json同级目录创建.npmrc文件registryhttps://registry.npmmirror.com或在流水线的npm install前添加npmconfigsetregistry https://registry.npmmirror.com你仓库中的package-lock.json的resolved字段已经指向registry.npmmirror.com说明本地装依赖时已经用了淘宝源CI 会沿用。Q2multi-publisher 支持 20 平台如何只发布到指定的几个使用-p参数即可精确指定目标平台mpub publish-fmy-article.md-pjuejin-pcsdnQ3如何只发布新增或修改的文章而不是全量发布流水线配置中的「获取要发布的文件」步骤就是为此而设计。它通过git diff只识别出本次推送涉及到的 md 文件实现增量发布。Q4文章中使用了图床外链微信公众号无法显示怎么办这正是引入文颜的意义之一。文颜在执行发布时会自动将 Markdown 中的外部图片链接下载并上传到微信公众号素材库然后用返回的mmbiz.qpic.cn链接替换原文全程无需手动操作。Q5遇到发布失败如何调试优先查看 GitHub Actions 的详细日志输出点击 Actions 中的具体任务即可展开。在本地重现命令例如wenyan publish -f your-article.md通过错误信息定位问题。访问对应工具的 GitHub 仓库查看已有 Issues 或提交新问题。Q6GitHub Actions 的免费额度够用吗GitHub Actions 对公开仓库完全免费对私有仓库每月提供 2000 分钟免费额度。对于个人博客发布场景通常绰绰有余。如果额度用尽可以考虑将仓库设为公开或购买额外额度。Q7微信公众平台需要配置 IP 白名单GitHub Actions 的 IP 怎么获取GitHub Actions 的 IP 段是动态的官方通过 https://api.github.com/meta 发布 IP 列表。建议先不加白名单运行一次流水线在微信后台的调用日志中会看到被拒绝的 IP再去「设置与开发」→「安全中心」→「IP 白名单」中将对应 IP 段加入。由于 IP 会变化可能需要定期更新。Q8流水线报错Process completed with exit code 128怎么解决这个错误大概率发生在流水线最后一步git push时。说明你跳过了 6.1 节的配置GitHub Actions 默认给工作流的GITHUB_TOKEN只有读权限无法向仓库推送新的 commit。解决办法请回到文章6.1 节前往仓库的Settings-Actions-General在页面最底部的Workflow permissions中勾选Read and write permissions保存后重新运行Re-run jobs即可。Q9流水线报错40164: invalid ip ... not in whitelist怎么办说明你把文章 4.1 节的 IP 白名单没配好或者 GitHub Actions 出口 IP 变了。建议将https://api.github.com/meta里actions的完整 IP 段批量加入微信后台白名单或者写一个自动更新脚本。Q10multi-publisher 报错“未配置 XX Cookie”怎么办这是提示你 Secrets 没配好。请回到文章 4.2 节使用mpub login和导出脚本重新生成 Cookie 字符串并确保在 GitHub 仓库 Settings - Secrets 中正确添加了对应平台的 Secret如CSDN_COOKIE、JUEJIN_COOKIE等且值粘贴正确。Q11知乎和 CSDN 草稿开头多出了一段 Front Matter 怎么办Front Matter 是给流水线提取元数据用的但 CSDN 的编辑器不识别它会把它当正文渲染。解决办法是在 workflow 中按平台分别处理CSDN剥离 Front Matter 删除[TOC] 压缩连续空行生成纯正文后发布知乎保留原始 Markdown直接交给 mpub由 mpub 自己解析 Front Matter并通过-t modern主题渲染掘金保留原文件掘金原生识别 Front Matter说明知乎和掘金都保留 Front Matter因为 mpub 会从中提取标题CSDN 走的是另一条路径由 workflow 主动剥离。九、结语从“写完一篇技术博客花半小时搬运到各个平台”到“git push之后静待花开”这条自动化之路在今天已经非常成熟。双引擎文颜 multi-publisher的组合既保证了对微信公众号这一封闭生态的稳定输出又兼顾了众多技术社区的广泛触达。GitHub Actions作为 CI/CD 平台配置简单、生态完善、日志清晰是技术博客自动化发布的最佳选择。一旦搭建完成你就能把时间真正还给思考和创作而不再被格式、图片和登录这些琐事打断。现在就动手享受一次git push然后全平台上线带来的畅快体验吧。
返回列表