CI 如何影响语义版本控制?

How does CI affect semantic versioning?

Countinous Delivery book 中,建议将所有内容(包括 CI 脚本)保留在版本控制中。实际上,当前的 CI 系统,如 gitlab CI 已经遵循这个经验法则并在同一代码库中搜索 CI 脚本。
另一方面,每当代码库发生变化时,我们都会对代码库(及其构建的工件)进行版本控制。为此,我们遵循语义版本控制;递增 patch 错误修正字段,minor 非破坏性功能,依此类推...
我们通过在 CI.
中检查来确保版本在提交之间递增 但是,有些提交只会更改 CI 脚本;即添加一个分析作业,优化另一个,等等
在这篇冗长无聊的序言之后,我的问题是,对 CI 进行此类更改的最佳实践是什么?因为它 可能 会影响最终构建的工件(例如更改 CI 作业中的构建标志以进行优化或...)。
在这种情况下可以增加版本吗?

Git 是一个版本控制系统。每次您向 git 存储库提交内容时,它都会使用代表该存储库版本的内容哈希值标记存储库的内容。 git 存储库内容的语义版本控制是多余且毫无意义的。 SemVer 的全部意义在于为生产者提供一种向消费者传达风险的方法。换句话说,语义版本控制用于构建产品标签,而不是用于生成构建的位。

如果您尝试将 SemVer 语义应用于存储库,则您是在标记产品输入,而不是产品本身。在执行所有 unit/regression/acceptance 测试之前,您不应该应用 SemVer 字符串。您还能如何确定 code/build-script 更改是否破坏了任何东西?


预构建标签无法工作。能够连续两次重现完全相同输出的构建过程极为罕见,如果存在的话。世界上有多个 API's/packages 并附有相同的 SemVer 字符串是违反最佳实践的。如果您标记 repo 内容,然后将该标签转发到构建输出,则每次 运行 构建时,您都会生成一个包含不同内容的包。总会有一些风险,即这些产出中不止一个会被释放到野外。许多有安全意识的消费者密切关注他们消费的包的内容散列。检测到某个特定的生产者发布了多个包哈希值而没有增加版本号,将引发危险信号并导致对该生产者内部流程的不信任。


这是一个很深的话题,这里无法完全涵盖。其他需要考虑的问题是 OS/Compiler/Tool 链更新。您还会将整个构建工具链提交给同一个存储库吗?这是一种站不住脚的方法,充满了我无法完全列举的危险,如果不花几个月的时间来记录它们。

最佳实践:

  • 使用语义提交消息来清楚地说明开发人员的意图。
  • 在 packaging/labeling 之前验证构建输出。
  • 对于非预发布出版物,始终让人类参与其中。

为了清楚起见,让我补充一点,在存储库中维护构建脚本和工具清单被认为是最佳实践。它将您的脚本和工具的版本与您正在构建的代码的版本联系起来。 Git 通过创建一个包含整个存储库状态的提交哈希(如果我没记错的话减去标签),确实很好地完成了这项工作。但最终会出现问题,旧版本的工具将从文件中撤回 shares/feeds,特别是当它们被发现会产生安全漏洞时。

有时候,您的产品的旧版本无法使用较早的构建过程进行复制。签入二进制文件通常被宣传为解决此问题的方法,但我认为这是一种反模式。您将来可能永远不需要或不需要的二进制文件不应存储在您的存储库中。它只会堵塞一切。

考虑使用备用存档系统。维护旧工具的单独存档不是一个坏主意,但您经常会发现,如果不对构建机器进行重大重新配置,您根本无法 运行 在当前硬件和 OS 上使用它们( s) 并重新引入众所周知的安全风险。您应该经常 p运行e 这样的存档,基于最新的已知风险并权衡必须做一些额外工作的成本,if/when总有一天,您需要从一个真正的旧提交哈希。

最好维护一个最新的构建系统,它可以构建您所有的代码库,回到其历史上的某个合理点。那一点通常是您愿意通过错误修复积极支持的最旧的部分。

最近我在使用 SemVer 兼容的 Headver; https://github.com/line/HeadVer 感觉很开心。

由于自动增量版本控制,它非常 CI 友好,但仍然能够通过允许手动定义主版本号来通知何时发生重大更改。