⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
发布周期

本文概述了 DuckDB 及其核心扩展的发布周期框架。旨在帮助从事 DuckDB 扩展开发的开发者更好地理解相关流程。

概览

  • DuckDB 遵循 语义化版本控制 (v<MAJOR>.<MINOR>.<PATCH>)
  • 小版本(Minor versions)大约每 4 个月发布一次
  • 补丁版本(Patch releases)根据需要针对以下情况发布:
    • 最新的稳定版本
    • 当前的长期支持(LTS)版本
  • 所有发布版本均列于 发布日历

术语

在发布文档中,我们使用一些基本术语来描述版本和分支。此处作简要说明。

  • 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 或 n >= 0 的 vx.<y+n>-codename
  • Single branch extension(单分支扩展): 只有一个活跃分支的扩展。由于 main 始终是活跃分支,因此这种情况通常指 main。这意味着格式为 vx.y-codename 的所有其他分支必须是 n >= 1 的 vx.<y-n>-codename
  • Multi branch extension(多分支扩展): 具有一个以上活跃分支的扩展
  • Two branch extension(双分支扩展): 具有两个活跃分支的扩展:main 和 vx.y-codename
  • Three branch extension(三分支扩展): 具有三个活跃分支的扩展:main、vx.y-codenamevx.<y+1>-codename
  • LTS release(长期支持版本): 长期支持版本。这些版本在其活跃发布周期结束之后仍将获得支持(补丁版本)。目前 LTS 版本将获得 1 年的支持
  • Unstable API extension(不稳定 API 扩展): 针对不稳定扩展 API 的扩展。这可以是 C++ API 或不稳定的 C API。这些扩展在不同的 DuckDB 版本之间不具备二进制兼容性
  • Stable API extension(稳定 API 扩展): 针对 DuckDB 稳定 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(长期支持)版本遵循单独的维护周期,以提供扩展的支持和稳定性。

DuckDB 主发布周期由 3 个主要阶段组成:周期中期 (Mid-cycle)预发布 (Pre-release)功能冻结 (Feature freeze)。这些阶段定义明确且经过沟通,以确保整个团队同步并共同推进下一次发布。

阶段 1:周期中期 (Mid-Cycle)

活跃的 DuckDB 分支

  • main
  • vx.y-codename

描述

