GitHub Actions 中 dotnet build 失败主因是 global.json 锁定的 SDK 版本未预装,应删 global.json 或设 "rollForward": "latestMinor",或用 actions/setup-dotnet@v4 安装 8.x;publish 输出路径需显式指定 -o ./publish;500 错误多因 ASPNETCORE_ENVIRONMENT 未设为 Production;secrets 不应在 build 阶段读取,而应在部署后注入。

GitHub Actions 跑不起来 dotnet build?检查 .NET SDK 版本和 global.json
GitHub Actions 默认 Ubuntu 运行器只预装特定版本的 .NET SDK(比如 ubuntu-22.04 预装 6.0、7.0、8.0),但你的项目可能依赖 global.json 锁定的版本(如 { "sdk": { "version": "8.0.100" } })。如果该精确版本未预装,dotnet build 就会报错 The SDK 'Microsoft.NET.Sdk' specified could not be found。
实操建议:
- 删掉项目根目录的
global.json(除非你真需要锁定补丁级版本) - 或改用
"rollForward": "latestMinor",让 SDK 自动降级/升级到可用版本 - 也可在 workflow 中显式安装:用
actions/setup-dotnet@v4并指定dotnet-version: '8.x'(注意写8.x而非8.0.x,后者可能匹配失败)
dotnet publish 输出路径不对,导致部署找不到文件
ASP.NET Core 默认 dotnet publish 输出到 bin/Release/net8.0/publish/,但很多部署动作(比如上传到 Azure App Service 或 SFTP)默认找的是 ./publish 或自定义路径。如果你没指定 -o 参数,后续步骤很可能提示 No such file or directory。
实操建议:
- 统一用
dotnet publish -c Release -o ./publish显式输出到项目根下的publish目录 - 确保后续部署步骤(如
azure/webapps-deploy@v2)的package输入指向./publish - 避免用
--self-contained true除非真要跨平台运行——它会让体积暴涨且容易因 RID 不匹配失败
ASP.NET Core 应用部署后 500 错误,大概率是 ASPNETCORE_ENVIRONMENT 没生效
本地开发时 Development 环境能看详细错误页,但部署到 GitHub Actions 后默认仍是 Production,而生产环境出错只返回空白 500。更常见的是:应用启动时因配置缺失(比如没设 ConnectionStrings:Default)直接崩溃,但日志根本看不到。
实操建议:
- 在 workflow 的
run步骤里加一句echo "ASPNETCORE_ENVIRONMENT=Production" >> $GITHUB_ENV,确保整个 job 都继承该变量 - 若用
web.config部署到 IIS,必须在标签里显式写environmentVariables="ASPNETCORE_ENVIRONMENT=Production" - Azure Web Apps 可在 Portal 的「配置 → 应用设置」里加键值对,但 GitHub Actions 部署时更推荐用
appSettings.json的Environment分区或密钥保管库
Secrets 传不进构建阶段?别在 build 里读 secrets
GitHub Actions 的 secrets 默认不注入到 build 步骤的环境变量中——即使你写了 env: { MY_KEY: ${{ secrets.MY_KEY }} },.NET 的 IConfiguration 也不会自动加载它,因为 dotnet build 是编译期行为,不走运行时配置系统。
实操建议:
- 敏感配置(数据库密码、API keys)一律放到部署后才注入:用
azure/appservice-settings@v1或env输入传给run步骤 - 若必须在构建时替换占位符(如
appsettings.Release.json),改用sed或jq命令行工具,而不是依赖 .NET 配置绑定 - 绝对不要把
secrets写进dotnet publish输出包——哪怕只是临时文件,也违反最小权限原则
最常被跳过的其实是发布前的 dotnet test 和发布后的健康检查。CI 不跑测试,CD 就是裸奔;部署完不 curl 一下 /healthz,等于没验证成功。











