Jekyll 稳定分支发布指南:从 3.9-stable 等旧版本分支回溯安全补丁与关键修复
2026/9/18 8:47:02 网站建设 项目流程

Jekyll 稳定分支发布指南:从 3.9-stable 等旧版本分支回溯安全补丁与关键修复

【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll

本文面向 Jekyll 核心维护者,讲解如何从[x].[y]-stable命名的旧版本稳定分支(如3.9-stable)切出包含安全补丁和关键 Bug 修复的发布版本,并同步更新master默认分支上的版本元文件。读完后你将掌握完整的双分支发布流程:稳定分支上如何触发发布、master上如何回填 History 与站点元文件,以及如何手动发布机器人不覆盖的非默认分支 GitHub Release。

背景:为什么要从稳定分支切发布

Jekyll Core 的常规发布都从默认master分支切出。但当仍在维护期内的旧版本系列出现需要修复的安全漏洞或关键 Bug 时,核心团队会从专门命名的稳定分支切出回溯发布。分支命名遵循[x].[y]-stable模式:

  • [x]为 semver 主版本号,[y]为次版本号;
  • 例如3.9-stable分支上的提交,最终都会以jekyll-3.9.x系列 gem 的形式发布。

这一点可以从 History.markdown 中得到印证:3.9.x系列至今持续有安全补丁发布,如## 3.9.5 / 2024-02-12## 3.9.4 / 2023-12-28## 3.9.3 / 2023-01-29## 3.9.2 / 2022-03-27等小节,它们与4.x主线版本并存于同一份历史文档中。

流程之所以比常规发布复杂,根源在于:稳定分支上的发布,最终也必须在master分支上留下记录——版本历史、文档站点的 changelog 和站点配置文件都只能由master上的生成任务统一维护。

前置条件

开始操作前,维护者必须满足以下条件(摘自 releasing-off-stable-branches.md):

  1. 对目标*-stable分支和master分支均拥有写权限
  2. 全程使用本地 CLI 程序(git/rake)完成任务,而不是通过 GitHub Web UI 操作;
  3. 熟悉从master切发布的标准流程(见 releasing-a-new-version.md),本文流程是其在稳定分支上的缩减改编版;
  4. 发布博文(release post)已经起草完毕,并且已通过一个处于可合并状态的 pull request等待合并到master
  5. 稳定的网络连接。

阶段一:在稳定分支上触发发布

确认本地已检出目标*-stable分支,且与远端jekyll/jekyll上的同名分支保持同步后,按以下步骤操作:

  1. 更新版本号:修改 lib/jekyll/version.rb 中的VERSION字符串。该文件是仓库中唯一需要手动改版本号的地方:

    module Jekyll VERSION = "4.4.1" end

    Rakefile 顶部的version辅助函数直接读取Jekyll::VERSION,gem 构建、任务名等均由此派生,因此改这一处即可联动全局。

  2. 更新 History 文档:按 更新 History 文档的标准做法操作——把 History.markdown 的第一个标题## HEAD替换为## X.Y.Z / YYYY-MM-DD形式的版本里程碑标题(版本号与发布日期都要调整),并按优先级从高到低重排小节(Major EnhancementsMinor EnhancementsBug FixesSecurity Fixes等)。

    重要:在稳定分支上切勿运行rake site:generate该任务会把 History.markdown 转换后写入文档站的 docs/_docs/history.md 等元文件,而这些文件只能在master上生成——这正是后文"更新默认分支"阶段才执行该命令的原因。

  3. 暂存 History 片段:把与本次发布相关的完整 History 小节(标题行连同其下所有条目)复制并粘贴到文本编辑器的一个新标签页/窗口中备用,后续在master回填和撰写 GitHub Release 正文时都会用到。

  4. 提交并推送:以规范的提交信息提交版本号文件与 History 文档的改动,然后推送到上游远端:

    git commit -am "Release :gem: v[CURRENT_VERSION]" git push upstream 3.9-stable

    其中upstream指向git@github.com:jekyll/jekyll.git[CURRENT_VERSION]替换为本次发布的实际版本号。

为什么稳定分支的流程与 master 不同:自动化边界

常规master发布中,推送后会自动触发 GitHub Actions 工作流完成 gem 构建、打 tag、推 gem,并由 JekyllBot 发布 GitHub Release。但从 release-please.yml 可以看到,该工作流的触发条件被严格限定为:

on: push: branches: - master

release-pleasejob 运行 release-please-action,其中version-file指向lib/jekyll/version.rbchangelog-path指向History.markdowninclude-v-in-tagtrue),随后的publish-gemjob 仅在release_created == 'true'时构建并发布 gem。也就是说,整套自动化只对master生效——从3.9-stable等非默认分支推送后,机器人不会创建 tag、不会发布 gem、更不会创建 GitHub Release,这些步骤都必须由维护者手动完成。当前发布基线可参考 .github/release-please-manifest.json(记录".": "4.4.1")。

阶段二:发布博文到 master

  1. 确认稳定分支上触发的工作流(gem 构建与发布流水线)已成功完成。
  2. 将此前起草的 release post pull request合并到master

阶段三:让默认分支反映稳定分支的发布

