跳到主要内容

发布周期

本文概述 Goose 与核心扩展的发布周期框架,面向扩展开发者,帮助理解相关流程。

概览

  • Goose 遵循 Semantic Versioningv<MAJOR>.<MINOR>.<PATCH>
  • Minor 版本约每 4 个月发布一次
  • Patch 版本按需发布,面向:
    • The latest stable version
    • The current Long Term Support (LTS) version

术语

发布文档中会用到一些描述版本与分支的基础术语,简要说明如下。

  • vx.y.z:最新稳定版
  • vx.y-codename:产出 vx.y.<n> 的分支名
  • vx.<y+1>-codename:产出下一次 minor 版本的分支名
  • Main release cycle:与 vx.<y+1>.0vx.y.<z+1> 发布相关的分支、提交和 PR
  • Active branch:属于主发布周期的分支,即 mainvx.<y+n>-codenamen >= 0
  • Single branch extension:仅 1 条活跃分支的扩展。由于 main 始终活跃,因此该分支总是 main. This means all other branches of format vx.y-codename must be vx.<y-n>-codename where n >= 1
  • Multi branch extension:有多条活跃分支的扩展
  • Two branch extension:有两条活跃分支:main 与 vx.y-codename
  • Three branch extension:有三条活跃分支:main、vx.y-codenamevx.<y+1>-codename
  • LTS release:长期支持版本。这类版本在主发布周期外仍会继续获得支持(patch 发布) lifetime in the active release cycle. Currently LTS releases will receive 1 year of support
  • Unstable API extension:面向 unstable 扩展 API 的扩展,可基于 C++ API 或 unstable C API. These extensions are not binary-compatible across multiple Goose versions
  • Stable API extension:面向 Goose stable C API 的扩展。这类扩展 binary-compatible across multiple Goose versions
  • In-tree extensions:位于 goose/goose 源码树内的扩展

主分支与标签

在 Git 版本控制中,分支用于让同一代码库的多个版本并行存在。在 Goose 中,有两类核心分支主导 Goose(及扩展)的发布周期。其格式如下:

  • main 分支:主分支,通常可视为汇总分支
  • vx.y-codename 分支:用于产出所有 vx.y.z 版本
  • vx.y.z 标签:Goose 稳定发布标签。该标签一旦打出即固定到同一提交

Goose 主发布周期

LTS (Long-Term Support) releases follow a separate maintenance cycle to provide extended support and stability.

Goose 主发布周期分为 3 个阶段:Mid-cyclePre-releaseFeature freeze。这些阶段边界清晰,并会同步给团队,确保协同推进下一次发布。

阶段 1:Mid-Cycle

活跃 Goose 分支

  • main
  • vx.y-codename

说明

mid-cycle 是最常见阶段,约占周期 75% 时间。该阶段可视为日常开发期:下一次发布尚远,团队会合并各类功能与修复。在此期间,patch 版本(vx.y.<z+n>)可从 vx.y-codename 分支产出。补丁先合并到 vx.y-codename,再频繁回合并到 main,保持同步。

Goose PR 合并目标

  • Bug-fixes for vx.y.<z+n> patch releases are merged into vx.y-codename
  • Features and bug-fixes for vx.<y+1>.0 are merged into main

阶段 2:Pre-Release

活跃分支

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

说明

pre-release 阶段用于准备即将到来的 vx.<y+1>.0 minor 发布。该阶段开始时会创建 vx.<y+1>-codename 分支。该分支用于产出下一个 minor 版本,以及后续 vx.<y+1>.<n> patch 版本。

Goose PR 合并目标

  • Bug-fixes for vx.y.<z+1> patch releases are merged into vx.y-codename
  • Features and bug-fixes for vx.<y+1>.0 are merged into vx.<y+1>-codename
  • Features for vx.<y+2>.0 are merged into vx.<y+2>-codename

阶段 3:Feature Freeze

活跃分支

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

说明

feature freeze 是最接近发布的阶段。在该阶段,vx.<y+1>-codename 不再接受功能合并,仅接收 bug 修复。目标是保障即将发布版本质量。此阶段会加强测试与基准验证,并通过禁止功能合并降低临近发布引入新问题的风险。

Goose PR 合并目标

  • Bug-fixes for vx.y.<z+1> are no longer allowed, should target vx.<y+1>.0 instead
  • Bug-fixes for vx.<y+1>.0 are merged into vx.<y+1>-codename
  • Features for vx.<y+1>.0 are no longer allowed, should target vx.<y+2>.0 instead
  • Features for vx.<y+2>.0 are merged into vx.<y+2>-codename

扩展主发布周期

多数 Goose 扩展与主仓库 goose/goose 完全分离,可采用自己的发布节奏。本节会按扩展类型说明各自发布周期。

在说明扩展发布周期前,先将扩展分成三类;同类扩展共享相近发布模型:

  • In-tree extensions
  • Unstable API extensions
  • Stable API extensions

下面按复杂度递增依次说明三类扩展的发布周期。

In-Tree 扩展

对于 in-tree 扩展,发布周期最简单。由于代码位于 goose/goose 仓库,它们与 Goose 完全同频,版本与分支策略一致。某种意义上,它们更像 goose/goose 代码库中可延迟加载的模块。

Stable API 扩展

Stable API 扩展在 Goose 中是较新的方向,但未来预计会成为主流。它们基于稳定 C 扩展 API 构建,可与多个 Goose 版本保持二进制兼容,因此其发布周期可以/应当与 Goose 主发布周期解耦。

尽管 Stable API 扩展的发布流程仍在演进,但核心思路是:形成与 goose/goose 类似但独立的周期,每个扩展版本可面向 1 个或多个 Goose 版本。

