版本管理与 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、集成事件和已部署制品之间的可追溯性。

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