版本管理与 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
- 从项目根目录执行命令。
- 选择一个或多个服务或 Web 应用程序。prompt 会显示每个项及其当前版本。
- 选择递增类型:patch、minor 或 major。
- 确认答案。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 流程
- 在打包前运行项目测试和
dotnet build,以验证源代码。 - 使用
lino version list查看当前版本,并审查哪些服务或 Web 应用程序发生了变化。 - 使用
lino build,并选择保持当前版本,或应用 patch、minor 或 major 递增。 - 将生成的 container images 发布到部署平台使用的 registry,例如 Docker Hub、GitHub Container Registry、AWS ECR、Azure Container Registry 或其他兼容 registry。
- 通过引用可追踪的版本 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、集成事件和已部署制品之间的可追溯性。
