.NET CI

dotnet-ci@1.0.0 Template

Restore, build and test a .NET solution or project, with optional coverage.

Start from it

flightstack template use dotnet-ci

What it does

Restore, build and run dotnet test in one job for a solution, a single test project, or whatever the working directory resolves to. Optional test filter, coverlet coverage and SDK version check.

Inputs

target string
Solution (.sln/.slnx) or project (.csproj) to test. Empty lets dotnet test pick the single solution or project in workingDir.
workingDir string default .
Directory to run in.
configuration string default Release
Build configuration.
filter string
dotnet test --filter expression, e.g. "Category!=Integration".
coverage boolean default false
Collect coverage with the built-in "XPlat Code Coverage" collector (coverlet). Reports land in TestResults/.
sdkVersion string
Fail early unless dotnet --version starts with this, e.g. "10.0". Empty skips the check.
extraArgs string
Extra arguments appended to dotnet test.
env object
Extra environment variables for the test run.

Definition

name: .NET CI
description: >-
  Restore, build and test a .NET solution or project, with optional coverage.

triggers:
  - type: push
    branches: [main]
  - type: pullRequest

jobs:
  test:
    name: Build and test
    type: plugin/dotnet-ci
    with:
      target: MyApp.sln
      configuration: Release

plugin:
  name: dotnet-ci
  displayName: .NET CI
  description: >-
    Restore, build and run `dotnet test` in one job. Works for a solution, a
    single test project, or whatever the working directory resolves to.
  category: quality

  supportedPlatforms:
    - linux
    - macos
    - windows

  parameters:
    type: object
    properties:
      target:
        type: string
        default: ""
        description: >-
          Solution (.sln/.slnx) or project (.csproj) to test. Empty lets
          `dotnet test` pick the single solution or project in workingDir.
      workingDir:
        type: string
        default: "."
        description: Directory to run in.
      configuration:
        type: string
        default: Release
        description: Build configuration.
      filter:
        type: string
        default: ""
        description: >-
          `dotnet test --filter` expression, e.g. "Category!=Integration".
      coverage:
        type: boolean
        default: false
        description: >-
          Collect coverage with the built-in "XPlat Code Coverage" collector
          (coverlet). Reports land in TestResults/.
      sdkVersion:
        type: string
        default: ""
        description: >-
          Fail early unless `dotnet --version` starts with this, e.g. "10.0".
          Empty skips the check.
      extraArgs:
        type: string
        default: ""
        description: Extra arguments appended to `dotnet test`.
      env:
        type: object
        description: Extra environment variables for the test run.

  script: |
    set -euo pipefail
    cd "{{workingDir}}"

    if ! command -v dotnet >/dev/null 2>&1; then
      echo "dotnet is not installed on this agent. Install the .NET SDK, or run this job on an agent that has it." >&2
      exit 1
    fi

    installed="$(dotnet --version)"
    echo ".NET SDK $installed"
    wanted="{{sdkVersion}}"
    if [ -n "$wanted" ] && [ "${installed#"$wanted"}" = "$installed" ]; then
      echo "This job wants .NET SDK $wanted but the agent has $installed." >&2
      exit 1
    fi

    export DOTNET_CLI_TELEMETRY_OPTOUT=1
    export DOTNET_NOLOGO=1
    {{#each env}}
    export {{@key}}="{{this}}"
    {{/each}}

    target="{{target}}"
    echo "--- restore"
    dotnet restore $target

    echo "--- build"
    dotnet build $target --no-restore --configuration "{{configuration}}"

    args=(test $target --no-build --configuration "{{configuration}}" --logger "console;verbosity=normal")
    filter="{{filter}}"
    if [ -n "$filter" ]; then
      args+=(--filter "$filter")
    fi
    if [ "{{coverage}}" = "true" ]; then
      args+=(--collect "XPlat Code Coverage")
    fi

    echo "--- test"
    dotnet "${args[@]}" {{extraArgs}}