周期中期是发布周期中最常见的阶段,大约 75% 的时间处于此阶段。这可以看作是日常工作状态,距离即将到来的发布还有很长时间,团队正在努力合并各种功能和错误修复。在此阶段,补丁版本(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

阶段 2:预发布 (Pre-Release)

活跃分支

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

描述

预发布阶段旨在为即将到来的 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

阶段 3:功能冻结 (Feature Freeze)

活跃分支

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

描述

功能冻结阶段是发布前的最后一个阶段。在此阶段,不允许再将新功能合并到 vx.<y+1>-codename,仅允许合并错误修复。此阶段旨在确保即将发布版本的质量。在此阶段,团队会进行额外的测试和基准测试,同时通过禁止功能合并来降低引入临时错误的风险。

DuckDB 的 PR 合并规则

  • 不再允许针对 vx.y.<z+1> 的错误修复,应改为针对 vx.<y+1>.0
  • vx.<y+1>.0 的错误修复合并到 vx.<y+1>-codename
  • 不再允许针对 vx.<y+1>.0 的功能合并,应改为针对 vx.<y+2>.0
  • vx.<y+2>.0 的功能合并到 vx.<y+2>-codename

扩展的主发布周期

大多数 DuckDB 扩展与主 duckdb/duckdb 仓库完全独立,可以自由遵循自己的发布周期。在本节中,我们将 DuckDB 扩展归类,并讨论它们的发布周期。

为了描述扩展的发布周期,我们需要首先将扩展分为三类,因为扩展共享的发布周期取决于它们所属的类别。

  • 树内扩展 (In-tree extensions)
  • 不稳定 API 扩展 (Unstable API extensions)
  • 稳定 API 扩展 (Stable API extensions)

现在,我们将按照复杂性增加的顺序介绍这三类扩展的发布周期。

树内扩展

对于树内扩展,发布周期非常简单。由于其代码存在于 duckdb/duckdb 仓库中,它们与 DuckDB 保持完全同步。这意味着它们共享相同的版本控制和分支。从这个意义上讲,它们并不是真正的扩展,更多是 duckdb/duckdb 代码库中可延迟加载的部分。

稳定 API 扩展

稳定 API 扩展在 DuckDB 中是一个相对较新的概念,但计划在未来成为大多数扩展的形式。稳定 API 扩展建立在稳定的 C 扩展 API 之上,使其与多个版本的 DuckDB 二进制兼容。这意味着它们的发布周期可以/应该完全独立于 DuckDB 的发布周期。

虽然稳定 API 扩展的发布周期仍在完善中,但基本思路是其发布周期由一个与 duckdb/duckdb 类似但独立的周期组成,其中每个版本将针对一个或多个 DuckDB 版本。

不稳定 API 扩展

不稳定 API 扩展目前占 DuckDB 扩展的大多数。这些扩展要么针对 C++ 扩展 API,要么针对不稳定 C 扩展 API。从发布周期的角度来看,它们是最复杂的。不稳定 API 扩展的每个版本仅针对单个 DuckDB 版本。这种 1:1 的绑定关系意味着这些扩展的发布周期往往需要在主 DuckDB 发布周期周围进行复杂的协调。虽然目标是将尽可能多的扩展迁移到稳定 API,但我们预计不稳定 API 扩展在相当长一段时间内仍将存在,因此有必要明确定义其生命周期。因此,我们将利用本节的其余部分进行详细描述。

按分支分类

首先,我们将不稳定 API 扩展划分为不同的子类别。正如 DuckDB 本身一样,这些扩展遵循与 DuckDB 相同的分支方案,其中 mainvx.y-codename 的组合起着主要作用。我们现在通过查看其活跃分支的数量来定义三种类型的不稳定扩展。

  • 单分支扩展 仅具有 main 活跃分支
  • 双分支扩展 具有两个活跃分支:mainvx.y-codename
  • 三分支扩展 具有三个活跃分支:mainvx.y-codenamevx.<y+1>-codename

DuckDB 目标版本

每个不稳定 API 扩展都应针对单个 DuckDB 版本。此目标版本由 duckdb 子模块MainDistributionPipeline 工作流中的目标版本共同决定。扩展针对的版本取决于发布阶段和分支。我们现在讨论所有组合。

  • 阶段:周期中期 (Mid-cycle)
    • 类型:单分支
      • 扩展 main -> DuckDB vx.y.zmain
    • 类型:双分支
      • 扩展 main -> DuckDB vx.y.zmain
      • 扩展 vx.y-codename -> DuckDB vx.y.zvx.y-codename
    • 类型:三分支:不应存在
  • 阶段:预发布 (Pre-release) / 补丁 (Patch)
    • 类型:单分支
      • 扩展 main -> DuckDB vx.y.zvx.<y+1>-codename
    • 类型:双分支
      • 扩展 main -> DuckDB vx.y.zvx.<y+1>-codename
      • 扩展 vx.y-codename -> DuckDB vx.y.zvx.y-codename
    • 类型:三分支
      • 扩展 main -> DuckDB main
      • 扩展 vx.y-codename -> DuckDB vx.y.zvx.y-codename
      • 扩展 vx.<y+1>-codename -> DuckDB vx.<y+1>-codename

PR 合并位置

知道将 PR 合并到不稳定 API 扩展的位置取决于两件事:当前的发布阶段和扩展类型。我们现在讨论所有组合。

  • 阶段:周期中期 (Mid-cycle)
    • 类型:单分支
      • 如果 DuckDB 目标为:vx.y.z
        • 针对 vx.y.<z+1> 的 PR 合并到 main1
        • 针对 vx.<y+1>.0 的 PR 合并到 main
      • 如果 DuckDB 目标为:main
        • 针对 vx.y.<z+1> 的 PR 是不可能的
        • 针对 vx.<y+1>.0 的 PR 合并到 main
    • 类型:双分支
      • 针对 vx.y.<z+1> 的 PR 合并到 vx.y-codename
      • 针对 vx.<y+1>.0 的 PR 合并到 main
    • 类型:三分支
      • 针对 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)
    • 类型:单分支
      • 如果 DuckDB 目标为:vx.y.z
        • 针对 vx.y.<z+1> 的 PR 合并到 main1 2
        • 针对 vx.<y+1>.0 的 PR 合并到 main
      • 如果 DuckDB 目标为:main
        • 针对 vx.y.<z+1> 的 PR 是不可能的
        • 针对 vx.<y+1>.0 的 PR 合并到 main
    • 类型:双分支
      • 针对 vx.y.<z+1> 的 PR 合并到 vx.y-codename 2
      • 针对 vx.<y+1>.0 的 PR 合并到 main
    • 类型:三分支
      • 针对 vx.y.<z+1> 的 PR 合并到 vx.y-codename2
      • 针对 vx.<y+1>.0 的 PR 合并到 vx.<y+1>-codename
      • 针对 vx.<y+2>.0 的 PR 合并到 main

