릴리스 주기

릴리스 주기 (Release Cycle)

이 문서는 DuckDB와 핵심 확장의 릴리스 주기 프레임워크를 설명해요. DuckDB 확장에서 작업하는 개발자가 기본 프로세스를 더 잘 이해하도록 돕기 위한 것이에요.

출처: 문서

본문

개요 (Overview)

  • DuckDB는 시맨틱 버저닝(v<MAJOR>.<MINOR>.<PATCH>)을 따르는.
  • 마이너 버전은 대략 4개월마다 릴리스돼요
  • 패치 릴리스는 필요에 따라 발행돼요:
    • 최신 안정 버전
    • 현재 Long Term Support (LTS) 버전
  • 모든 릴리스는 [Release Calendar]({% link release_calendar.md %})에 나열돼요

용어 (Terminology)

릴리스 문서에서 버전과 브랜치를 설명하는 데 사용하는 기본 용어가 있어요. 여기서 간단히 살펴볼게요.

  • vx.y.z: 최신 안정 릴리스
  • vx.y-codename: vx.y.<n> 릴리스를 생산할 브랜치의 이름
  • vx.<y+1>-codename: 다음 마이너 릴리스를 생산할 브랜치에 사용되는 브랜치 이름
  • Main release cycle: vx.<y+1>.0vx.y.<z+1> 릴리스를 생산하는 데 관련된 브랜치, 커밋, PR
  • Active branch: main 릴리스 주기의 일부인 브랜치. main 또는 vx.<y+n>-codename (n >= 0)
  • Single branch extension: 활성 브랜치가 1개인 확장. main은 항상 활성 브랜치이므로 이것은 항상 main이에요. 즉 vx.y-codename 형식의 다른 모든 브랜치는 vx.<y-n>-codename (n >= 1)이어야 해요
  • Multi branch extension: 활성 브랜치가 2개 이상인 확장
  • Two branch extension: main과 vx.y-codename 두 개의 활성 브랜치를 가진 확장
  • Three branch extension: main, vx.y-codename, vx.<y+1>-codename 세 개의 활성 브랜치를 가진 확장
  • LTS release: Long term support 릴리스. 활성 릴리스 주기에서의 수명을 넘어 지원(패치 릴리스)을 받을 것. 현재 LTS 릴리스는 1년 지원을 받아요
  • Unstable API extension: unstable 확장 API를 대상으로 하는 확장. C++ API 또는 unstable C API일 수 있어요. 이 확장들은 여러 DuckDB 버전에서 바이너리 호환되지 않아요
  • Stable API extension: DuckDB의 stable C API를 대상으로 하는 확장. 여러 DuckDB 버전에서 바이너리 호환돼요
  • In-tree extensions: duckdb/duckdb 소스 트리 안에 사는 확장

주요 브랜치와 태그

git 기반 버전 관리에서 브랜치는 같은 코드베이스의 여러 버전이 공존하도록 하는 데 사용돼요. DuckDB에는 DuckDB(과 확장) 릴리스 주기에서 주요 역할을 하는 두 개의 핵심 브랜치가 있어요. 이 핵심 브랜치들이 오는 형식을 나열하는 것부터 시작할게요.

  • main 브랜치: main 브랜치는 여러 의미일 수 있지만 일반적으로 만능 브랜치로 간주할 수 있어요
  • vx.y-codename 브랜치: 모든 vx.y.z 릴리스를 생산하는 데 사용되는 브랜치
  • vx.y.z 태그: DuckDB의 안정 릴리스. 이 태그는 쓰기 전용이며 항상 같은 커밋에 묶여요

메인 DuckDB 릴리스 주기

LTS(Long-Term Support) 릴리스는 확장된 지원과 안정성을 제공하기 위한 별도의 유지보수 주기를 따르는.

메인 DuckDB 릴리스 주기는 Mid-cycle, Pre-release, Feature freeze의 3가지 주요 단계로 구성돼요. 이 단계는 명확히 정의되고 전달되며, 전체 팀이 동기화되어 다음 릴리스를 향해 함께 작업하도록 보장해요.

