My Workflow
Note: # description: A project to demonstrate using github actions for a .net core 3.1 project. Uses unit tests, json snapshots, database tests using docker service containers. Demonstrates their use in github actions, bitbucket, azure devops, and gitlab.
Submission Category:
Note: # Maintainer Must-Haves
Yaml File or Link to Code
lastlink / dotnet-ci-pipelines
dotnet ci cd pipelines for github, azure devops, gitlab, bitbucket, and etc.
DOTNET CORE CI PIPELINE EXAMPLE:
Goal to have dotnet core c# example pipelines for major git source control dev ops including github, azure devops, gitlab, bitbucket, and etc. Should auto run only on a new pull request, show test results in native ui per website, code coverage, and some additional manual steps running code quality analysis. Badge support native is also nice or from https://shields.io/category/build. Also will try service containers and database unit tests Originally off of gitlab-ci-example-dotnetcore.
Contribution
- Please do a pull request to the proper source control pipeline that you are trying to update.
TOC
[ ] GitHub Actions
-
limits 2,000 (per month) to 20 concurrent jobs support windows, ubuntu, mac
- doesn't currently support retry and max timeout although will cancel when limit reached.
- Badges - workflow
- api docs - docfx html only
- [!] Tests - noβ¦
name: .NET Core
# use https://marketplace.visualstudio.com/items?itemName=me-dutour-mathieu.vscode-github-actions to validate yml in vscode
env:
NUGET_PACKAGES_DIRECTORY: '.nupkg'
RESHARPER_CLI_NAME: 'JetBrains.ReSharper.CommandLineTools.Unix'
RESHARPER_CLI_VERSION: "2019.2.3"
DOCKER_DRIVER: overlay
CONTAINER_IMAGE: codeclimate/codeclimate
CONTAINER_TAG: '0.85.2'
rIds: ${{ secrets.rIds }}
dotnetVersion: 3.1.102
on:
pull_request:
branches:
- master
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: Build with dotnet
run: |
export DOTNET_CLI_TELEMETRY_OPTOUT=1
dotnet publish -c Release
- name: Tests
run: |
cp MyProject.Repository.Test/Data/appSettings.gitlab.json MyProject.Repository.Test/Data/AppSettings.json
dotnet test --logger "junit" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput='./TestResults/'
- name: Coverage Report
run: |
dotnet --version
dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools
./tools/reportgenerator "-reports:**/TestResults/coverage.opencover.xml;" "-targetdir:Reports" -reportTypes:TextSummary;
./tools/reportgenerator "-reports:**/TestResults/coverage.opencover.xml;" "-targetdir:Reports" -reportTypes:Html;
./tools/reportgenerator "-reports:**/TestResults/coverage.opencover.xml;" "-targetdir:Reports" -reportTypes:Badges;
cat ./Reports/Summary.txt
- uses: actions/upload-artifact@v1
with:
name: CodeCoverage
path: Reports
- name: Resharper Code Quality
run: |
# apt update && apt install -y curl zip unzip
curl -LO "https://download.jetbrains.com/resharper/ReSharperUltimate.$RESHARPER_CLI_VERSION/$RESHARPER_CLI_NAME.$RESHARPER_CLI_VERSION.zip"
unzip -q $RESHARPER_CLI_NAME.$RESHARPER_CLI_VERSION.zip -d "resharper"
mkdir -p CodeQuality
files=(*.sln)
sh ./resharper/dupfinder.sh "${files[0]}" --output=CodeQuality/dupfinderReport.html --format=Html
sh ./resharper/inspectcode.sh "${files[0]}" --output=CodeQuality/inspectcodeReport.html --format=Html
- uses: actions/upload-artifact@v1
with:
name: CodeQuality
path: CodeQuality
- name: prerelease
if: ${{ env.rIds }} != ''
run: |
echo 'build, obfuscate, and release'
dotnet tool install Obfuscar.GlobalTool --tool-path tools --version 2.2.28
bash scripts/extractRelease.sh
export rIds=${{ env.rIds }}
bash ./scripts/pipeline.sh
bash ./scripts/finalRelease.sh
- name: upload release
uses: actions/upload-artifact@v2
if: ${{ env.rIds }} != ''
with:
name: Release_unix
path: Release/post
build-win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: Build with dotnet
run: |
set DOTNET_CLI_TELEMETRY_OPTOUT=1
dotnet publish -c Release
- name: Tests
run: |
copy MyProject.Repository.Test/Data/appSettings.gitlab.json MyProject.Repository.Test/Data/AppSettings.json
dotnet test --logger "junit" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput='.\TestResults\'
- name: prerelease
if: ${{ env.rIds }} != ''
run: |
echo "build, obfuscate, and release"
dotnet tool install Obfuscar.GlobalTool --tool-path tools --version 2.2.28
.\scripts\extractRelease.cmd
set rIds=$env:rIds
.\scripts\pipeline.cmd
.\scripts\finalRelease.cmd
- name: upload release
uses: actions/upload-artifact@v2
if: ${{ env.rIds }} != ''
with:
name: Release_win
path: Release\post
unit_test_db_mssql:
runs-on: ubuntu-latest
# Service containers to run with `runner-job`
services:
# Label used to access the service container
localhost_mysql:
# Docker Hub image
image: mcr.microsoft.com/mssql/server:2019-latest
#
ports:
# Opens tcp port 6379 on the host and service container
- 1433:1433
env:
GIT_SUBMODULE_STRATEGY: recursive
ACCEPT_EULA: Y
SA_PASSWORD: yourStrong(!)Password
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: enabledb
run: cp ./MyProject.Repository.Test/Data/appSettings.bitbucket.mssql.json ./MyProject.Repository.Test/Data/AppSettings.json
- name: Tests
run: |
cd MyProject.Repository.Test
dotnet test --logger "junit" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput='./TestResults/'
unit_test_db_postgres:
runs-on: ubuntu-latest
# Service containers to run with `runner-job`
services:
# Label used to access the service container
redis:
# Docker Hub image
image: postgres:11
#
ports:
- 5432:5432
# Provide the password for postgres
env:
POSTGRES_DB: mockDb
POSTGRES_USER: postgres
POSTGRES_PASSWORD: "mysecretpassword"
POSTGRES_HOST_AUTH_METHOD: trust
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: enabledb
run: cp ./MyProject.Repository.Test/Data/appSettings.devops.postgres.json ./MyProject.Repository.Test/Data/AppSettings.json
- name: Tests
run: |
cd MyProject.Repository.Test
dotnet test --logger "junit" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput='./TestResults/'
unit_test_db_mysql:
runs-on: ubuntu-latest
# Service containers to run with `runner-job`
services:
# Label used to access the service container
redis:
# Docker Hub image
image: mysql:5.7.29
#
ports:
- 3306:3306
env:
MYSQL_DATABASE: "mockDb"
MYSQL_ROOT_PASSWORD: "mysecretpw"
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: enabledb
run: cp ./MyProject.Repository.Test/Data/appSettings.devops.mysql.json ./MyProject.Repository.Test/Data/AppSettings.json
- name: Tests
run: |
cd MyProject.Repository.Test
dotnet test --logger "junit" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput='./TestResults/'
code_docs:
runs-on: windows-latest
name: code documentation
steps:
- uses: actions/checkout@v1
- name: docfx
run: |
curl -LO "https://github.com/dotnet/docfx/releases/download/v2.48/docfx.zip"
powershell.exe -NoP -NonI -Command "Expand-Archive '.\docfx.zip' '.\docfx\'"
./docfx/docfx.exe
- uses: actions/upload-artifact@v1
with:
name: CodeDocs
path: _site
security:
runs-on: ubuntu-latest
name: Snyk Security Scan
steps:
- uses: actions/checkout@v1
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ env.dotnetVersion}}
- name: Build with dotnet
run: |
export DOTNET_CLI_TELEMETRY_OPTOUT=1
dotnet build
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/dotnet@master
with:
args: --file=MyProject.sln
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Additional Resources / Info
Note: # https://github.com/lastlink/dotnet-ci-pipelines/blob/master/.github/workflows/dotnetcore.yml
Note: # @lastlink
[Reminder]: # (Submissions are due on December 8th, 2021 (11:59 PM PT or 2 AM ET/6 AM UTC on December 9th).
Top comments (5)
Hi!
Really thanks for the article.
I am facing one issue in my project.
Scenario:- project repository is available in GitHub and we have an azure devops pipeline for ci-cd tasks.
The only thing is not working is auto trigger.. i want to run the pipeline whenever someone approves the PR for the branch main automatically.
Can someone help me with this issue by writing a yml code?
There arenβt triggers for approved pr. You can after an approved pr is merged have a trigger on the target branch like dev or master to auto run. If you have a pr trigger the pipeline will auto run when a pr is created and any changes pushed to the branch before the pipeline is merged. Another options is you can have manual approvals for stages in a pipeline that only run when approved. E.g. pr pipeline auto builds and runs tests, manual approval to deploy to dev.
I want to build something like that only, like when the code is merge to dev it should trigger the azure pipeline to start run.
Any help writing yaml will be helpful.
Hi!
Thanks for this info, it help me understand better.
But i was wondering if you could help me with this task:
I want to deploy to azure let say a solution with both webjobs, webapp, etc to azure everything is in .Net exept the front end that is in Angular.
And i want to have a pipeline that look lite this:
build, test (unit, integration)-> deploy to DEV -> Deploy to Qa -> Deply to Staging -> swap to production.
I want to have this kind of pipeline so that i cant test my donet app in dev, end if every is working send it to acc and so on and so on.
I have look in google, youtube etc. but it seem dificult to find this info for .net with gitlab.
In azure devops you can choose like build for .net and will get lot of predifine task, like restore the solutionm download nugets, build the solution and zip in in an artifac. also for deply to different stages. But with gitlab i dont fins such things.
Sorry for the lon text.
Thank you in advance. anoob in gitlab
Thank you for the article, need to save it later for further learning.