From c228fe74bf1118078fad6efaea5d2a57bb139e9d Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:08:31 +0100 Subject: [PATCH 1/8] Update publish workflow to create a github release before pushing to nuget. --- .github/scripts/build-and-pack-nuget.sh | 68 ++++++++++++++++++++----- .github/scripts/push-nuget-packages.sh | 44 +++++++++------- .github/workflows/publish-nuget.yml | 30 +++++------ 3 files changed, 97 insertions(+), 45 deletions(-) diff --git a/.github/scripts/build-and-pack-nuget.sh b/.github/scripts/build-and-pack-nuget.sh index 7cd485e6..2b801370 100644 --- a/.github/scripts/build-and-pack-nuget.sh +++ b/.github/scripts/build-and-pack-nuget.sh @@ -87,17 +87,49 @@ while [ -n "$REMAINING_PROJECTS" ] && [ $ITERATION -lt $MAX_ITERATIONS ]; do while IFS= read -r project; do if [ -z "$project" ]; then continue; fi PROJECT_NAME=$(basename $(dirname "$project")) - echo "Building $PROJECT_NAME..." - - # Restore with local feed for dependencies from previous iterations - dotnet restore "$project" -p:Configuration=Release --verbosity minimal --force --no-cache - - # Build the project - dotnet build "$project" --configuration Release --no-restore --verbosity minimal - - # Pack directly to artifacts with project name folder structure for proper NuGet feed - dotnet pack "$project" --configuration Release --no-build --output "./artifacts/${PROJECT_NAME}" -p:PACK=true --verbosity minimal - + + # Get the version from the project file by evaluating MSBuild properties + VERSION=$(dotnet msbuild "$project" -getProperty:Version -p:Configuration=Release 2>/dev/null | tail -1) + + if [ -z "$VERSION" ]; then + echo "❌ ERROR: Could not extract version from $PROJECT_NAME, skipping" + echo " Make sure the project has a property defined" + SHOULD_BUILD=false + else + echo "Checking if $PROJECT_NAME $VERSION exists on NuGet.org..." + + # Query NuGet API to check if this version exists + API_URL="https://api.nuget.org/v3/registration5-semver1/${PROJECT_NAME,,}/index.json" + + if response=$(curl -s -f "$API_URL" 2>/dev/null); then + # Check if the specific version exists in the response + if echo "$response" | grep -q "\"$VERSION\""; then + echo " ⚪ Already exists on NuGet.org, skipping build" + SHOULD_BUILD=false + else + echo " 🟢 New version, will build" + SHOULD_BUILD=true + fi + else + # Package ID doesn't exist at all, so this version is definitely new + echo " 🟢 New package, will build" + SHOULD_BUILD=true + fi + fi + + if [ "$SHOULD_BUILD" = true ]; then + echo "Building $PROJECT_NAME..." + + # Restore with local feed for dependencies from previous iterations + dotnet restore "$project" -p:Configuration=Release --verbosity minimal --force --no-cache + + # Build the project + dotnet build "$project" --configuration Release --no-restore --verbosity minimal + + # Pack directly to artifacts with project name folder structure for proper NuGet feed + dotnet pack "$project" --configuration Release --no-build --output "./artifacts/${PROJECT_NAME}" -p:PACK=true --verbosity minimal + fi + BUILT_PROJECTS="${BUILT_PROJECTS}${PROJECT_NAME};" done < <(echo "$PROJECTS_TO_BUILD" | tr ';' '\n') @@ -112,5 +144,17 @@ if [ $ITERATION -eq $MAX_ITERATIONS ]; then exit 1 fi +PACKAGE_COUNT=$(ls ./artifacts/*/*.nupkg 2>/dev/null | wc -l) + +if [ $PACKAGE_COUNT -eq 0 ]; then + echo "" + echo "No new packages to release (all packages are up-to-date)" + exit 1 +fi + echo "" -echo "Successfully created $(ls ./artifacts/*/*.nupkg 2>/dev/null | wc -l) packages" \ No newline at end of file +echo "=== Build Summary ===" +echo "Successfully created $PACKAGE_COUNT new package(s)" +echo "Creating release archive with new packages..." +find ./artifacts -name "*.nupkg" | zip -j "artifacts/Packages.zip" -@ +echo "Created: artifacts/Packages.zip" \ No newline at end of file diff --git a/.github/scripts/push-nuget-packages.sh b/.github/scripts/push-nuget-packages.sh index bbce31aa..e4cbf41e 100644 --- a/.github/scripts/push-nuget-packages.sh +++ b/.github/scripts/push-nuget-packages.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -# Script to push NuGet packages and create a .zip file with all uploaded packages +# Script to push NuGet packages to NuGet.org # Usage: ./push-nuget-packages.sh [--mock] MOCK_MODE=false @@ -19,30 +19,25 @@ done echo "==================================" UPLOADED_COUNT=0 -SKIPPED_COUNT=0 +CONFLICT_COUNT=0 FAILED_COUNT=0 -UPLOADED_PACKAGES="" for package in ./artifacts/*/*.nupkg; do PACKAGE_NAME=$(basename "$package") echo "Attempting to push: $PACKAGE_NAME" if [[ "$MOCK_MODE" == "true" ]]; then - UPLOADED_PACKAGES="$UPLOADED_PACKAGES$package -" echo "🟢 Successfully uploaded (mocked): $PACKAGE_NAME" UPLOADED_COUNT=$((UPLOADED_COUNT + 1)) elif output=$(dotnet nuget push "$package" \ --api-key "$NUGET_API_KEY" \ --source "https://api.nuget.org/v3/index.json" 2>&1); then - UPLOADED_PACKAGES="$UPLOADED_PACKAGES$package -" echo "🟢 Successfully uploaded: $PACKAGE_NAME" UPLOADED_COUNT=$((UPLOADED_COUNT + 1)) else if echo "$output" | grep -q "409 (Conflict"; then - echo "⚪ Already exists: $PACKAGE_NAME" - SKIPPED_COUNT=$((SKIPPED_COUNT + 1)) + echo "🟡 Conflict (already exists): $PACKAGE_NAME" + CONFLICT_COUNT=$((CONFLICT_COUNT + 1)) else echo "🔴 Failed to upload: $PACKAGE_NAME" echo " Error: $output" @@ -54,16 +49,29 @@ done echo "" echo "=== Upload Summary ===" echo "Successfully uploaded: $UPLOADED_COUNT packages" -echo "Already existed: $SKIPPED_COUNT packages" +echo "Conflicts (409): $CONFLICT_COUNT packages" echo "Failed uploads: $FAILED_COUNT packages" -if [ $UPLOADED_COUNT -gt 0 ]; then +# Fail if any errors were encountered +TOTAL_FAILED=$((FAILED_COUNT + CONFLICT_COUNT)) + +if [ $TOTAL_FAILED -gt 0 ]; then + echo "" + if [ $CONFLICT_COUNT -gt 0 ]; then + echo "❌ ERROR: $TOTAL_FAILED package(s) failed to upload (of which $CONFLICT_COUNT were conflicts)" + echo "Note: Conflicts should not happen as build-and-pack-nuget.sh filters existing packages." + else + echo "❌ ERROR: $FAILED_COUNT package(s) failed to upload" + fi + exit 1 +fi + +if [ $UPLOADED_COUNT -eq 0 ]; then echo "" - echo "Creating release archive..." - echo "$UPLOADED_PACKAGES" | zip -j "artifacts/Packages.zip" -@ - echo "Created: artifacts/Packages.zip" - exit 0 -else - echo "No packages were successfully uploaded" + echo "❌ ERROR: No packages were successfully uploaded" exit 1 -fi \ No newline at end of file +fi + +echo "" +echo "✅ Successfully pushed $UPLOADED_COUNT package(s) to NuGet.org" +exit 0 \ No newline at end of file diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index 6d099b4d..9b1b7633 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -36,6 +36,20 @@ jobs: chmod +x .github/scripts/build-and-pack-nuget.sh .github/scripts/build-and-pack-nuget.sh + - name: Set release date + run: | + echo "RELEASE_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV + echo "RELEASE_TAG=v$(date +%Y.%-m.%-d)" >> $GITHUB_ENV + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2.3.2 + with: + name: War3Net Release ${{ env.RELEASE_DATE }} + tag_name: ${{ env.RELEASE_TAG }} + files: | + ./artifacts/Packages.zip + draft: ${{ github.ref_name != 'master' }} + - name: NuGet login uses: NuGet/login@v1 id: login @@ -51,18 +65,4 @@ jobs: .github/scripts/push-nuget-packages.sh fi env: - NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }} - - - name: Set release date - run: | - echo "RELEASE_DATE=$(date +%Y-%m-%d)" >> $GITHUB_ENV - echo "RELEASE_TAG=v$(date +%Y.%-m.%-d)" >> $GITHUB_ENV - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2.3.2 - with: - name: War3Net Release ${{ env.RELEASE_DATE }} - tag_name: ${{ env.RELEASE_TAG }} - files: | - ./artifacts/Packages.zip - draft: ${{ github.ref_name != 'master' }} \ No newline at end of file + NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }} \ No newline at end of file From 8c64225682117b27f7f7e31bb41dae97ffa34496 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:14:01 +0100 Subject: [PATCH 2/8] Fix package ID --- .github/scripts/build-and-pack-nuget.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/scripts/build-and-pack-nuget.sh b/.github/scripts/build-and-pack-nuget.sh index 2b801370..fe95450d 100644 --- a/.github/scripts/build-and-pack-nuget.sh +++ b/.github/scripts/build-and-pack-nuget.sh @@ -88,18 +88,24 @@ while [ -n "$REMAINING_PROJECTS" ] && [ $ITERATION -lt $MAX_ITERATIONS ]; do if [ -z "$project" ]; then continue; fi PROJECT_NAME=$(basename $(dirname "$project")) - # Get the version from the project file by evaluating MSBuild properties + # Get the version and PackageId from the project file by evaluating MSBuild properties VERSION=$(dotnet msbuild "$project" -getProperty:Version -p:Configuration=Release 2>/dev/null | tail -1) + PACKAGE_ID=$(dotnet msbuild "$project" -getProperty:PackageId -p:Configuration=Release 2>/dev/null | tail -1) + + # If PackageId is not set, fall back to project name + if [ -z "$PACKAGE_ID" ]; then + PACKAGE_ID="$PROJECT_NAME" + fi if [ -z "$VERSION" ]; then echo "❌ ERROR: Could not extract version from $PROJECT_NAME, skipping" echo " Make sure the project has a property defined" SHOULD_BUILD=false else - echo "Checking if $PROJECT_NAME $VERSION exists on NuGet.org..." + echo "Checking if $PACKAGE_ID $VERSION exists on NuGet.org..." # Query NuGet API to check if this version exists - API_URL="https://api.nuget.org/v3/registration5-semver1/${PROJECT_NAME,,}/index.json" + API_URL="https://api.nuget.org/v3/registration5-semver1/${PACKAGE_ID,,}/index.json" if response=$(curl -s -f "$API_URL" 2>/dev/null); then # Check if the specific version exists in the response From ec6e27e2bd12f7838d60a906cf273d01f34f9e2e Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:15:59 +0100 Subject: [PATCH 3/8] AI says this should fix the 403 --- .github/workflows/publish-nuget.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish-nuget.yml b/.github/workflows/publish-nuget.yml index 9b1b7633..ba75f2d7 100644 --- a/.github/workflows/publish-nuget.yml +++ b/.github/workflows/publish-nuget.yml @@ -10,6 +10,7 @@ env: DOTNET_CLI_TELEMETRY_OPTOUT: true permissions: + contents: write id-token: write jobs: @@ -17,6 +18,7 @@ jobs: runs-on: ubuntu-latest permissions: + contents: write id-token: write steps: From 94f97bdbbdd08294fc3a11d038bfff4f5a74c076 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:18:07 +0100 Subject: [PATCH 4/8] Temporarily update version to test workflow --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6b76cede..405e3435 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,7 +40,7 @@ 5.8.0 0.1.0 5.8.0 - 5.8.0 + 5.8.1 0.1.0 5.8.0 5.8.1 From 2f0a7c5fe389e0616223366cbe07ba9804da8e21 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:26:57 +0100 Subject: [PATCH 5/8] Seems like this is required when skipping package builds. --- .github/scripts/build-and-pack-nuget.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/scripts/build-and-pack-nuget.sh b/.github/scripts/build-and-pack-nuget.sh index fe95450d..2bab4645 100644 --- a/.github/scripts/build-and-pack-nuget.sh +++ b/.github/scripts/build-and-pack-nuget.sh @@ -4,6 +4,9 @@ set -e # Script to build and pack NuGet packages in dependency order # Usage: ./build-and-pack-nuget.sh +# Create artifacts directory for local NuGet feed +mkdir -p ./artifacts + # Get all packable projects from the solution filter # Extract project paths from the solution filter and convert Windows paths to Unix paths PROJECTS=$(jq -r '.solution.projects[]' War3NetPublish.slnf | sed 's/\\/\//g' | grep -v "Tests" | tr '\n' ';') From d76e79e4d940877e30986909f6c6e536b6371ca7 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:28:31 +0100 Subject: [PATCH 6/8] Add flag to build script for pack-nuget (PR build-only) workflow. --- .github/scripts/build-and-pack-nuget.sh | 88 ++++++++++++++----------- .github/workflows/pack-nuget.yml | 2 +- 2 files changed, 52 insertions(+), 38 deletions(-) diff --git a/.github/scripts/build-and-pack-nuget.sh b/.github/scripts/build-and-pack-nuget.sh index 2bab4645..033dbef7 100644 --- a/.github/scripts/build-and-pack-nuget.sh +++ b/.github/scripts/build-and-pack-nuget.sh @@ -2,7 +2,10 @@ set -e # Script to build and pack NuGet packages in dependency order -# Usage: ./build-and-pack-nuget.sh +# Usage: ./build-and-pack-nuget.sh [--skip-version-check] + +SKIP_VERSION_CHECK=false +[[ "$1" == "--skip-version-check" ]] && SKIP_VERSION_CHECK=true # Create artifacts directory for local NuGet feed mkdir -p ./artifacts @@ -91,38 +94,44 @@ while [ -n "$REMAINING_PROJECTS" ] && [ $ITERATION -lt $MAX_ITERATIONS ]; do if [ -z "$project" ]; then continue; fi PROJECT_NAME=$(basename $(dirname "$project")) - # Get the version and PackageId from the project file by evaluating MSBuild properties - VERSION=$(dotnet msbuild "$project" -getProperty:Version -p:Configuration=Release 2>/dev/null | tail -1) - PACKAGE_ID=$(dotnet msbuild "$project" -getProperty:PackageId -p:Configuration=Release 2>/dev/null | tail -1) - - # If PackageId is not set, fall back to project name - if [ -z "$PACKAGE_ID" ]; then - PACKAGE_ID="$PROJECT_NAME" - fi - - if [ -z "$VERSION" ]; then - echo "❌ ERROR: Could not extract version from $PROJECT_NAME, skipping" - echo " Make sure the project has a property defined" - SHOULD_BUILD=false + # Check if we should skip version checking (for PR validation) + if [ "$SKIP_VERSION_CHECK" = true ]; then + echo "Building $PROJECT_NAME (version check skipped)..." + SHOULD_BUILD=true else - echo "Checking if $PACKAGE_ID $VERSION exists on NuGet.org..." + # Get the version and PackageId from the project file by evaluating MSBuild properties + VERSION=$(dotnet msbuild "$project" -getProperty:Version -p:Configuration=Release 2>/dev/null | tail -1) + PACKAGE_ID=$(dotnet msbuild "$project" -getProperty:PackageId -p:Configuration=Release 2>/dev/null | tail -1) - # Query NuGet API to check if this version exists - API_URL="https://api.nuget.org/v3/registration5-semver1/${PACKAGE_ID,,}/index.json" + # If PackageId is not set, fall back to project name + if [ -z "$PACKAGE_ID" ]; then + PACKAGE_ID="$PROJECT_NAME" + fi - if response=$(curl -s -f "$API_URL" 2>/dev/null); then - # Check if the specific version exists in the response - if echo "$response" | grep -q "\"$VERSION\""; then - echo " ⚪ Already exists on NuGet.org, skipping build" - SHOULD_BUILD=false + if [ -z "$VERSION" ]; then + echo "❌ ERROR: Could not extract version from $PROJECT_NAME, skipping" + echo " Make sure the project has a property defined" + SHOULD_BUILD=false + else + echo "Checking if $PACKAGE_ID $VERSION exists on NuGet.org..." + + # Query NuGet API to check if this version exists + API_URL="https://api.nuget.org/v3/registration5-semver1/${PACKAGE_ID,,}/index.json" + + if response=$(curl -s -f "$API_URL" 2>/dev/null); then + # Check if the specific version exists in the response + if echo "$response" | grep -q "\"$VERSION\""; then + echo " ⚪ Already exists on NuGet.org, skipping build" + SHOULD_BUILD=false + else + echo " 🟢 New version, will build" + SHOULD_BUILD=true + fi else - echo " 🟢 New version, will build" + # Package ID doesn't exist at all, so this version is definitely new + echo " 🟢 New package, will build" SHOULD_BUILD=true fi - else - # Package ID doesn't exist at all, so this version is definitely new - echo " 🟢 New package, will build" - SHOULD_BUILD=true fi fi @@ -155,15 +164,20 @@ fi PACKAGE_COUNT=$(ls ./artifacts/*/*.nupkg 2>/dev/null | wc -l) -if [ $PACKAGE_COUNT -eq 0 ]; then - echo "" - echo "No new packages to release (all packages are up-to-date)" - exit 1 -fi - echo "" echo "=== Build Summary ===" -echo "Successfully created $PACKAGE_COUNT new package(s)" -echo "Creating release archive with new packages..." -find ./artifacts -name "*.nupkg" | zip -j "artifacts/Packages.zip" -@ -echo "Created: artifacts/Packages.zip" \ No newline at end of file +echo "Successfully created $PACKAGE_COUNT package(s)" + +# Only create zip and check for updates when NOT skipping version check +if [ "$SKIP_VERSION_CHECK" = false ]; then + if [ $PACKAGE_COUNT -eq 0 ]; then + echo "" + echo "No new packages to release (all packages are up-to-date)" + exit 1 + fi + + echo "" + echo "Creating release archive with new packages..." + find ./artifacts -name "*.nupkg" | zip -j "artifacts/Packages.zip" -@ + echo "Created: artifacts/Packages.zip" +fi \ No newline at end of file diff --git a/.github/workflows/pack-nuget.yml b/.github/workflows/pack-nuget.yml index 532f5d3d..c5469c65 100644 --- a/.github/workflows/pack-nuget.yml +++ b/.github/workflows/pack-nuget.yml @@ -30,4 +30,4 @@ jobs: - name: Build and pack in dependency order run: | chmod +x .github/scripts/build-and-pack-nuget.sh - .github/scripts/build-and-pack-nuget.sh \ No newline at end of file + .github/scripts/build-and-pack-nuget.sh --skip-version-check \ No newline at end of file From 8227ca59dff3a0392af27b9a8a5bb92559ecabd7 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:31:12 +0100 Subject: [PATCH 7/8] Update package source mapping to allow getting up-to-date/skipped packages to be restored from nuget. --- NuGet.config | 1 + 1 file changed, 1 insertion(+) diff --git a/NuGet.config b/NuGet.config index b9dffb44..c4feff89 100644 --- a/NuGet.config +++ b/NuGet.config @@ -27,6 +27,7 @@ + \ No newline at end of file From 74c8e33c4e7fd8bcb923db40be560dc7cd223710 Mon Sep 17 00:00:00 2001 From: Drake53 <49623303+Drake53@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:33:53 +0100 Subject: [PATCH 8/8] Revert version bump for testing purposes --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 405e3435..6b76cede 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,7 +40,7 @@ 5.8.0 0.1.0 5.8.0 - 5.8.1 + 5.8.0 0.1.0 5.8.0 5.8.1