구형 Discourse 설치에서 플러그인 및 테마 버전 고정 (d-compat 브랜치)

:open_book: 배경

테마 및 플러그인 개발자는 일반적으로 Discourse의 latest 릴리스를 대상으로 개발하되, 하위 호환성에 대해 걱정하지 않으려는 경향이 있습니다. 하지만 구버전 Discourse를 실행 중인 사이트들은 해당 환경에서 작동하는 테마/플러그인 버전이 여전히 필요합니다.

이 간극을 메우기 위해, Discourse에 테마/플러그인의 이전 ‘고정(pinned)’ 버전을 체크아웃하도록 지시할 수 있습니다. 이를 위한 두 가지 메커니즘이 있으며, 순서대로 확인됩니다:

  1. 테마/플러그인 저장소 내 d-compat/<YYYY>.<M> git 브랜치 (주요 방법 — 모든 새로운 고정(pinning)에 권장됨).
  2. 저장소 루트 디렉터리에 있는 .discourse-compatibility YAML 파일 (원래 메커니즘이며, 여전히 폴백으로 지원됨).

두 가지가 모두 존재하는 경우, 브랜치가 우선합니다.

:herb: d-compat/<YYYY>.<M> 브랜치 시스템

Discourse 릴리스는 2025.5, 2025.6과 같은 날짜 기반 버전을 사용합니다. Discourse가 git에서 플러그인이나 테마를 업데이트할 때 저장소에 "내 버전과 일치하는 d-compat/<YYYY>.<M> 이름의 브랜치가 있습니까?"라고 질문합니다 (예: Discourse 2025.5.x의 경우 d-compat/2025.5). 해당 브랜치가 있으면, Discourse는 main 대신 해당 브랜치의 끝(tip)을 체크아웃합니다.

이 조회는 로컬 체크아웃이 저장소의 기본 브랜치에 있을 때만 실행됩니다. 다른 브랜치로 의도적으로 고정했다면, d-compat 로직은 건너뛰고 사용자의 고정이 존중됩니다.

이 시스템으로 이전 Discourse 버전을 지원하려면:

  1. 해당 버전에서 정상 동작이 확인된 커밋에서 d-compat/<YYYY>.<M> 이름의 브랜치를 생성합니다 (예: git checkout -b d-compat/2025.5 <commit>).
  2. origin에 푸시합니다. 브랜치가 실수로 삭제되는 것을 방지하기 위해 브랜치를 보호하는 것이 좋습니다.
  3. 백포트된 커밋을 해당 브랜치에 반영합니다. 2025.5.x를 실행 중인 Discourse 인스턴스는 다음 업데이트 시 자동으로 이를 가져오게 되며, 더 새로운 Discourse를 실행 중인 인스턴스는 기본 브랜치를 계속 추적합니다.

브랜치를 사용할 때 .discourse-compatibility 파일에 대해 전혀 수정할 필요가 없습니다.

:gear: 자동 브랜치 생성 (create-d-compat-branch.yml)

실제로는 이러한 브랜치를 수동으로 생성할 필요가 거의 없습니다. 기본 테마 및 플러그인 스켈레톤에는 Discourse 코어 새 버전을 확인하고 필요한 경우 일치하는 d-compat/<YYYY>.<M> 브랜치를 푸시하는 일일 실행 워크플로우인 d-compat-branch.yml 워크플로우가 포함되어 있습니다.

저장소가 구버전 스켈레톤에서 생성된 경우, 작동하도록 하려면 d-compat-branch.yml 파일을 .github/workflows 디렉터리에 복사하기만 하면 됩니다.

:git_merged: 수정 사항을 d-compat 브랜치에 백포트하기

기본 브랜치에 수정 사항을 반영했는데, 이전 Discourse 릴리스를 사용하는 사이트에도 해당 수정 사항이 필요할 경우:

  1. 대상 d-compat 브랜치에서 분기(branch)하고 수정 사항을 체리픽(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. 베이스 브랜치d-compat/2025.5로 설정하여 PR을 엽니다 (main이 아닙니다). 다른 PR과 동일한 방식으로 검토 및 병합을 진행합니다.

  3. 수정 사항이 필요한 각 이전 d-compat/<YYYY>.<M> 브랜치에 대해 이 과정을 반복합니다.

2025.5.x를 실행 중인 사이트는 다음 업데이트 시 병합된 커밋을 가져오게 됩니다.

레거시 폴백: `.discourse-compatibility` 파일

일치하는 d-compat 브랜치가 없으면, Discourse는 저장소 루트에 있는 YAML .discourse-compatibility 파일로 폴백하여, Discourse 버전을 플러그인/테마의 git ref로 매핑합니다:

< 3.2.0.beta2-dev: abcde

Discourse는 실행 중인 코어 버전과 일치하는 가장 낮은 항목을 선택하므로, < 3.2.0.beta2-dev를 실행 중인 모든 사용자는 커밋 abcde를 체크아웃하게 됩니다. 버전 경계를 지정하려면 < (또는 연산자가 지정되지 않은 경우 기본값인 레거시 <=)를 사용합니다. 이는 브랜치 기반 시스템으로 원하는 것을 표현할 수 없는 경우에만 사용하세요.


이 문서는 버전 관리됩니다 - 변경 사항을 github에서 제안해 주세요.

17개의 좋아요

If the version is < 3.5.0.beta8-dev, would it include 3.5.0?

No. 3.5.0 is considered “higher” than the prerelease version “3.5.0.beta8-dev”.

You can always try out comparisons on a ruby console:

> Gem::Version.new("3.5.0") < Gem::Version.new("3.5.0.beta8-dev")
=> false
5개의 좋아요

Understood. Thanks for the explanation!

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이 여전히 Discourse에서 지원되는 동안 플러그인을 새로운 ESR(2026.7)으로 이동할 때, 다음 브랜치를 생성해야 하나요?

  • 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가 main 브랜치를 가정하는 대신 가장 적합한 브랜치를 찾나요?

예를 들어, 2026.5를 실행 중이고 유일한 브랜치가 d-compat/2026.1d-compat/2026.6인 경우, 어떤 브랜치가 사용되나요?

  1. 가장 가까운 호환 버전인 d-compat/2026.1?
  2. 특정 브랜치가 없으므로 main?
1개의 좋아요

네, Discourse 코어 버전마다 하나의 브랜치가 필요합니다. 브랜치 생성을 자동화하는 것을 권장합니다:

main이 사용됩니다.

2개의 좋아요