改为针对小版本发布。

将发布什么版本的扩展?

每次 DuckDB 发布时,都应提供一套完整的所有核心扩展。对于不稳定 API 扩展,这意味着需要重新构建二进制文件。对于核心扩展,此构建通常通过 duckdb/duckdb CI 进行。这意味着发布时将提供的扩展列表记录在 扩展配置文件 中。但是,此配置文件可能并非总是最新的。为了决定扩展的哪个版本应包含在即将到来的版本中,我们基于发布类型(大/小版本)和扩展类型(单/多分支)定义了以下用于确定最新扩展版本的“事实来源”:

  • 发布类型:补丁 (Patch)
    • 扩展类型:单分支
    • 扩展类型:多分支
      • 最新版本:扩展的 vx.y-codename 分支
  • 发布类型:小版本 (Minor)
    • 扩展类型:单分支
      • 最新版本:扩展的 main 分支
    • 扩展类型:双分支
      • 最新版本:扩展的 main 分支
    • 扩展类型:三分支
      • 最新版本:扩展的 vx.<y+1>-codename 分支

在单分支、双分支和三分支之间切换

在不同的扩展分支类型之间切换是一个相当简单的过程,应按如下方式进行:

  • 切换:单分支 -> 双分支
    • 时间:在任何阶段
    • 原因
      • 当希望合并不符合 vx.y.<z+1> 标准的功能,同时又需要保持为 vx.y.<z+n> 进行发布的能力时
      • 为了能够使用最新的 DuckDB main 进行测试,同时保持为 vx.y.<z+n>(包括 vx.y.z 本身)进行发布的能力
    • 操作
      • main 分支的某个提交点创建 vx.y-codename 分支,该提交点介于 main 的 HEAD 与 DuckDB vx.y.z 配置文件中的提交之间。
  • 切换:双分支 -> 三分支
    • 时间:在预发布 (Pre-release)功能冻结 (Feature-freeze) 阶段
    • 原因
      • 每当需要合并一个不符合合并到 vx.<y+1>.0 标准的功能时。
    • 操作
      • 从 main 创建 vx.<y+1>-codename 分支
  • 切换:三分支 -> 双分支双分支 -> 单分支
    • 时间:作为从 功能冻结 (Feature Freeze) -> 周期中期 (Mid-cycle) 过渡的一部分
    • 操作:自动发生(vx.y-codename 定义上变为不活跃
  1. 单分支扩展需要手动更新版本,以确保更改包含在目标发布版本中。  2

  2. 在预发布或功能冻结阶段进行补丁发布是不常见的。考虑将更改目标定为下一个版本。  2 3

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南