Phase 1: Mid-Cycle

활성 DuckDB 브랜치

  • main
  • vx.y-codename

설명

mid-cycle 단계는 릴리스 주기의 가장 흔한 단계로, 시간의 약 75%가 이 단계에서 보내져요. 다가오는 릴리스가 아직 먼 business-as-usual로 볼 수 있고, 팀이 다양한 기능과 버그픽스를 병합하는 데 열심히 작업하는 시기예요. 이 단계에서 패치 릴리스(vx.y.<z+n>)는 vx.y-codename 브랜치에서 만들어질 수 있어요. 패치는 vx.y-codename 브랜치에 병합되고, vx.y-codename 브랜치는 둘을 동기화하기 위해 자주 main에 병합돼요.

DuckDB로의 PR

  • vx.y.<z+n> 패치 릴리스를 위한 버그픽스는 vx.y-codename에 병합돼요
  • vx.<y+1>.0을 위한 기능과 버그픽스는 main에 병합돼요

Phase 2: Pre-Release

활성 브랜치

  • main
  • vx.y-codename
  • vx.<y+1>-codename

설명

pre-release 단계는 다가오는 vx.<y+1>.0 마이너 릴리스를 준비하기 위한 것이에요. 이 단계 시작에 vx.<y+1>-codename 브랜치가 생성돼요. 이 브랜치는 다가오는 마이너 릴리스를 생산하는 데 사용되고, 이후 모든 vx.<y+1>.<n> 패치 릴리스가 릴리스되는 브랜치예요.

DuckDB로의 PR

  • vx.y.<z+1> 패치 릴리스를 위한 버그픽스는 vx.y-codename에 병합돼요
  • vx.<y+1>.0을 위한 기능과 버그픽스는 vx.<y+1>-codename에 병합돼요
  • vx.<y+2>.0을 위한 기능은 vx.<y+2>-codename에 병합돼요

Phase 3: Feature Freeze

활성 브랜치

  • main
  • vx.y-codename
  • vx.<y+1>-codename

설명

feature freeze 단계는 릴리스에 가장 가까운 단계예요. 이 단계에서는 더 이상 기능이 vx.<y+1>-codename에 병합될 수 없고 버그픽스만 병합돼요. 이 단계는 다가오는 릴리스의 품질을 보장하기 위한 것이에요. 이 단계에서 추가 테스트와 벤치마킹이 수행되며 새 기능을 도입할 위험을 줄여요.

메인 확장 릴리스 주기 (Main Extension Release Cycle)

대부분의 DuckDB 확장은 duckdb/duckdb 저장소와 완전히 분리되어 있고 자체 릴리스 주기를 따를 수 있어요. 이 섹션에서 다양한 종류의 DuckDB 확장을 분류하고 그 릴리스 주기를 살펴볼게요.

확장의 릴리스 주기를 설명하려면 먼저 확장을 세 그룹으로 분류해야 해요. 확장은 이 세 범주 중 어디에 속하느냐에 따라 릴리스 주기를 공유하기 때문이에요.

  • In-tree 확장
  • Unstable API 확장
  • Stable API 확장

이제 복잡성이 증가하는 순서로 세 범주의 릴리스 주기를 살펴볼게요.

In-Tree 확장

in-tree 확장의 릴리스 주기는 매우 간단해요. 코드가 duckdb/duckdb 저장소에 있으므로 DuckDB와 완전히 함께 움직여요. 즉 같은 버저닝과 브랜칭을 공유한다는 뜻이에요. 이런 의미에서 진짜 확장이라기보다 duckdb/duckdb 코드베이스의 지연-로드 가능한 부분에 가까워요.

Stable API 확장

DuckDB의 stable API 확장은 비교적 새로운 개념이지만, 앞으로 확장의 대부분을 형성할 계획이에요. Stable API 확장은 stable C 확장 API를 기반으로 구축되어 여러 버전의 DuckDB와 바이너리 호환돼요. 즉 그 릴리스 주기도 DuckDB 릴리스 주기와 완전히 분리될 수(그리고 그래야) 있어요.

