dotnet-add-ci

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

dotnet-add-ci

dotnet-add-ci

Add starter CI/CD workflows to an existing .NET project. Detects the hosting platform (GitHub Actions or Azure DevOps) and generates an appropriate starter workflow for build, test, and pack.
为现有.NET项目添加入门级CI/CD工作流。可检测托管平台(GitHub Actions或Azure DevOps),并生成适用于构建、测试和打包的入门工作流。

Scope

适用范围

  • Platform detection (GitHub Actions vs Azure DevOps)
  • Starter build/test/pack workflow generation
  • Basic CI workflow templates for .NET projects
  • 平台检测(GitHub Actions与Azure DevOps)
  • 生成构建/测试/打包的入门工作流
  • 适用于.NET项目的基础CI工作流模板

Out of scope

不适用范围

  • Advanced CI/CD patterns (reusable workflows, matrix builds, deployment) -- see [skill:dotnet-gha-patterns] and [skill:dotnet-ado-patterns]
Prerequisites: Run [skill:dotnet-version-detection] first to determine SDK version for the workflow. Run [skill:dotnet-project-analysis] to understand solution structure.
Cross-references: [skill:dotnet-project-structure] for build props layout, [skill:dotnet-scaffold-project] which generates the project structure these workflows build.

  • 高级CI/CD模式(可复用工作流、矩阵构建、部署)——请查看[skill:dotnet-gha-patterns]和[skill:dotnet-ado-patterns]
前置条件: 请先运行[skill:dotnet-version-detection]以确定工作流所需的SDK版本。运行[skill:dotnet-project-analysis]以了解解决方案结构。
相关参考:[skill:dotnet-project-structure]用于构建属性布局,[skill:dotnet-scaffold-project]可生成这些工作流所构建的项目结构。

Platform Detection

平台检测

Detect the CI platform from existing repo indicators:
IndicatorPlatform
.github/
directory exists
GitHub Actions
azure-pipelines.yml
exists
Azure DevOps
.github/workflows/
has YAML files
GitHub Actions (already configured)
NeitherAsk the user which platform to target

根据现有仓库中的标识检测CI平台:
标识平台
存在
.github/
目录
GitHub Actions
存在
azure-pipelines.yml
文件
Azure DevOps
.github/workflows/
目录下有YAML文件
GitHub Actions(已配置)
以上都没有询问用户要针对哪个平台

GitHub Actions Starter Workflow

GitHub Actions 入门工作流

Create
.github/workflows/build.yml
:
yaml
name: Build and Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          global-json-file: global.json

      - name: Restore
        run: dotnet restore --locked-mode

      - name: Build
        run: dotnet build --no-restore -c Release

      - name: Test
        run: dotnet test --no-build -c Release --logger trx --results-directory TestResults

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: TestResults/**/*.trx
创建
.github/workflows/build.yml
文件:
yaml
name: Build and Test

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read

env:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          global-json-file: global.json

      - name: Restore
        run: dotnet restore --locked-mode

      - name: Build
        run: dotnet build --no-restore -c Release

      - name: Test
        run: dotnet test --no-build -c Release --logger trx --results-directory TestResults

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: TestResults/**/*.trx

Key Decisions Explained

关键决策说明

  • global-json-file
    — uses the repo's
    global.json
    to install the exact SDK version. If the project has no
    global.json
    , replace with
    dotnet-version: '10.0.x'
    (or the appropriate version)
  • --locked-mode
    — ensures
    packages.lock.json
    files are respected; fails if they're out of date. If the project doesn't use lock files, replace with plain
    dotnet restore
  • -c Release
    — builds in Release mode so
    ContinuousIntegrationBuild
    takes effect
  • permissions: contents: read
    — principle of least privilege
  • Environment variables — suppress .NET CLI noise in logs
  • global-json-file
    — 使用仓库中的
    global.json
    安装精确的SDK版本。如果项目没有
    global.json
    ,请替换为
    dotnet-version: '10.0.x'
    (或相应版本)
  • --locked-mode
    — 确保
    packages.lock.json
    文件被遵循;如果文件过期则会失败。如果项目不使用锁定文件,请替换为普通的
    dotnet restore
  • -c Release
    — 以Release模式构建,使
    ContinuousIntegrationBuild
    生效
  • permissions: contents: read
    — 最小权限原则
  • 环境变量 — 抑制.NET CLI在日志中的冗余输出

Adding NuGet Pack (Libraries)

添加上传NuGet包(适用于类库)

