Фиксация версий плагинов и тем для старых установок Discourse (ветки d-compat)

:open_book: Предыстория

Разработчики тем и плагинов обычно стремятся ориентироваться на релиз latest версии Discourse, не беспокоясь о обратной совместимости. Однако сайты, работающие на более старых версиях Discourse, всё ещё нуждаются в версии темы/плагина, которая будет для них работать.

Чтобы заполнить этот пробел, можно настроить Discourse на использование более старой «закреплённой» версии темы или плагина. Для этого существуют два механизма, проверяемые в следующем порядке:

  1. Гит-ветки d-compat/<YYYY>.<M> в репозитории темы/плагина (основной метод — рекомендуется для всех новых закреплений).
  2. YAML-файл .discourse-compatibility в корне репозитория (исходный механизм, всё ещё поддерживается как запасной вариант).

Если существуют оба, приоритет отдаётся ветке.

:herb: Система веток d-compat/<YYYY>.<M>

Релизы Discourse используют версии на основе дат, такие как 2025.5, 2025.6 и т. д. Когда Discourse обновляет плагин или тему из git, он спрашивает репозиторий: «есть ли у вас ветка с именем d-compat/<YYYY>.<M>, соответствующая моей версии?» (например, d-compat/2025.5 для Discourse 2025.5.x). Если такая ветка есть, Discourse проверяет её последнюю версию вместо ветки main.

Поиск выполняется только в том случае, если локальная проверка находится на ветке по умолчанию репозитория. Если вы намеренно закрепились на другой ветке, логика d-compat пропускается, и ваше закрепление учитывается.

Чтобы поддержать старую версию Discourse с помощью этой системы:

  1. Создайте ветку с именем d-compat/<YYYY>.<M> из коммита, который, как известно, работает в этой версии (например, git checkout -b d-compat/2025.5 <commit>).
  2. Отправьте её в origin. Возможно, стоит защитить ветку от случайного удаления.
  3. Внесите любые коммиты с обратным портированием в эту ветку. Экземпляры Discourse на версии 2025.5.x автоматически подхватят их при следующем обновлении; экземпляры на более новых версиях 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-ссылками вашего плагина/темы:

< 3.2.0.beta2-dev: abcde

Discourse выбирает наименьшую запись, соответствующую работающей версии ядра, поэтому пользователи версии < 3.2.0.beta2-dev будут проверять коммит abcde. Используйте < (или устаревший <=, который используется по умолчанию, если оператор не указан) для указания границы версии. К этому методу стоит прибегать только в том случае, если система на основе веток не может выразить то, что вам нужно.


Этот документ находится под версионным контролем — предложите изменения на GitHub.

17 лайков

Если версия < 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 лайк

Этот документ обновлён для описания новой стратегии d-compat/* из RFC: A new versioning strategy for Discourse, которая теперь доступна для использования.

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, но пользователи могут всё ещё ими пользоваться.

Или Discourse находит наиболее подходящую ветку, если нужная отсутствует, вместо того чтобы предполагать использование главной ветки?

Например, если я использую версию 2026.5, а существуют только ветки d-compat/2026.1 и d-compat/2026.6. Какая ветка будет использована?

  1. d-compat/2026.1, как ближайшая совместимая версия?
  2. main, поскольку нет конкретной ветки?
1 лайк

Да, для каждой версии ядра Discourse требуется отдельная ветка. Мы рекомендуем автоматизировать их создание:

Будет использована ветка main.

2 лайка