Unstable API 扩展

Unstable API 扩展目前仍占多数。它们要么基于 C++ 扩展 API,要么基于不稳定 C 扩展 API。从发布周期视角看,这类扩展最复杂:每个扩展版本只面向单一 Goose 版本。这种 1:1 绑定使其发布周期与 Goose 主周期紧密耦合。虽然长期目标是迁移到稳定 API,但 unstable 扩展在较长时间内仍会存在,因此需要明确其生命周期。

按分支模型分类

首先将 unstable API 扩展按子类划分。与 Goose 类似,这些扩展也采用以 mainvx.y-codename 为核心的分支体系。我们按活跃分支数量定义三类:

  • Single branch extensions have only the main active branch
  • Two branch extensions have two active branches: main and vx.y-codename
  • Three branch extensions have three active branches: main, vx.y-codename, and vx.<y+1>-codename

Goose 目标版本

每个 unstable API 扩展都应面向单一 Goose 版本。目标版本由 goose 子模块MainDistributionPipeline 工作流中的目标版本共同决定。扩展具体面向哪个版本取决于发布阶段与分支,下面列出组合情况。

  • Phase: Mid-cycle
    • Type: Single branch
      • Extension main -> Goose vx.y.z or main
    • Type: Two branch
      • Extension main -> Goose vx.y.z or main
      • Extension vx.y-codename -> Goose vx.y.z or vx.y-codename
    • Type: Three branch: should not exist
  • Phase: Pre-release / Patch
    • Type: Single branch
      • Extension main -> Goose vx.y.z or vx.<y+1>-codename
    • Type: Two branch
      • Extension main -> Goose vx.y.z or vx.<y+1>-codename
      • Extension vx.y-codename -> Goose vx.y.z or vx.y-codename
    • Type: Three branch
      • Extension main -> Goose main
      • Extension vx.y-codename -> Goose vx.y.z or vx.y-codename
      • Extension vx.<y+1>-codename -> Goose vx.<y+1>-codename

PR 应合并到哪里

unstable API 扩展的 PR 合并目标取决于两点:当前发布阶段和扩展类型。下面给出各组合规则。

  • Phase: Mid-cycle
    • Type: Single branch
      • if Goose target: vx.y.z:
        • PR for vx.y.<z+1> into main1
        • PR for vx.<y+1>.0 merges into main
      • if Goose target: main:
        • PR for vx.y.<z+1> are impossible
        • PR for vx.<y+1>.0 merges into main
    • Type: Two branch
      • PR for vx.y.<z+1> merges into vx.y-codename
      • PR for vx.<y+1>.0 merges into main
    • Type: Three branch
      • PR for vx.y.<z+1> merges into vx.y-codename
      • PR for vx.<y+1>.0 merges into vx.<y+1>-codename
      • PR for vx.<y+2>.0 merges into main
  • Phase: Pre-release / Patch
    • Type: Single branch
      • if Goose target: vx.y.z:
        • PR for vx.y.<z+1> into main1 2
        • PR for vx.<y+1>.0 merges into main
      • if Goose target: main:
        • PR for vx.y.<z+1> are impossible
        • PR for vx.<y+1>.0 merges into main
    • Type: Two branch
      • PR for vx.y.<z+1> merges into vx.y-codename 2
      • PR for vx.<y+1>.0 merges into main
    • Type: Three branch
      • PR for vx.y.<z+1> merges into vx.y-codename2
      • PR for vx.<y+1>.0 merges into vx.<y+1>-codename
      • PR for vx.<y+2>.0 merges into main

将发布哪个扩展版本?

每次 Goose 发布都应提供完整核心扩展集合。对 unstable API 扩展而言,这意味着需要重建二进制。核心扩展通常通过 goose/goose CI 构建。因此发布可用扩展列表记录在 extension config files 中。但该配置不一定始终最新。为确定某次发布应带哪个扩展版本,我们按发布类型(patch/minor)和扩展类型(single/multi branch)定义如下“权威来源”。

  • Release type: Patch
    • Extension type: Single branch
    • Extension type: Multi branch
      • Latest version: Extension vx.y-codename branch
  • Release type: Minor
    • Extension type: Single branch
      • Latest version: Extension main branch
    • Extension type: Two branch
      • Latest version: Extension main branch
    • Extension type: Three branch
      • Latest version: Extension vx.<y+1>-codename branch

Single/Two/Three Branch 间切换

扩展分支类型之间的切换流程相对直接,建议按以下方式进行:

  • Switch: Single branch -> Two branch
    • When: during any phase
    • Reasons:
      • When desire arises to merge features not eligible for vx.y.<z+1> while also maintaining ability to do releases for vx.y.<z+n>
      • To be able to test with latest Goose main while maintaining ability to do releases for vx.y.<z+n> (including vx.y.z itself)
    • Actions:
      • Create branch vx.y-codename from a commit on main between HEAD of main and the commit in the Goose vx.y.z config file.
  • Switch: Two branch -> Three branch
    • When: during Pre-release or Feature-freeze phase
    • Reasons:
      • Whenever a feature needs to be merged that is not eligible for merging into vx.<y+1>.0.
    • Actions:
      • Create vx.<y+1>-codename branch from main
  • Switch Three branch -> Two branch or Two branch -> Single branch
    • When: part of transition from Feature Freeze -> Mid-cycle
    • Action: happens automatically (vx.y-codename becomes inactive by definition)

Footnotes

  1. Single branch 扩展需要手动更新版本,以确保变更进入目标发布。 2

  2. pre-release 或 feature-freeze 阶段做 patch 发布并不常见。更建议将变更指向下一个 minor release instead. 2 3