Stable API 확장의 릴리스 주기는 아직 작업 중이지만, 기본 아이디어는 duckdb/duckdb의 릴리스 주기와 유사하지만 분리된 주기로 구성되며, 각 버전이 DuckDB의 1개 이상 버전을 대상으로 한다는 것이에요.

Unstable API 확장

Unstable API 확장은 현재 DuckDB 확장의 대부분을 차지해요. 이 확장들은 C++ 확장 API나 unstable C 확장 API를 대상으로 해요. 릴리스 주기 관점에서 가장 복잡해요. Unstable API 확장의 각 버전은 단일 DuckDB 버전만 대상으로 해요. 이 1:1 연결은 이 확장들의 릴리스 주기가 때로는 메인 DuckDB 릴리스 주기 주변에서 복잡한 춤을 형성하는 경향이 있다는 뜻이에요. 많은 확장을 stable API로 옮기는 것이 목표이지만, unstable API 확장이 꽤 오래 남아 있을 것으로 예상하므로 그 수명 주기를 명확히 정의할 필요가 여전히 있어요. 따라서 이 섹션의 나머지를 그 설명에 사용할게요.

브랜칭으로 분류

먼저 unstable API 확장을 하위 범주로 나눌게요. DuckDB 자체처럼, 이 확장들은 mainvx.y-codename의 조합이 주요 역할을 하는 DuckDB와 같은 브랜칭 방식을 따르는. 이제 unstable 확장의 세 유형을 활성 브랜치 수로 정의할게요.

  • Single branch 확장main 활성 브랜치만 가지고
  • Two branch 확장은 두 개의 활성 브랜치를 가져: mainvx.y-codename
  • Three branch 확장은 세 개의 활성 브랜치를 가져: main, vx.y-codename, vx.<y+1>-codename

DuckDB 대상 (DuckDB Targets)

모든 unstable API 확장은 DuckDB의 단일 버전을 대상으로 해야 해요. 이 대상 버전은 duckdb 서브모듈MainDistributionPipeline 워크플로의 대상 버전의 조합으로 정의돼요. 확장이 대상으로 하는 버전은 릴리스 주기 단계와 브랜치에 따라 달라져요. 모든 조합을 살펴볼게요.

  • 단계: Mid-cycle
    • 유형: Single branch
      • 확장 main -> DuckDB vx.y.z 또는 main
    • 유형: Two branch
      • 확장 main -> DuckDB vx.y.z 또는 main
      • 확장 vx.y-codename -> DuckDB vx.y.z 또는 vx.y-codename
    • 유형: Three branch: 없어야 함
  • 단계: Pre-release / Patch
    • 유형: Single branch
      • 확장 main -> DuckDB vx.y.z 또는 vx.<y+1>-codename
    • 유형: Two branch
      • 확장 main -> DuckDB vx.y.z 또는 vx.<y+1>-codename
      • 확장 vx.y-codename -> DuckDB vx.y.z 또는 vx.y-codename
    • 유형: Three branch
      • 확장 main -> DuckDB main
      • 확장 vx.y-codename -> DuckDB vx.y.z 또는 vx.y-codename
      • 확장 vx.<y+1>-codename -> DuckDB vx.<y+1>-codename

PR 병합 위치

