版本管理与 Build

专业应用程序需要清晰的 release 标识符、可复现的 build 命令,以及源代码与已部署制品之间的可追溯性。
Lino 为服务和 Web 应用程序管理独立的 SemVer 版本,然后在发布用于 release 的 container images 时使用这些版本。

独立版本管理

Lino 项目可以包含多个服务和 Web 应用程序。每个可部署项都有自己的版本,因此一个服务中的小修复不会强制整个系统进行人为的 release。这对于模块化和分布式架构很重要,因为 APIs、workers、web apps、migrations 和集成契约可能以不同节奏演进。

运行版本存储在名为 version.txt 的简单文本文件中。对于服务,该文件位于 src/Services/<ServiceName>/version.txt。对于 Web 应用程序,该文件位于 src/WebApps/<WebAppName>/version.txt。Lino CLI 在列出、查看、递增以及生成带版本的 builds 时会读取这些文件。

Lino 使用的 SemVer 规则

MAJOR.MINOR.PATCH
  • PATCH 递增最后一个数字,应用于兼容性修复、小型内部改进,以及不改变公共契约的变更。
  • MINOR 递增中间数字并将 patch 重置为零。用于向后兼容的功能、新 endpoints、可选字段或增量行为。
  • MAJOR 递增第一个数字并将 minor 和 patch 重置为零。用于消费者必须适配的情况,例如 API contract 发生不兼容变更,或某个行为被有意替换。

示例:1.0.0 可以表示第一个稳定版本,1.0.1 表示兼容性修复,1.1.0 表示兼容的新能力或无破坏性变更的新 endpoints,2.0.0 表示包含需要客户端更新的变更的 release。

查看当前版本

使用 lino version list 查看项目中所有服务和 Web 应用程序的当前版本:

lino version list

当需要查看某个特定服务或 Web 应用程序的版本时,使用 lino version show。该命令会询问目标是服务还是 Web 应用程序,并显示从对应 version.txt 文件读取的版本。

lino version show

递增版本

当服务或 Web 应用程序准备好进行新的 release 时,使用 lino version bump

lino version bump
  1. 从项目根目录执行命令。
  2. 选择一个或多个服务或 Web 应用程序。prompt 会显示每个项及其当前版本。
  3. 选择递增类型:patch、minor 或 major。
  4. 确认答案。Lino 会更新选定的 version.txt 文件,并显示包含新版本的表格。

每次执行都会保持清晰的变更跟踪,提高与 release 实践的一致性,并更容易与 CI/CD pipelines 对齐。版本号不再是孤立细节,而是用于识别真正发生变更的可部署制品。

版本变更应与 release 的技术影响一起审查。数据库 migration 可能与服务版本关联,API 消费者可能需要契约说明,集成事件可能需要兼容性检查。让版本靠近可部署项,可以使这些决策更加明确,也更容易审计。

在 major 递增前,审查公共 APIs、事件契约、migrations、客户端兼容性和外部消费者。在 minor 递增前,确认新行为是增量式的。在 patch 前,确认变更兼容且不会改变使用预期。

Build 与容器化

在视频和日常开发中,dotnet build 经常用于验证生成的解决方案在每个建模步骤之后仍然可以编译。lino build 命令有另一个目标:使用 .NET container publish profile 以 Release 模式发布选定的服务和 Web 应用程序,为 release 做准备。

这种分离避免将简单的编译验证当成交付包。在开发期间使用 dotnet build 及早发现错误。当制品准备好接收版本、成为 container image 并进入 registry 或 deploy pipeline 时,使用 lino build

lino build 的作用

从 Lino 项目的根目录执行命令:

lino build

CLI 会验证已认证用户和当前项目配置,询问哪些服务或 Web 应用程序应进入 build,然后询问版本应保持不变还是递增。选择递增时,Lino 会在生成 build 命令之前更新对应的 version.txt

backend 返回要执行的精确命令。目前这些命令使用 dotnet publish,并带有 -c Release-p:PublishProfile=DefaultContainer-p:ContainerRepository-p:ContainerImageTag-p:ContainerLabelVersion。image tag 和 container version label 会接收为 release 选择的同一个 SemVer 值。

实际上,该过程会编译服务或 Web 应用程序代码,应用必要的发布配置,基于当前 SemVer 版本生成 container image,并为制品分配标准化的名称、tag 和 metadata。

生成的 repository 名称

Lino 会规范化项目和项名称,以生成可预测的 container repositories:

  • 简单服务 API:<project-name>/services/<service-name>-api:1.2.3
  • 模块化服务 host:<project-name>/services/<service-name>-host:1.2.3
  • Blazor Web 应用程序:<project-name>/webapps/<webapp-name>:1.2.3

该约定让服务 APIs、模块化 hosts 和 Web 应用程序在 registry 中保持分离,并在 tag 中保留 release 版本。该模式还消除了重复的手动决策,并减少环境、CI/CD scripts 和运维文档之间的差异。

发布到 registries

生成的 images 可以发布到部署平台使用的 registry:

  • Docker Hub
  • GitHub Container Registry
  • AWS ECR
  • Azure Container Registry
  • 任何其他兼容 OCI 的 registry。

尽可能通过指向不可变版本 tag(如 1.2.3)进行 deploy,而不是使用浮动 tags。这会改善 rollback、审计,以及对已构建、已发布和已部署内容的比较。

推荐的 release 流程

  1. 在打包前运行项目测试和 dotnet build,以验证源代码。
  2. 使用 lino version list 查看当前版本,并审查哪些服务或 Web 应用程序发生了变化。
  3. 使用 lino build,并选择保持当前版本,或应用 patch、minor 或 major 递增。
  4. 将生成的 container images 发布到部署平台使用的 registry,例如 Docker Hub、GitHub Container Registry、AWS ECR、Azure Container Registry 或其他兼容 registry。
  5. 通过引用可追踪的版本 tags 进行 deploy,并将 changelog、migrations 和 rollback plan 连接到同一个 release。

不要将 secrets、生产 connection strings 或特定环境凭据放入生成的 images 中。请使用环境变量、本地开发的 user secrets、CI/CD secret vault,或部署平台的 secret 机制。

通过此流程,版本管理和 build 保持关联:项目中记录的同一个 SemVer 值会作为 container tag 和 release metadata 使用,从而改善源代码、migrations、API contracts、集成事件和已部署制品之间的可追溯性。

发生了未处理的错误。 重新加载 🗙