本地检出master并确认其与远端同步后:

  1. 回填 History 文档:将之前暂存的 History 片段手动注入 History.markdown 的正确位置。History 文档中的各版本小节首要按时间倒序排列,次要按 semver 主版本归类。例如v3.9.2的发布小节会排在v3.9.1之上、但位于所有4.x版本小节之下。这一点在 History.markdown 中可以直接验证:4.4.1 / 2025-01-294.4.0 / 2025-01-274.x小节在前,其后才是## 3.9.5 / 2024-02-12起的3.9.x序列。

  2. 可选:更新VERSION字符串:若 lib/jekyll/version.rb 中的现有版本号小于本次稳定分支发布的最新版本号,则一并更新。

  3. 运行rake site:generate更新文档站点的元文件。该任务是 rake/site.rake 中定义的聚合任务:generated_pages,包含:history:latest_version:conduct:contributing:security:support六个子任务,其中与版本号直接相关的产物有:

    • docs/_config.yml—— 站点配置中的version字段;
    • docs/_docs/history.md—— 由History.markdown转换生成的 changelog 页面;
    • docs/latest_version.txt—— 记录最新版本号的纯文本文件。

    从 site.rake 的latest_version任务 可以看到其具体逻辑:

    task :latest_version do next if version =~ %r!(beta|rc|alpha)!i # 预发布版本不写入 ... config["version"] = version # 写入 docs/_config.yml File.write(config_file, YAML.dump(config)) File.open("#{docs_folder}/latest_version.txt", "wb") { |f| f.puts(version) } end

    注意其中有一处关键约束:版本号匹配beta|rc|alpha时任务直接跳过,即预发布版本不会同步到站点元文件。当前仓库中这三个文件的状态也印证了这一点:docs/_config.yml中为version: 4.4.1,docs/latest_version.txt 内容为4.4.1,与lib/jekyll/version.rb完全一致。

    History 页面的生成则由:history任务调用siteify_file("History.markdown")完成:Rakefile 中的siteify_file会为文件补上 front matter(含permalink: /docs/history/与"本文件自动生成,请编辑源文件"的提示),content_for 再经converted_history管道处理——去掉## HEAD段、为每个版本标题和子小节生成锚点、把裸的#1234PR 编号转为链接、并对含 Liquid 语法的片段包上{% raw %}转义。

  4. 提交并推送:将各元文件改动以提交信息Release :gem: v[CURRENT_VERSION]提交,推送到上游远端。

阶段四:手动发布 GitHub Release

这是稳定分支发布与master发布最显著的区别:由于 JekyllBot 只为默认分支创建的 tag 自动创建并发布 GitHub Release,维护者必须手动为稳定分支新推的 tag 创建发布:

  1. 选择刚推送的新 tag;
  2. 标题与所选 tag 名保持一致(因include-v-in-tagtrue,tag 形如v3.9.5);
  3. 之前暂存的 History 片段作为 Release 正文;
  4. 从正文中删除片段标题行(即## x.y.z / YYYY-MM-DD这一行);
  5. 点击发布。

技巧:可以在更新默认分支之前就先把 GitHub Release 置为draft(草稿)状态,待推送完master的更新提交后立即正式发布,从而让整体流程更平滑。

版本号的确定与发布博文脚手架

稳定分支上更新版本号前,需要先确定正确的目标版本。可参考 releasing-a-new-version.md 给出的判读规则:先查看 History.markdown 中## HEAD小节的内容——

  • 若含Major Enhancements子节:递增主版本,次版本与补丁版本归零(如"3.9.1" => "4.0.0"),预发布可加后缀;
  • 若含Minor Enhancements子节:仅递增次版本,补丁版本归零(如"4.0.2" => "4.1.0");
  • 其余情况(Bug FixesSecurity Fixes等):仅递增补丁版本(如"4.0.2" => "4.0.3")。

稳定分支上的安全补丁发布通常落在第三种情况,例如在3.9-stable上把3.9.4递增为3.9.5

若发布博文尚未起草,可用仓库内置的 rake 任务生成脚手架:

bundle exec rake site:releases:new[3.9.5]

site.rake 中的site:releases:new任务 会在docs/_posts/下按YYYY-MM-DD-jekyll-3-9-5-released.markdown命名创建博文,并预填titledateversioncategory: release等 front matter。随后撰写正文时,感谢名单可用提交日志命令生成(v3.9.4为上一个发布 tag):

git shortlog -sn master...v3.9.4

完成后为该博文开启 pull request,等待前述阶段二的合并步骤。

流程小结

阶段所在分支关键动作自动化程度
触发发布*-stableversion.rb、更新History.markdown、暂存片段、提交推送推送后由 CI 构建 gem
发布博文master合并 release post 的 pull request
更新默认分支master回填 History、可选改版本号、rake site:generate、提交推送元文件由 rake 生成
发布 GitHub ReleaseWeb手动为稳定分支 tag 创建 Release,正文用暂存片段机器人不覆盖非默认分支

整个流程的核心风险点有两个:一是在稳定分支上误跑rake site:generate(会把不该出现在该分支的元文件改动混入提交),二是 History 片段回填时放错位置(必须遵守"时间倒序 + 按主版本归类"的双层排序规则)。只要牢记"稳定分支只改版本与历史、master负责一切站点元文件与记录回填"的分工,回溯发布就能安全完成。

【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询