PR을 unstable API 확장에 어디에 병합할지 아는 것은 두 가지에 달려 있어요: 현재 릴리스 단계와 확장 유형. 모든 조합을 살펴볼게요.

  • 단계: Mid-cycle
    • 유형: Single branch
      • DuckDB 대상: vx.y.z:
        • vx.y.<z+1> PR을 **main**으로[^1]
        • vx.<y+1>.0 PR은 **main**으로 병합
      • DuckDB 대상: main:
        • vx.y.<z+1> PR은 불가능
        • vx.<y+1>.0 PR은 **main**으로 병합
    • 유형: Two branch
      • vx.y.<z+1> PR은 **vx.y-codename**으로 병합
      • vx.<y+1>.0 PR은 **main**으로 병합
    • 유형: Three branch
      • vx.y.<z+1> PR은 **vx.y-codename**으로 병합
      • vx.<y+1>.0 PR은 **vx.<y+1>-codename**으로 병합
      • vx.<y+2>.0 PR은 **main**으로 병합
  • 단계: Pre-release / Patch
    • 유형: Single branch
      • DuckDB 대상: vx.y.z:
        • vx.y.<z+1> PR을 **main**으로[^1] [^2]
        • vx.<y+1>.0 PR은 **main**으로 병합
      • DuckDB 대상: main:
        • vx.y.<z+1> PR은 불가능
        • vx.<y+1>.0 PR은 **main**으로 병합
    • 유형: Two branch
      • vx.y.<z+1> PR은 **vx.y-codename**으로 병합 [^2]
      • vx.<y+1>.0 PR은 **main**으로 병합
    • 유형: Three branch
      • vx.y.<z+1> PR은 **vx.y-codename**으로 병합[^2]
      • vx.<y+1>.0 PR은 **vx.<y+1>-codename**으로 병합
      • vx.<y+2>.0 PR은 **main**으로 병합

[^1]: Single branch 확장은 변경 사항이 대상 릴리스에 포함되도록 수동 버전 업데이트가 필요해요. [^2]: pre-release나 feature-freeze 단계의 패치 릴리스는 드물어요. 변경 사항을 다음 마이너 릴리스를 대상으로 하길 고려해요.

어떤 확장 버전이 릴리스될까?

DuckDB 릴리스마다 모든 핵심 확장의 전체 집합이 사용 가능해야 해요. Unstable API 확장의 경우 이것은 바이너리 재빌드를 의미해요. 핵심 확장의 경우 이 빌드는 일반적으로 duckdb/duckdb CI를 통해 일어나요. 즉 릴리스 시 사용 가능한 확장 목록은 확장 구성 파일에 문서화되어 있어요. 하지만 이 구성 파일이 항상 최신일 수는 없어요. 다가오는 릴리스에 어떤 버전의 확장이 포함되어야 할지 결정하기 위해, 릴리스 타입(major/minor)과 확장 타입(single/multi branch)에 따라 최신 확장 버전에 대한 다음 source-of-truth를 정의해요:

  • 릴리스 타입: Patch
    • 확장 타입: Single branch
    • 확장 타입: Multi branch
      • 최신 버전: 확장 vx.y-codename 브랜치
  • 릴리스 타입: Minor
    • 확장 타입: Single branch
      • 최신 버전: 확장 main 브랜치
    • 확장 타입: Two branch
      • 최신 버전: 확장 main 브랜치
    • 확장 타입: Three branch
      • 최신 버전: 확장 vx.<y+1>-codename 브랜치

Single Branch, Two Branch, Three Branch 전환

확장의 브랜치 타입 전환은 비교적 간단한 프로세스이며 다음과 같이 수행해야 해요:

  • 전환: Single branch -> Two branch
    • 시점: 어느 단계에서든
    • 이유:
      • vx.y.<z+1>에 해당하지 않는 기능을 병합하려는 욕구가 생기면서 vx.y.<z+n> 릴리스 가능성을 유지하고 싶을 때
      • vx.y.<z+n>(vx.y.z 자체 포함) 릴리스 가능성을 유지하면서 최신 DuckDB main으로 테스트하고 싶을 때
    • 조치:
      • main의 HEAD와 DuckDB vx.y.z 구성 파일의 커밋 사이의 main 커밋에서 vx.y-codename 브랜치 생성.
  • 전환: Two branch -> Three branch
    • 시점: Pre-release 또는 Feature-freeze 단계에서
    • 이유:
      • vx.<y+1>.0으로 병합할 수 없는 기능을 병합해야 할 때.
    • 조치:
      • main에서 vx.<y+1>-codename 브랜치 생성
  • 전환: Three branch -> Two branch 또는 Two branch -> Single branch
    • 시점: Feature Freeze -> Mid-cycle 전환의 일부
    • 조치: 자동으로 일어난다(vx.y-codename이 정의상 비활성이 됨)

더 알아보기 (Learn more)

릴리스 일정은 [Release Calendar]({% link release_calendar.md %})를 참고해요.