浏览知识库目录

C#

NuGet、发布与部署

使用 NuGet Tool、dotnet publish、干净环境烟测和校验和形成可回滚交付流程。

NuGet、发布与部署

“在源码目录能运行”不等于可以交付。交付流程要证明版本和依赖明确、构建结果可安装、入口可执行,并且在没有源码目录和开发机缓存帮助的干净环境中仍能通过验收。


一、学习目标

  • 区分 build、pack 与 publish
  • 把 CLI 打包为 .NET Tool
  • 理解框架依赖与独立部署
  • 生成单文件发布产物
  • 在干净环境完成安装和冒烟
  • 记录校验和、依赖与回滚信息

二、构建、打包和发布

  • dotnet build:编译项目,供开发和测试使用
  • dotnet pack:创建 NuGet .nupkg
  • dotnet publish:准备可部署应用及其依赖

Release 构建:

dotnet restore --locked-mode
dotnet build StudyTasks.slnx \
  -c Release \
  --no-restore \
  --warnaserror
dotnet test StudyTasks.slnx \
  -c Release \
  --no-build

发布前还要运行格式检查和安全扫描。不要在生产服务器临时拉源码构建;CI 应产生不可变、可追踪产物。


三、版本元数据

StudyTasks.Cli.csproj

<PropertyGroup>
  <Version>1.0.0</Version>
  <Authors>OliverChiu</Authors>
  <Description>跨平台命令行任务管理器</Description>
  <RepositoryUrl>https://example.com/StudyTasks</RepositoryUrl>
  <RepositoryType>git</RepositoryType>
  <ContinuousIntegrationBuild
    Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>

稳定版本遵循语义化版本:

  • MAJOR:不兼容接口或命令契约变化
  • MINOR:向后兼容能力
  • PATCH:向后兼容修复

版本不仅影响程序集,也影响 NuGet、日志、--version 和回滚定位。CI 应由受控标签或发布参数提供版本,不靠开发者手工编辑后忘记提交。


四、打包为 .NET Tool

项目属性:

<PropertyGroup>
  <PackAsTool>true</PackAsTool>
  <ToolCommandName>study-tasks</ToolCommandName>
  <PackageId>StudyTasks.Tool</PackageId>
  <PackageOutputPath>$(MSBuildThisFileDirectory)..\..\artifacts\packages</PackageOutputPath>
</PropertyGroup>

构建包:

dotnet pack src/StudyTasks.Cli \
  -c Release \
  --no-build

本地隔离安装:

mkdir .tool-test
dotnet new tool-manifest --output .tool-test
dotnet tool install StudyTasks.Tool \
  --tool-manifest .tool-test/.config/dotnet-tools.json \
  --add-source artifacts/packages \
  --version 1.0.0

dotnet tool run study-tasks --help

使用本地 tool manifest 避免污染用户全局环境。测试结束后删除隔离目录即可。


五、框架依赖发布

dotnet publish src/StudyTasks.Cli \
  -c Release \
  --no-build \
  --no-self-contained \
  -o artifacts/publish/framework-dependent

目标机器需要兼容 .NET 10 Runtime。优点是产物较小,运行时安全补丁可由机器统一更新;缺点是部署必须管理 Runtime 前置条件。

验证:

dotnet artifacts/publish/framework-dependent/StudyTasks.Cli.dll --help

框架依赖可执行文件也可能包含平台 apphost;跨平台调用 DLL 最清楚。


六、独立部署

dotnet publish src/StudyTasks.Cli \
  -c Release \
  -r linux-x64 \
  --self-contained true \
  -o artifacts/publish/linux-x64

独立部署包含 Runtime,目标机器无需预装 .NET,但产物更大。运行时补丁不会自动进入既有包,必须重新构建和部署。

常见 RID:

  • win-x64
  • linux-x64
  • linux-arm64
  • osx-x64
  • osx-arm64

只发布实际支持并测试过的平台。不要把“能生成产物”当作“在该系统已受支持”。


七、单文件与裁剪

dotnet publish src/StudyTasks.Cli \
  -c Release \
  -r linux-x64 \
  --self-contained true \
  -p:PublishSingleFile=true \
  -o artifacts/publish/linux-x64-single

单文件简化分发,但仍可能在启动时提取部分原生资产,行为受包依赖影响。

