Skip to content

.NET Build, Test & Publish #14

.NET Build, Test & Publish

.NET Build, Test & Publish #14

Workflow file for this run

name: .NET Build, Test & Publish
on:
push:
tags:
- '*'
workflow_dispatch:
env:
configuration: 'Release'
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
PACKAGE_ID: 'Valuify'
solution: 'Valuify.sln'
permissions:
packages: write
jobs:
build:
name: Build, Test & Publish
runs-on: windows-latest
outputs:
semantic: ${{ steps.extract-version.outputs.semantic }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Use .NET SDKs
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
9.0.x
- name: Cache NuGet Packages
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore NuGet Packages
run: dotnet restore ${{ env.solution }}
- name: Extract and Format Version from Tag
id: extract-version
shell: bash
run: |
# If push event with refs/tags, parse that. Otherwise, fallback to describing the last tag found.
if [[ "$GITHUB_REF" =~ ^refs/tags/ ]]; then
rawTag="${GITHUB_REF#refs/tags/}"
else
rawTag="$(git describe --tags $(git rev-list --tags --max-count=1) 2>/dev/null || echo "")"
fi
# If there's no real tag, rawTag might be empty on a manual run
if [ -z "$rawTag" ]; then
echo "No tag found - setting semantic=0.0.0"
semantic="0.0.0"
else
# Remove a leading 'v' if present
semantic="${rawTag#v}"
fi
numeric="${semantic%%-*}.0"
echo "version=$numeric" >> $GITHUB_ENV
echo "semantic=$semantic" >> $GITHUB_ENV
echo "informational=$rawTag" >> $GITHUB_ENV
echo "semantic=$semantic" >> $GITHUB_OUTPUT
- name: Build Solution
run: dotnet build ${{ env.solution }} --configuration ${{ env.configuration }} --no-restore -p:AssemblyVersion=${{ env.version }} -p:FileVersion=${{ env.version }} -p:InformationalVersion=${{ env.informational }} -p:PackageVersion=${{ env.semantic }} -p:Version=${{ env.version }}
- name: Test Solution
run: dotnet test ${{ env.solution }} --configuration ${{ env.configuration }} --no-build
- name: Upload Code Coverage
if: ${{ github.event_name == 'push' }}
uses: codecov/codecov-action@1e68e06f1dbfde0e4cefc87efeba9e4643565303
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Pack Solution
if: ${{ github.event_name == 'push' }}
run: dotnet pack ${{ env.solution }} --configuration ${{ env.configuration }} --no-build --output ./artifacts -p:Version=${{ env.semantic }}
- name: Publish Packages to GitHub
if: ${{ github.event_name == 'push' }}
run: dotnet nuget push **/{{ env.PACKAGE_ID }}*.nupkg --source "https://nuget.pkg.github.com/MooVC/index.json" --api-key ${{ secrets.GITHUB_TOKEN }} --skip-duplicate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish Packages to NuGet
if: ${{ github.event_name == 'push' }}
run: dotnet nuget push **/{{ env.PACKAGE_ID }}*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate
post-deployment:
name: Post Deployment
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Wait for 5 Minutes
if: ${{ github.event_name == 'push' }}
shell: bash
run: |
echo "Waiting for 5 minutes with periodic updates..."
total=300
interval=10
elapsed=0
while [ $elapsed -lt $total ]
do
echo "Elapsed $elapsed seconds..."
sleep $interval
elapsed=$((elapsed + interval))
done
echo "Wait complete. Checking packages..."
- name: Deprecate/Unlist Older Packages
shell: bash
env:
PACKAGE_ID: ${{ env.PACKAGE_ID }}
SKIP_VERSION: ${{ needs.build.outputs.semantic }}
NUGET_FEED: "https://api.nuget.org/v3/index.json"
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
set -e
# If we have "0.0.0", presumably no real tag was found during manual run
if [ "$SKIP_VERSION" = "0.0.0" ]; then
echo "No real version found, skipping deprecation/unlisting."
exit 0
fi
echo "Package ID: $PACKAGE_ID"
echo "Skip Version (newly published): $SKIP_VERSION"
# Decide if skip-version is release or prerelease
isRelease=true
if [[ "$SKIP_VERSION" == *"-"* ]]; then
isRelease=false
fi
# Get registration info
registrationJson=$(curl -s "https://api.nuget.org/v3/registration5-semver1/${PACKAGE_ID}/index.json")
if [ -z "$registrationJson" ]; then
echo "No data returned from registration endpoint."
exit 0
fi
combinedData=$(echo "$registrationJson" | jq -r '
.items[]?.items[]? as $entry
| [
$entry.catalogEntry.version,
(if $entry.catalogEntry.listed then "true" else "false" end),
(if $entry.catalogEntry.deprecation then "deprecated" else "null" end)
]
| join("|")
')
if [ -z "$combinedData" ]; then
echo "No published versions found for $PACKAGE_ID."
exit 0
fi
while IFS= read -r row; do
ver=$(echo "$row" | cut -d'|' -f1)
isListed=$(echo "$row" | cut -d'|' -f2)
isDeprecated=$(echo "$row" | cut -d'|' -f3)
# Always skip the newly published version
if [ "$ver" = "$SKIP_VERSION" ]; then
echo "Skipping newly published version $ver."
continue
fi
if [[ "$ver" == *"-"* ]]; then
# Prerelease => unlist if still listed
if [ "$isListed" = "true" ]; then
echo "Unlisting older prerelease $ver..."
dotnet nuget delete "$PACKAGE_ID" "$ver" \
--source "$NUGET_FEED" \
--api-key "$NUGET_API_KEY" \
--non-interactive || echo "Could not unlist $ver."
else
echo "Prerelease $ver is already unlisted."
fi
else
# Release => deprecate if skip-version is release
if [ "$isRelease" = true ]; then
if [ "$isDeprecated" = "null" ]; then
echo "Deprecating older release $ver..."
dotnet nuget deprecate "$PACKAGE_ID" \
--version "$ver" \
--source "$NUGET_FEED" \
--api-key "$NUGET_API_KEY" \
--reason Other \
--message "Superseded by $SKIP_VERSION" \
--non-interactive || echo "Deprecation failed for $ver."
else
echo "Release $ver is already deprecated."
fi
else
echo "Found release $ver, but skip-version is prerelease => no action."
fi
fi
done <<< "$combinedData"
echo "Done!"