为旧版 Discourse 安装固定插件和主题版本(d-compat 分支)

:open_book: 背景

主题和插件开发者通常希望针对 Discourse 的 latest 版本进行开发,而无需担心向后兼容性问题。但运行旧版 Discourse 的网站仍然需要一个适用于它们的主题/插件版本。

为了弥合这一差距,可以指示 Discourse 检出主题/插件的旧版“固定”(pinned)版本。系统会按顺序检查以下两种机制:

  1. 主题/插件仓库中的 d-compat/<YYYY>.<M> git 分支(主要方法——推荐所有新的固定版本使用此方法)。
  2. 仓库根目录下的 .discourse-compatibility YAML 文件(原始机制,仍作为后备方案受支持)。

如果两者都存在,分支优先。

:herb: d-compat/<YYYY>.<M> 分支系统

Discourse 发布版本采用基于日期的版本号,例如 2025.52025.6 等。当 Discourse 从 git 更新插件或主题时,它会向仓库询问:“你是否有与我版本匹配的名为 d-compat/<YYYY>.<M> 的分支?”(例如,针对 Discourse 2025.5.x,对应 d-compat/2025.5)。如果有,Discourse 将检出该分支的尖端(tip),而不是 main 分支。

只有当本地检出位于仓库的默认分支上时,才会执行此查找。如果你有意固定到其他分支,d-compat 逻辑将被跳过,并尊重你的固定设置。

若要使用此系统支持较旧的 Discourse 版本:

  1. 从一个已知在该版本上正常工作的提交创建一个名为 d-compat/<YYYY>.<M> 的分支(例如 git checkout -b d-compat/2025.5 <commit>)。
  2. 将其推送到 origin。你可能希望保护该分支以免被意外删除。
  3. 将任何回移(backport)提交合并到该分支。运行 2025.5.x 的 Discourse 实例将在下次更新时自动获取这些更改;而运行较新 Discourse 的实例将继续跟踪默认分支。

使用分支时,你完全不需要修改 .discourse-compatibility 文件。

:gear: 自动化分支创建(create-d-compat-branch.yml

在实际操作中,你很少需要手动创建这些分支。默认的主题和插件骨架包含一个 d-compat-branch.yml 工作流,它每天运行,检查 Discourse 核心是否有新版本,并在需要时推送相应的 d-compat/<YYYY>.<M> 分支。

如果你的仓库是从旧版骨架创建的,只需将 d-compat-branch.yml 文件复制到你的 .github/workflows 目录中即可使其生效。

:git_merged: 将修复回移到 d-compat 分支

当你在默认分支上合并了一个修复,且该修复也需要到达运行旧版 Discourse 的网站时:

  1. 从目标 d-compat 分支创建新分支并摘取(cherry-pick)该修复:

    git fetch origin
    git checkout -b backport/my-fix-2025.5 origin/d-compat/2025.5
    git cherry-pick <commit-sha>
    git push -u origin backport/my-fix-2025.5
    
  2. 打开一个 PR,并将 d-compat/2025.5 设置为基础分支(而不是 main)。像处理其他任何 PR 一样,对其进行审查并合并。

  3. 对每个需要该修复的较旧 d-compat/<YYYY>.<M> 分支重复此操作。

运行 2025.5.x 的网站将在下次更新时获取合并后的提交。

遗留后备方案:`.discourse-compatibility` 文件

如果不存在匹配的 d-compat 分支,Discourse 将回退到仓库根目录下的 YAML .discourse-compatibility 文件,该文件将 Discourse 版本映射到你插件/主题的 git 引用(refs):

< 3.2.0.beta2-dev: abcde

Discourse 会选择匹配当前运行核心版本的最低条目,因此任何运行 < 3.2.0.beta2-dev 的用户都会检出提交 abcde。使用 <(或遗留的 <=,在未指定操作符时默认为此值)来指定版本边界。仅当基于分支的系统无法表达你的需求时,才使用此方法。


本文档受版本控制 - 建议修改请提交至 github

17 个赞

如果版本是 \u003c 3.5.0.beta8-dev,它会包含 3.5.0 吗?

3.5.0 被认为“高于”预发布版本“3.5.0.beta8-dev”。

您始终可以在 Ruby 控制台中尝试比较:

> Gem::Version.new("3.5.0") < Gem::Version.new("3.5.0.beta8-dev")
=> false
5 个赞

明白了。感谢您的解释!

1 个赞

本文档已更新,以描述来自 RFC: A new versioning strategy for Discourse 的新 d-compat/* 策略,该策略现已可供使用。

5 个赞

d-compat/<YYYY>.<M> 策略是否意味着需要为每个特定版本创建一个分支?无法像 .discourse-compatibility 构造那样使用范围。

假设我正在维护一个从 ESR 到最新版本都兼容的插件。当我将开发工作迁移到新的 ESR(与旧 ESR 有重叠)时,我是否需要为每个中间版本创建分支?

例如,目前 ESR 是 2026.1,发布版是 2026.6,最新版是 2026.7,而 2026.5 仍受支持。当我将插件迁移到新的 ESR(2026.7),而旧 ESR 仍受 Discourse 支持时,我是否需要创建以下分支:

  • d-compat/2026.1
  • d-compat/2026.2
  • d-compat/2026.3
  • d-compat/2026.4
  • d-compat/2026.5
  • d-compat/2026.6

其中 .2 到 .5(含)已由 Discourse 停止支持(EOL),但用户可能仍在使用。

或者,如果缺少某个分支,Discourse 是否会寻找最合适的分支,而不是默认使用主分支?

例如,如果我运行的是 2026.5,而仅有的分支是 d-compat/2026.1d-compat/2026.6。会使用哪个分支?

  1. d-compat/2026.1,即最接近的兼容版本?
  2. main,因为没有特定的分支?
1 个赞

是的,Discourse 核心版本的每个版本都需要一个分支。我们建议自动化创建这些分支:

将使用 main 分支。

2 个赞