For projects that publish to NuGet, add a pack step:
yaml
      - name: Pack
        run: dotnet pack --no-build -c Release -o artifacts

      - name: Upload packages
        uses: actions/upload-artifact@v4
        with:
          name: nuget-packages
          path: artifacts/*.nupkg

对于要发布到NuGet的项目,添加打包步骤:
yaml
      - name: Pack
        run: dotnet pack --no-build -c Release -o artifacts

      - name: Upload packages
        uses: actions/upload-artifact@v4
        with:
          name: nuget-packages
          path: artifacts/*.nupkg

Azure DevOps Starter Pipeline

Azure DevOps 入门流水线

Create
azure-pipelines.yml
at the repo root:
yaml
trigger:
  branches:
    include:
      - main

pr:
  branches:
    include:
      - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
  buildConfiguration: 'Release'

steps:
  - task: UseDotNet@2
    displayName: 'Setup .NET SDK'
    inputs:
      useGlobalJson: true

  - script: dotnet restore --locked-mode
    displayName: 'Restore'

  - script: dotnet build --no-restore -c $(buildConfiguration)
    displayName: 'Build'

  - task: DotNetCoreCLI@2
    displayName: 'Test'
    inputs:
      command: 'test'
      arguments: '--no-build -c $(buildConfiguration) --logger trx'
      publishTestResults: true
在仓库根目录创建
azure-pipelines.yml
文件:
yaml
trigger:
  branches:
    include:
      - main

pr:
  branches:
    include:
      - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  DOTNET_NOLOGO: true
  DOTNET_CLI_TELEMETRY_OPTOUT: true
  DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
  buildConfiguration: 'Release'

steps:
  - task: UseDotNet@2
    displayName: 'Setup .NET SDK'
    inputs:
      useGlobalJson: true

  - script: dotnet restore --locked-mode
    displayName: 'Restore'

  - script: dotnet build --no-restore -c $(buildConfiguration)
    displayName: 'Build'

  - task: DotNetCoreCLI@2
    displayName: 'Test'
    inputs:
      command: 'test'
      arguments: '--no-build -c $(buildConfiguration) --logger trx'
      publishTestResults: true

Adding NuGet Pack (Libraries)

添加上传NuGet包(适用于类库)

yaml
  - script: dotnet pack --no-build -c $(buildConfiguration) -o $(Build.ArtifactStagingDirectory)
    displayName: 'Pack'

  - task: PublishBuildArtifacts@1
    displayName: 'Publish NuGet packages'
    inputs:
      pathToPublish: '$(Build.ArtifactStagingDirectory)'
      artifactName: 'nuget-packages'

yaml
  - script: dotnet pack --no-build -c $(buildConfiguration) -o $(Build.ArtifactStagingDirectory)
    displayName: 'Pack'

  - task: PublishBuildArtifacts@1
    displayName: 'Publish NuGet packages'
    inputs:
      pathToPublish: '$(Build.ArtifactStagingDirectory)'
      artifactName: 'nuget-packages'

Adapting the Starter Workflow

适配入门工作流

Multi-TFM Projects

多目标框架(TFM)项目

If the project multi-targets, the default workflow works without changes —
dotnet build
and
dotnet test
handle all TFMs automatically. No matrix is needed for the starter.
如果项目是多目标框架,默认工作流无需修改即可使用——
dotnet build
dotnet test
会自动处理所有TFM。入门工作流不需要矩阵构建。

Windows-Only Projects (MAUI, WPF, WinForms)

仅Windows项目(MAUI、WPF、WinForms)

Change the runner:
yaml
undefined
修改运行环境:
yaml
undefined

GitHub Actions

GitHub Actions

runs-on: windows-latest
runs-on: windows-latest

Azure DevOps

Azure DevOps

pool: vmImage: 'windows-latest'
undefined
pool: vmImage: 'windows-latest'
undefined

Solution Filter

解决方案筛选器

If the repo has multiple solutions or uses solution filters:
yaml
      - name: Build
        run: dotnet build MyApp.slnf --no-restore -c Release

如果仓库中有多个解决方案或使用解决方案筛选器:
yaml
      - name: Build
        run: dotnet build MyApp.slnf --no-restore -c Release

Verification

验证

After adding the workflow, verify locally:
bash
undefined
添加工作流后,可在本地验证:
bash
undefined

GitHub Actions — validate YAML syntax

GitHub Actions — 验证YAML语法

Install: gh extension install moritztomasi/gh-workflow-validator

安装:gh extension install moritztomasi/gh-workflow-validator

gh workflow-validator .github/workflows/build.yml
gh workflow-validator .github/workflows/build.yml

Or simply verify the build steps work locally

或者直接在本地验证构建步骤是否正常

dotnet restore --locked-mode dotnet build --no-restore -c Release dotnet test --no-build -c Release

Push a branch and open a PR to trigger the workflow.

---
dotnet restore --locked-mode dotnet build --no-restore -c Release dotnet test --no-build -c Release

推送分支并创建PR以触发工作流。

---

What's Next

下一步

This starter covers build-test-pack. For advanced scenarios, see the CI/CD depth skills:
  • Reusable composite actions and workflow templates
  • Matrix builds across OS/TFM combinations
  • Deployment pipelines with environment gates
  • NuGet publishing with signing
  • Container image builds
  • Code coverage reporting and enforcement

本入门工作流涵盖了构建-测试-打包环节。对于高级场景,请查看CI/CD进阶技能:
  • 可复用复合操作和工作流模板
  • 跨操作系统/目标框架组合的矩阵构建
  • 带环境门限的部署流水线
  • 带签名的NuGet发布
  • 容器镜像构建
  • 代码覆盖率报告与强制检查

References

参考资料