This repository contains reusable GitHub Actions workflow templates for .NET applications. These templates help automate the process of building, testing, and deploying applications, following best practices and reducing boilerplate code across projects.
- Overview
- Prerequisites
- Quick Start
- Main Workflow Templates
- Step Templates
- Common Usage Examples
- Additional Documentation
- Contributing
- License
The pipelines in this repository are designed to be composable and reusable. They provide:
- Automated CI/CD for .NET applications
- Code quality checks including formatting and linting
- Testing with coverage reporting and multiple OS support
- Versioning using GitVersion
- Publishing to NuGet with manual approval workflows
- Dependabot integration for automated dependency updates
All workflows are designed to work with .NET 8.x and 9.x by default, with configurable support for other versions.
Before using these workflows, ensure you have:
- A GitHub repository with a .NET solution or project
- GitHub Actions enabled in your repository
- Required secrets configured (see individual workflow documentation)
- (Optional) GitVersion configuration file (
GitVersion.yml) in your repository root - (Optional) Release Drafter configuration (
.github/release-drafter.yml) for draft releases
Many workflows support the following optional secret:
FETCH_TOKEN: A GitHub Personal Access Token (PAT) with repository access, used to fetch dependencies from private repositories. If not provided, the defaultgithub.tokenis used.
To use any of these workflows in your repository, reference them in your workflow file:
name: CI/CD Pipeline
on:
push:
branches: [main]
pull_request:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-single.yml@main
with:
solution: "src/YourApp.sln"
secrets: inheritFor specific versions, replace @main with a tag like @v1.0.0.
These are complete CI/CD workflows that orchestrate multiple jobs.
A fast CI pipeline that performs a single-pass build and test on a single OS. Ideal for quick feedback on pull requests.
Features:
- Commit linting
- Build and test in one job (no separate stages)
- Automatic Dependabot PR merging
Usage:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-fast.yml@main
with:
solution: "src/YourApp.sln"
secrets: inheritParameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
solution |
Path to the solution or project file | ✅ | |
disableCodeFormat |
Skip code formatting checks | ❌ | false |
disableCoverageUpload |
Skip uploading coverage reports | ❌ | false |
disableDependaMerge |
Disable automatic Dependabot merge | ❌ | false |
dotnetLogging |
Verbosity level for dotnet commands | ❌ | minimal |
dotnetVersion |
.NET SDK version(s) to install | ❌ | 8.x\n9.x |
dotnetQuality |
.NET SDK quality channel | ❌ | ga |
enableCleanUpDockerDocker |
Free disk space by cleaning Docker images | ❌ | false |
runsOnBuild |
Runner label for build job | ❌ | ubuntu-latest |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
A comprehensive CI pipeline that runs on a single OS with separate stages for formatting, versioning, testing, and building.
Features:
- Commit linting
- Code formatting validation
- Version detection using GitVersion
- Testing with coverage reports
- Build with artifact publishing
- Automatic Dependabot PR merging
Usage:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-single.yml@main
with:
solution: "src/YourApp.sln"
secrets: inheritParameters:
Same as build-dotnet-fast.yml.
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
A comprehensive CI pipeline that runs tests across multiple operating systems (Windows, Linux, macOS) in a matrix strategy.
Features:
- All features from
build-dotnet-single.yml - Multi-OS testing (Windows, Linux, macOS)
- Configurable fail-fast behavior
- OS-specific test exclusions
Usage:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-matrix.yml@main
with:
solution: "src/YourApp.sln"
secrets: inheritParameters:
All parameters from build-dotnet-single.yml, plus:
| Parameter | Description | Required | Default |
|---|---|---|---|
disableTestsOnLinux |
Skip tests on Linux | ❌ | false |
disableTestsOnMacOs |
Skip tests on macOS | ❌ | false |
disableTestsOnWindows |
Skip tests on Windows | ❌ | false |
failFast |
Stop all jobs if one fails | ❌ | true |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
A deprecated/experimental workflow template. This workflow is currently set to fail on purpose and should not be used.
A workflow for publishing NuGet packages with manual approval. This workflow verifies a successful build on the main branch and requires manual approval before publishing to NuGet.
Features:
- Cross-workflow artifact downloading
- Build verification on main branch
- Manual approval via GitHub Environments
- Automatic package publishing to NuGet.org
- Automated release creation
Usage:
name: Publish to NuGet
on:
workflow_dispatch:
jobs:
publish:
uses: dailydevops/pipelines/.github/workflows/publish-nuget.yml@main
with:
artifactPattern: "release-packages-*"
workflowName: "build-dotnet-single.yml"
runId: "1234567890" # Get this from the workflow run you want to publish
environment: "nuget-production"
secrets:
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
WORKFLOW_PACKAGES: ${{ secrets.GITHUB_TOKEN }}Parameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
artifactPattern |
Pattern to match artifact names | ✅ | release-packages-* |
workflowName |
Workflow name to check for builds | ✅ | ci-dotnet.yml |
runId |
ID of workflow run to download artifacts from | ✅ | (none) |
environment |
GitHub Environment for manual approval | ✅ | nuget-production |
Note: Parameters marked as required have default values (except
runId), so you only need to specify them if you want to override the defaults. The defaultworkflowNamevalueci-dotnet.ymlis a legacy reference - you should explicitly specify your actual build workflow name (e.g.,build-dotnet-single.yml,build-dotnet-matrix.yml, orbuild-dotnet-fast.yml).
Secrets:
| Secret | Description | Required |
|---|---|---|
NUGET_TOKEN |
NuGet API key for publishing | ✅ |
WORKFLOW_PACKAGES |
GitHub token for workflow/artifact access | ✅ |
Prerequisites:
- GitHub Environment configured with manual approval reviewers
- Source workflow must produce NuGet package artifacts
- See Manual Approval Setup Guide for detailed setup instructions
These are individual job templates that can be composed into custom workflows or used independently.
Validates commit messages using commitlint to ensure they follow conventional commit standards.
Usage:
jobs:
commitlint:
uses: dailydevops/pipelines/.github/workflows/step-node-commitlint.yml@main
secrets: inheritParameters: None
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
Requirements:
.commitlintrcor similar configuration file in repository root
Detects the version of your application using GitVersion based on commit history and branching strategy.
Usage:
jobs:
version:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-version.yml@main
with:
dotnet-version: "8.x"
secrets: inherit
# Use the version in another job
another-job:
needs: version
runs-on: ubuntu-latest
steps:
- run: echo "Version is ${{ needs.version.outputs.solution-version }}"Parameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
dotnet-version |
.NET SDK version to install | ❌ | 8.x |
dotnet-quality |
.NET SDK quality channel | ❌ | ga |
runs-on |
Runner label | ❌ | ubuntu-latest |
Outputs:
| Output | Description |
|---|---|
solution-version |
Detected semantic version (e.g., 1.2.3) |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
Requirements:
GitVersion.ymlconfiguration file in repository root
Validates code formatting using CSharpier to ensure consistent code style.
Usage:
jobs:
format:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-format.yml@main
with:
dotnet-version: "8.x"
secrets: inheritParameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
dotnet-logging |
Verbosity level | ❌ | quiet |
dotnet-version |
.NET SDK version | ❌ | 8.x |
dotnet-quality |
.NET SDK quality channel | ❌ | ga |
runs-on |
Runner label | ❌ | ubuntu-latest |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
Requirements:
- CSharpier will be installed automatically
Builds the .NET solution and uploads build artifacts as release-packages.
Usage:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-build.yml@main
with:
solution: "src/YourApp.sln"
secrets: inheritParameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
solution |
Path to solution or project file | ✅ | |
disablePublish |
Skip uploading artifacts | ❌ | false |
dotnet-logging |
Verbosity level | ❌ | quiet |
dotnet-version |
.NET SDK version | ❌ | 8.x |
dotnet-quality |
.NET SDK quality channel | ❌ | ga |
runs-on |
Runner label | ❌ | ubuntu-latest |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository access
Artifacts:
release-packages: Contains built NuGet packages (if any)
Runs tests for the .NET solution with code coverage reporting.
Features:
- Test execution with coverage collection
- ReportGenerator for coverage reports
- Codecov integration
- Optional SonarQube support
- Optional Docker image cleanup for disk space
Usage:
jobs:
version:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-version.yml@main
secrets: inherit
test:
needs: version
uses: dailydevops/pipelines/.github/workflows/step-dotnet-tests.yml@main
with:
solution: "src/YourApp.sln"
solution-version: ${{ needs.version.outputs.solution-version }}
secrets: inheritParameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
solution |
Path to solution or project file | ✅ | |
solution-version |
Version from step-dotnet-version | ✅ | |
enableSonarQube |
Enable SonarQube analysis | ❌ | false |
enableCleanUpDockerDocker |
Free disk space | ❌ | false |
disableCoverageUpload |
Skip coverage artifacts | ❌ | false |
dotnet-logging |
Verbosity level | ❌ | quiet |
dotnet-version |
.NET SDK version | ❌ | 8.x |
dotnet-quality |
.NET SDK quality channel | ❌ | ga |
runs-on |
Runner label | ❌ | ubuntu-latest |
retry-max-attempts |
Max retry attempts | ❌ | 3 |
retry-timeout |
Timeout in minutes | ❌ | 15 |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository accessCODECOV_TOKEN(optional): Codecov token for coverage uploadSONAR_ORGANIZATION(optional): SonarQube organizationSONAR_PROJECT(optional): SonarQube project keySONAR_TOKEN(optional): SonarQube token
Artifacts:
reportgenerator-{os}-{hash}: Generated coverage reportscoverage-{os}-{hash}: Raw coverage data fileslogs-{os}-{hash}: Test logs and SARIF files
Creates or updates a draft release using Release Drafter when code is pushed to the main branch.
Usage:
jobs:
version:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-version.yml@main
secrets: inherit
release:
needs: version
uses: dailydevops/pipelines/.github/workflows/step-dotnet-draft-release.yml@main
with:
solution-version: ${{ needs.version.outputs.solution-version }}
secrets: inheritParameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
solution-version |
Version from step-dotnet-version | ✅ | |
runs-on |
Runner label | ❌ | ubuntu-latest |
Secrets:
FETCH_TOKEN(optional): GitHub token for private repository accessGITHUB_TOKEN(required): Automatically provided
Requirements:
.github/release-drafter.ymlconfiguration file- Only runs on pushes to
mainbranch (not pull requests)
Publishes NuGet packages from artifacts to NuGet.org with manual approval via GitHub Environments.
Usage:
jobs:
publish:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-publish-nuget.yml@main
with:
artifactPattern: "release-packages-*"
environment: "nuget-production"
runId: "123456789"
workflowName: "build-dotnet-single.yml"
secrets:
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
WORKFLOW_PACKAGES: ${{ secrets.GITHUB_TOKEN }}Parameters:
| Parameter | Description | Required | Default |
|---|---|---|---|
artifactPattern |
Pattern to match artifacts | ✅ | release-packages-* |
environment |
GitHub Environment for approval | ✅ | nuget-production |
runId |
Workflow run ID to download from | ✅ | |
workflowName |
Source workflow name | ✅ | ci-dotnet.yml |
Note: Parameters marked as required have default values (except
runId), so you only need to specify them if you want to override the defaults. The defaultworkflowNamevalueci-dotnet.ymlis a legacy reference - you should explicitly specify your actual build workflow name (e.g.,build-dotnet-single.yml,build-dotnet-matrix.yml, orbuild-dotnet-fast.yml).
Secrets:
| Secret | Description | Required |
|---|---|---|
NUGET_TOKEN |
NuGet API key | ✅ |
WORKFLOW_PACKAGES |
GitHub token for artifacts | ✅ |
Note: Consider using the higher-level publish-nuget.yml workflow instead for a more complete publishing solution.
Automatically merges Dependabot pull requests after successful CI checks.
Usage:
jobs:
dependabot:
if: github.actor == 'dependabot[bot]'
needs: [build, test] # Add your CI jobs here
uses: dailydevops/pipelines/.github/workflows/step-dependabot-merge.yml@main
secrets: inheritParameters: None
Secrets:
- All secrets are inherited from the calling workflow
- Requires appropriate
GITHUB_TOKENpermissions to merge PRs
Requirements:
- Only runs on pull requests from
dependabot[bot] - All required status checks must pass before merge
name: CI/CD
on:
push:
branches: [main]
pull_request:
jobs:
build-and-test:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-single.yml@main
with:
solution: "src/MyApp.sln"
secrets: inheritname: CI
on:
push:
branches: [main]
pull_request:
jobs:
build:
uses: dailydevops/pipelines/.github/workflows/build-dotnet-matrix.yml@main
with:
solution: "src/MyApp.sln"
disableTestsOnMacOs: true # Skip macOS if not needed
secrets: inheritname: Custom Pipeline
on:
push:
branches: [main]
pull_request:
jobs:
commitlint:
uses: dailydevops/pipelines/.github/workflows/step-node-commitlint.yml@main
secrets: inherit
version:
uses: dailydevops/pipelines/.github/workflows/step-dotnet-version.yml@main
secrets: inherit
format:
needs: [commitlint]
uses: dailydevops/pipelines/.github/workflows/step-dotnet-format.yml@main
secrets: inherit
test:
needs: [commitlint, version]
uses: dailydevops/pipelines/.github/workflows/step-dotnet-tests.yml@main
with:
solution: "src/MyApp.sln"
solution-version: ${{ needs.version.outputs.solution-version }}
secrets: inherit
build:
needs: [test, format]
uses: dailydevops/pipelines/.github/workflows/step-dotnet-build.yml@main
with:
solution: "src/MyApp.sln"
secrets: inherit
draft-release:
if: github.ref == 'refs/heads/main'
needs: [build, version]
uses: dailydevops/pipelines/.github/workflows/step-dotnet-draft-release.yml@main
with:
solution-version: ${{ needs.version.outputs.solution-version }}
secrets: inheritname: Publish to NuGet
on:
workflow_dispatch:
permissions:
actions: read
contents: write
jobs:
publish:
uses: dailydevops/pipelines/.github/workflows/publish-nuget.yml@main
with:
artifactPattern: "release-packages-*"
workflowName: "build-dotnet-single.yml"
runId: "1234567890" # Replace with actual workflow run ID
environment: "nuget-production"
secrets:
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
WORKFLOW_PACKAGES: ${{ secrets.GITHUB_TOKEN }}- Manual Approval Setup Guide - Detailed instructions for configuring GitHub Environments for manual approval workflows
Contributions are welcome! Please feel free to submit issues or pull requests.
When contributing:
- Ensure your changes are backwards compatible
- Update documentation for any parameter or behavior changes
- Follow conventional commit standards
- Test your changes in a real project before submitting
This project is licensed under the MIT License - see the LICENSE file for details.
Copyright (c) 2023-2025 Daily DevOps & .NET