I have a dotnet project and am trying to build a CI/CD pipeline that does the following using Github Actions:
So far, I have this workflow that builds and tests my project. This seems to work nicely. However, it also has a publish step, which never seems to be run (I guess the if
is wrong(?)) and I'm really not sure where to start with the SemVer part of what I want.
name: .NET Build, Test and Publish
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
env:
DISCOS_API_KEY: ${{ secrets.DISCOS_API_KEY }}
DISCOS_API_URL: http://localhost:3000/api/
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Build docker stack
run: docker-compose -f src/DISCOSweb-Sdk/DISCOSweb-Sdk.Tests/docker-compose.yml up -d --force-recreate --build
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.x
- name: Restore dependencies
run: dotnet restore src/DISCOSweb-Sdk/DISCOSweb-Sdk.sln
- name: Build
run: dotnet build --no-restore src/DISCOSweb-Sdk/DISCOSweb-Sdk.sln
- name: Test
run: dotnet test --no-build --verbosity normal src/DISCOSweb-Sdk/DISCOSweb-Sdk.sln
publish: # This stage is never run
if: github.event.pull_request.merged == 'true'
needs: build
runs-on: ubuntu-latest
steps:
- name: Publish
id: publish_nuget
uses: brandedoutcast/publish-nuget@v2
with:
PACKAGE_NAME: DISCOSweb-Sdk
PROJECT_FILE_PATH: "**/DISCOSweb-Sdk.csproj"
BUILD_CONFIGURATION: Release
NUGET_KEY: ${{secrets.NUGET_KEY}}
VERSION_STATIC: 1.0.0 # Replace with something better
I feel like this should be a relatively common and straightforward thing to do so any assistance would be really appreciated.
I managed to accomplish this by splitting my CI and CD workflows, and making use of some very helpful packages.
CI Workflow
This first workflow runs on PRs and pushes to master. It's worth noting that when branch protection is on, a push to master is synonymous with a merged PR.
name: .NET Continuous Integration
on:
pull_request:
branches: [ master ]
push:
branches: [ master ]
jobs:
test:
name: Test Project (Mock API)
runs-on: ubuntu-latest
env:
DISCOS_API_KEY: ${{ secrets.DISCOS_API_KEY }}
DISCOS_API_URL: http://localhost:3000/api/
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Build docker stack
run: docker-compose -f ./src/DiscosWebSdk/DiscosWebSdk.Tests/docker-compose.yml up -d --force-recreate --build
- name: Run tests against mock API
run: dotnet test --logger GitHubActions ./src/DiscosWebSdk/DiscosWebSdk.sln
CD Workflow
There's a bit more to the CD workflow. It runs on pushes to master but only when there are changes made to the folder containing the actual source code for the SDK (that's what the paths
block does).
I then used the mathieudutour/github-tag-action@v6.0
action to tag the commit with a calculated semantic version (calculated using conventional commits).
The package build is then tagged with this version using the -p:PackageVersion=${{ steps.tag_version.outputs.new_version }}
option on dotnet nuget pack
.
The ncipollo/release-action@v1
also creates a release on Github.
Finally, building and pushing the release to Github and Nuget is done using dotnet nuget push
as usual.
name: .NET Continuous Deployment
on:
push:
branches: [ master ]
paths:
- src/DiscosWebSdk/DiscosWebSdk/**
workflow_dispatch:
jobs:
test:
name: Test Project (Real API)
runs-on: ubuntu-latest
env:
DISCOS_API_KEY: ${{ secrets.DISCOS_API_KEY }}
DISCOS_API_URL: https://discosweb.esoc.esa.int/api/
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Test against real API
run: dotnet test --logger GitHubActions ./src/DiscosWebSdk/DiscosWebSdk.sln
semantic-release:
needs: test
name: Create a Package Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3 # Need the full commit history for conventional commit
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Bump version and push tag
id: tag_version
uses: mathieudutour/github-tag-action@v6.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Create a GitHub release
uses: ncipollo/release-action@v1
with:
tag: ${{ steps.tag_version.outputs.new_tag }}
name: Release ${{ steps.tag_version.outputs.new_tag }}
body: ${{ steps.tag_version.outputs.changelog }}
- name: Create Nuget Package
run: dotnet build -c Release ./src/DiscosWebSdk/DiscosWebSdk/DiscosWebSdk.csproj && dotnet pack -c Release -p:PackageVersion=${{ steps.tag_version.outputs.new_version }} -o . ./src/DiscosWebSdk/DiscosWebSdk/DiscosWebSdk.csproj
- name: Upload Package for Publishing
uses: actions/upload-artifact@v3
with:
name: PackedLib
path: ./*.nupkg
github-publish:
needs: semantic-release
name: Publish to Github
runs-on: ubuntu-latest
steps:
- name: Download built project
uses: actions/download-artifact@v3
with:
name: PackedLib
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Push Package to GitHub
run: dotnet nuget push --api-key ${{secrets.GITHUB_TOKEN}} --source "https://nuget.pkg.github.com/hughesjs/index.json" *.nupkg
nuget-publish:
needs: semantic-release
name: Publish to Nuget
runs-on: ubuntu-latest
steps:
- name: Download built project
uses: actions/download-artifact@v3
with:
name: PackedLib
- name: Setup .NET
uses: actions/setup-dotnet@v2
with:
dotnet-version: 6.0.x
- name: Push Package to Nuget
run: dotnet nuget push --api-key ${{secrets.NUGET_KEY}} --source "https://api.nuget.org/v3/index.json" *.nupkg