C#
NuGet、发布与部署
使用 NuGet Tool、dotnet publish、干净环境烟测和校验和形成可回滚交付流程。
发布于 2026年7月23日
NuGet、发布与部署
“在源码目录能运行”不等于可以交付。交付流程要证明版本和依赖明确、构建结果可安装、入口可执行,并且在没有源码目录和开发机缓存帮助的干净环境中仍能通过验收。
一、学习目标
- 区分 build、pack 与 publish
- 把 CLI 打包为 .NET Tool
- 理解框架依赖与独立部署
- 生成单文件发布产物
- 在干净环境完成安装和冒烟
- 记录校验和、依赖与回滚信息
二、构建、打包和发布
dotnet build:编译项目,供开发和测试使用dotnet pack:创建 NuGet.nupkgdotnet 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-x64linux-x64linux-arm64osx-x64osx-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 已包含在产物中,安全补丁需要重新发布。
开启裁剪却不做完整测试
反射路径可能只在生产功能中失败。先看分析警告并覆盖真实入口。
包含秘密或用户数据库
检查包内容和构建输入,使用配置模板而非真实配置。
十四、练习与自测
练习:
- 生成
StudyTasks.Tool.1.0.0.nupkg并检查内容。 - 在本地 tool manifest 中安装并运行。
- 分别生成框架依赖和 linux-x64 独立产物。
- 生成 SHA-256 和最小发布说明。
- 模拟回滚,验证旧版本能读取现有测试数据。
自测:
- pack 与 publish 的目标有何不同?
- 框架依赖和独立部署各由谁更新 Runtime?
- 单文件为何不等于完全无提取?
- 二进制回滚为何可能不足?
十五、官方资料
上一篇:测试、调试与代码质量 | 下一篇:综合实战与进阶路线