裁剪:

<PublishTrimmed>true</PublishTrimmed>

裁剪会删除静态分析认为未使用的代码。反射、动态加载和某些序列化模式可能被误删,必须启用分析器并做完整运行测试。本系列默认不把裁剪作为交付前提。

Native AOT 可以减少启动时间和运行依赖,但兼容性要求更严格,应作为测量驱动的独立路线,不在首次交付中强开。


八、包内容检查

dotnet nuget locals all --list
dotnet package search StudyTasks.Tool --source artifacts/packages

.nupkg 本质上是 ZIP,应检查:

  • 只有 Release 二进制和必要元数据
  • 不包含数据库、Token、开发配置
  • 不包含 bin/Debug、临时文件和测试数据
  • 许可证和说明完整
  • 包依赖版本符合预期

发布前在一个没有源码的临时目录安装,避免工具因当前工作目录中的 DLL 或配置“碰巧可用”。


九、可重复与供应链

最低要求:

  • 固定 .NET SDK 与包版本
  • 提交 packages.lock.json
  • CI 使用 --locked-mode
  • 只允许明确 NuGet 源
  • 保留构建日志、提交 SHA 和依赖清单
  • 检查已知漏洞和废弃包
dotnet list package --vulnerable --include-transitive
dotnet list package --deprecated

不要在 CI 日志输出私有源凭据。第三方构建步骤和 GitHub Action 也属于供应链,应固定可信版本并限制权限。


十、校验和与发布记录

Linux/macOS:

sha256sum artifacts/packages/*.nupkg
sha256sum artifacts/publish/linux-x64-single/*

PowerShell:

Get-FileHash .\artifacts\packages\*.nupkg -Algorithm SHA256

发布记录至少包含:

  • 版本与发布日期
  • 源提交 SHA
  • SDK、Runtime 与依赖版本
  • 支持的操作系统和架构
  • 产物 SHA-256
  • 数据格式或配置变化
  • 已知限制
  • 升级和回滚步骤

校验和用于验证传输完整性,不替代可信签名和发布渠道。


十一、干净环境验收

在官方 .NET 10 SDK 容器或全新虚拟机:

dotnet --info
dotnet tool install StudyTasks.Tool \
  --tool-path /tmp/study-tools \
  --add-source /packages \
  --version 1.0.0

/tmp/study-tools/study-tasks --help
/tmp/study-tools/study-tasks add "发布验收"
/tmp/study-tools/study-tasks list
/tmp/study-tools/study-tasks done 1
/tmp/study-tools/study-tasks delete 1

数据库路径指向临时目录,远端同步使用本地测试服务。验收不得访问真实用户数据或生产 API。


十二、回滚

回滚需要:

  • 保留上一版本产物和校验和
  • 知道数据格式是否向后兼容
  • 配置变化有默认值或恢复步骤
  • 数据迁移有备份和恢复演练

二进制回滚不一定能回滚数据库。若新版本写入旧版本无法读取的数据,必须提供兼容窗口或反向迁移。

NuGet 公共包通常不应删除或覆盖同一版本;发现缺陷时发布新补丁版本并标记问题版本。


十三、常见错误

只在源码目录验收

可能隐式加载本地配置和项目输出。必须在干净目录安装产物。

独立部署后不再更新

Runtime 已包含在产物中,安全补丁需要重新发布。

开启裁剪却不做完整测试

反射路径可能只在生产功能中失败。先看分析警告并覆盖真实入口。

包含秘密或用户数据库

检查包内容和构建输入,使用配置模板而非真实配置。


十四、练习与自测

练习:

  1. 生成 StudyTasks.Tool.1.0.0.nupkg 并检查内容。
  2. 在本地 tool manifest 中安装并运行。
  3. 分别生成框架依赖和 linux-x64 独立产物。
  4. 生成 SHA-256 和最小发布说明。
  5. 模拟回滚,验证旧版本能读取现有测试数据。

自测:

  • pack 与 publish 的目标有何不同?
  • 框架依赖和独立部署各由谁更新 Runtime?
  • 单文件为何不等于完全无提取?
  • 二进制回滚为何可能不足?

十五、官方资料

上一篇:测试、调试与代码质量 | 下一篇:综合实战与进阶路线