.NET Build, Test & Publish #14
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!" |