扩展版本管理
扩展版本管理
大多数软件都有版本号。版本号主要用于以下目标:
- 将二进制绑定到源码的特定状态
- 判断预期功能集合
- 判断 API 状态
- 更高效地处理缺陷报告(如 bug
#1337在v3.4.5引入) - 判断版本发布时间顺序(如
v1.2.3早于v1.2.4) - 反映大致稳定性预期(如
v0.0.1通常不稳定,v13.11.0往往更稳定)
和 Goose 本体一样,Goose 扩展也有独立版本号。为保证不同扩展间版本语义一致,Goose 的核心扩展采用统一版本方案,包含 3 个稳定性层级:unstable、pre-release、stable。 下面依次说明三种层级与其格式:
Unstable 扩展
Unstable 扩展是指当前稳定性无法(或不愿)给出保证,或尚无明确稳定化目标的扩展。Unstable 扩展使用扩展源码的短 git hash 作为版本标识。
例如在撰写本文时,vss 扩展属于 unstable,版本为 690bfc5。
使用 unstable 版本格式的扩展通常意味着:
- 可通过扩展仓库中的该 hash 定位对应源码状态
- 功能在每次发布时都可能变化或被移除
- API 可能在每次发布时变化
- 可能不遵循固定发布节奏,破坏性版本可能随时发布
Pre-Release 扩展
Pre-release 扩展是 unstable 之上的阶段。其版本使用 SemVer,更具体地说是 v0.y.z 格式。
在语义化版本中,以 v0 开头有特殊含义:表示正式(>v1.0.0)版本的更严格语义尚未完全适用。即该扩展正朝稳定版本演进,但尚未完全稳定。
例如在撰写本文时,delta 扩展属于 pre-release,版本为 v0.1.0。
使用 pre-release 版本格式的扩展通常意味着:
- 扩展由对应 tag 的源码构建
- 适用语义化版本规则,详见 Semantic Versioning
- 遵循发布流程:新特性先在 nightly 测试,再合并发布并推送到
core仓库 - 通常有发布说明,帮助理解版本差异
Stable 扩展
Stable 扩展是稳定性的最终阶段,使用 stable SemVer 格式 vx.y.z(其中 x>0)。
例如在撰写本文时,parquet 扩展属于 stable,版本为 v1.0.0。
使用 stable 版本格式时,整体预期与 pre-release 类似,但适用更严格 SemVer 规则:扩展 API 应保持稳定,仅在主版本号提升时才允许不向后兼容变更。 详情参见 SemVer 规范。
Pre-Release 与 Stable 核心扩展的发布周期
一般来说,扩展发布周期取决于稳定性级别。unstable 扩展通常与 Goose 发布周期同步,但也可能在两个 Goose 版本间静默更新。pre-release 与 stable 扩展遵循各自发布节奏,可能与 Goose 发布一致,也可能不一致。要了解某扩展具体发布周期,请查看其文档或 GitHub 页面。通常 pre-release 与 stable 扩展会以 GitHub releases 形式发布,例如 delta 扩展。
最后有个小例外:所有 in-tree 扩展都直接跟随 Goose 发布周期。
Nightly 构建
和 Goose 本体一样,Goose 核心扩展也有 nightly/dev 构建,可用于在正式发布前试用新功能。 当你的工作流依赖某新特性,或需要验证与即将发布版本的兼容性时,这很有价值。
扩展 nightly 的使用稍复杂,因为当前 Goose 扩展二进制与 Goose 版本强绑定。由于这种耦合,可能出现组合爆炸风险,因此并非所有“nightly 扩展 + nightly Goose”的组合都可用。
总体有两种使用 nightly 的方式:配合稳定版 Goose,或配合 nightly Goose。下面分别说明:
在 Stable Goose 上使用
多数情况下,用户只想使用某个扩展的 nightly,而不想切换 Goose 本体到 nightly。这样可以获取特定前沿特性,同时降低接触不稳定代码的范围。
为此,Core Extensions 通常会定期将构建推送到 core_nightly 仓库。示例如下:
先安装稳定版 Goose。
然后可这样安装并加载 nightly 扩展:
INSTALL aws FROM core_nightly;
LOAD aws;
在该示例中,我们使用的是 aws 扩展最新 nightly 构建,搭配 Goose 最新 stable 版本。
在 Nightly Goose 上使用
当 Goose CI 产出 Goose 本体 nightly 二进制时,会搭配一组固定版本的扩展一起分发。这些扩展版本已针对该 Goose 构建测试,但不一定是最新 dev 版本。示例如下:
先安装 nightly Goose 构建。然后按常规安装并加载 aws 扩展:
INSTALL aws;
LOAD aws;
更新扩展
Goose 提供专用语句自动将所有扩展更新到最新版本。输出会展示哪些扩展发生更新,以及更新前后版本。例如:
UPDATE EXTENSIONS;
| extension_name | repository | update_result | previous_version | current_version |
|---|---|---|---|---|
| httpfs | core | NO_UPDATE_AVAILABLE | 70fd6a8a24 | 70fd6a8a24 |
| delta | core | UPDATED | d9e5cc1 | 04c61e4 |
| azure | core | NO_UPDATE_AVAILABLE | 49b63dc | 49b63dc |
| aws | core_nightly | NO_UPDATE_AVAILABLE | 42c78d3 | 42c78d3 |
注意 Goose 会在各扩展对应来源仓库中查找更新。若扩展来自 core_nightly,将更新为最新 nightly 构建。
更新语句也可指定仅更新部分扩展:
UPDATE EXTENSIONS (httpfs, azure);
| extension_name | repository | update_result | previous_version | current_version |
|---|---|---|---|---|
| httpfs | core | NO_UPDATE_AVAILABLE | 70fd6a8a24 | 70fd6a8a24 |
| azure | core | NO_UPDATE_AVAILABLE | 49b63dc | 49b63dc |
目标 Goose 版本
当前扩展在编译时会绑定特定 Goose 版本。也就是说,例如为 0.10.3 编译的扩展二进制不能直接用于 1.0.0。多数情况下这对用户是透明的:Goose 会自动安装与自身版本匹配的二进制。对扩展开发者而言,这意味着每次 Goose 发布新版本时都需产出新二进制。好在 Goose 提供了 extension template 简化此流程。
In-Tree 与 Out-of-Tree
最初 Goose 扩展全部位于主仓库 github.com/kumose/goose,这类称为 in-tree。后来引入 out-of-tree 概念,即扩展拆分到各自独立仓库。
从用户视角通常差异不明显,但在版本管理上有一些细微区别:
- in-tree 扩展使用 Goose 版本,不单独维护版本号
- in-tree 扩展没有独立发布说明,其变更体现在常规 Goose release notes
- core out-of-tree 扩展通常位于形如
github.com/kumose/goose-⟨extension_name⟩的仓库,但命名可能有差异。详见核心扩展完整列表。