From a8a23e9c2fd4a6cf67510bf3b262494ab3d57594 Mon Sep 17 00:00:00 2001 From: Chad Payne Date: Thu, 12 Mar 2026 23:02:58 -0600 Subject: [PATCH 1/2] Add CI/CD workflows for PR validation and release automation - build.yml: validates PRs against main with dotnet build - release.yml: builds, packages ZIP, creates GitHub Release on merge to main - IceSkates.csproj: conditional CopyToMods target so CI builds don't fail Co-Authored-By: Claude Opus 4.6 --- .github/workflows/build.yml | 41 +++++++++++++++++ .github/workflows/release.yml | 83 +++++++++++++++++++++++++++++++++++ IceSkates.csproj | 2 +- 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f03cb7a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,41 @@ +name: Build + +on: + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Cache VS DLLs + id: cache + uses: actions/cache@v4 + with: + path: ~/vs-game + key: vs-game-1.21.6 + + - name: Download VS DLLs + if: steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ~/vs-game/Mods ~/vs-game/Lib /tmp/vs-extract + curl -sSL https://cdn.vintagestory.at/gamefiles/stable/vs_client_linux-x64_1.21.6.tar.gz \ + | tar xz -C /tmp/vs-extract + VS_ROOT=$(find /tmp/vs-extract -name "VintagestoryAPI.dll" -printf '%h\n' -quit) + cp "$VS_ROOT"/VintagestoryAPI.dll ~/vs-game/ + cp "$VS_ROOT"/VintagestoryLib.dll ~/vs-game/ + cp "$VS_ROOT"/Vintagestory.dll ~/vs-game/ + cp "$VS_ROOT"/Mods/VSSurvivalMod.dll ~/vs-game/Mods/ + cp "$VS_ROOT"/Lib/SkiaSharp.dll ~/vs-game/Lib/ + cp "$VS_ROOT"/Lib/Newtonsoft.Json.dll ~/vs-game/Lib/ + rm -rf /tmp/vs-extract + + - name: Build + run: dotnet build -c Release -p:VintageStoryPath=$HOME/vs-game diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..9c8e95b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,83 @@ +name: Release + +on: + push: + branches: [main] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract version + id: version + run: echo "version=$(jq -r .version modinfo.json)" >> "$GITHUB_OUTPUT" + + - name: Check if release exists + id: check + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh release view "v${{ steps.version.outputs.version }}" > /dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Setup .NET + if: steps.check.outputs.exists == 'false' + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Cache VS DLLs + if: steps.check.outputs.exists == 'false' + id: cache + uses: actions/cache@v4 + with: + path: ~/vs-game + key: vs-game-1.21.6 + + - name: Download VS DLLs + if: steps.check.outputs.exists == 'false' && steps.cache.outputs.cache-hit != 'true' + run: | + mkdir -p ~/vs-game/Mods ~/vs-game/Lib /tmp/vs-extract + curl -sSL https://cdn.vintagestory.at/gamefiles/stable/vs_client_linux-x64_1.21.6.tar.gz \ + | tar xz -C /tmp/vs-extract + VS_ROOT=$(find /tmp/vs-extract -name "VintagestoryAPI.dll" -printf '%h\n' -quit) + cp "$VS_ROOT"/VintagestoryAPI.dll ~/vs-game/ + cp "$VS_ROOT"/VintagestoryLib.dll ~/vs-game/ + cp "$VS_ROOT"/Vintagestory.dll ~/vs-game/ + cp "$VS_ROOT"/Mods/VSSurvivalMod.dll ~/vs-game/Mods/ + cp "$VS_ROOT"/Lib/SkiaSharp.dll ~/vs-game/Lib/ + cp "$VS_ROOT"/Lib/Newtonsoft.Json.dll ~/vs-game/Lib/ + rm -rf /tmp/vs-extract + + - name: Build + if: steps.check.outputs.exists == 'false' + run: dotnet build -c Release -p:VintageStoryPath=$HOME/vs-game + + - name: Package ZIP + if: steps.check.outputs.exists == 'false' + run: | + VERSION="${{ steps.version.outputs.version }}" + mkdir -p /tmp/package + cp bin/Release/IceSkates.dll /tmp/package/ + cp modinfo.json /tmp/package/ + cp -r assets /tmp/package/ + cd /tmp/package + zip -r "$GITHUB_WORKSPACE/IceSkates-v${VERSION}.zip" . + + - name: Create GitHub Release + if: steps.check.outputs.exists == 'false' + env: + GH_TOKEN: ${{ github.token }} + run: | + VERSION="${{ steps.version.outputs.version }}" + gh release create "v${VERSION}" "IceSkates-v${VERSION}.zip" \ + --title "Ice Skates v${VERSION}" \ + --generate-notes diff --git a/IceSkates.csproj b/IceSkates.csproj index 5c933db..9b09ab1 100644 --- a/IceSkates.csproj +++ b/IceSkates.csproj @@ -44,7 +44,7 @@ - + $(VintageStoryDataPath)/Mods/IceSkates From 09de473d17750f83b4b62409d51dc9a22b227e9f Mon Sep 17 00:00:00 2001 From: Chad Payne Date: Thu, 12 Mar 2026 23:11:37 -0600 Subject: [PATCH 2/2] Automate release versioning via git tags and PR labels modinfo.json now holds a 0.0.0-dev placeholder; the release workflow determines the bump type from PR labels (version:major/minor, default patch), calculates the next version from the latest git tag, and injects it at build time. A concurrency group prevents racing releases. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 59 ++++++++++++++++++++++++++--------- modinfo.json | 2 +- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c8e95b..f8f63ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,35 +7,67 @@ on: permissions: contents: write +concurrency: + group: release + cancel-in-progress: false + jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - - name: Extract version - id: version - run: echo "version=$(jq -r .version modinfo.json)" >> "$GITHUB_OUTPUT" - - - name: Check if release exists - id: check + - name: Determine version bump + id: bump env: GH_TOKEN: ${{ github.token }} run: | - if gh release view "v${{ steps.version.outputs.version }}" > /dev/null 2>&1; then - echo "exists=true" >> "$GITHUB_OUTPUT" + PR_NUMBER=$(gh pr list --state merged --base main --json number,mergeCommit \ + --jq ".[] | select(.mergeCommit.oid == \"$GITHUB_SHA\") | .number") + BUMP="patch" + if [ -n "$PR_NUMBER" ]; then + LABELS=$(gh pr view "$PR_NUMBER" --json labels --jq '.labels[].name') + if echo "$LABELS" | grep -q "version:major"; then + BUMP="major" + elif echo "$LABELS" | grep -q "version:minor"; then + BUMP="minor" + fi + fi + echo "bump=$BUMP" >> "$GITHUB_OUTPUT" + + - name: Calculate next version + id: version + run: | + LATEST=$(git tag -l 'v*' --sort=-v:refname | head -n1) + if [ -z "$LATEST" ]; then + NEXT="1.0.0" else - echo "exists=false" >> "$GITHUB_OUTPUT" + VER="${LATEST#v}" + IFS='.' read -r MAJOR MINOR PATCH <<< "$VER" + BUMP="${{ steps.bump.outputs.bump }}" + if [ "$BUMP" = "major" ]; then + NEXT="$((MAJOR + 1)).0.0" + elif [ "$BUMP" = "minor" ]; then + NEXT="${MAJOR}.$((MINOR + 1)).0" + else + NEXT="${MAJOR}.${MINOR}.$((PATCH + 1))" + fi fi + echo "version=$NEXT" >> "$GITHUB_OUTPUT" + + - name: Inject version into modinfo.json + run: | + jq --arg v "${{ steps.version.outputs.version }}" \ + '.version = $v' modinfo.json > modinfo.tmp && mv modinfo.tmp modinfo.json - name: Setup .NET - if: steps.check.outputs.exists == 'false' uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - name: Cache VS DLLs - if: steps.check.outputs.exists == 'false' id: cache uses: actions/cache@v4 with: @@ -43,7 +75,7 @@ jobs: key: vs-game-1.21.6 - name: Download VS DLLs - if: steps.check.outputs.exists == 'false' && steps.cache.outputs.cache-hit != 'true' + if: steps.cache.outputs.cache-hit != 'true' run: | mkdir -p ~/vs-game/Mods ~/vs-game/Lib /tmp/vs-extract curl -sSL https://cdn.vintagestory.at/gamefiles/stable/vs_client_linux-x64_1.21.6.tar.gz \ @@ -58,11 +90,9 @@ jobs: rm -rf /tmp/vs-extract - name: Build - if: steps.check.outputs.exists == 'false' run: dotnet build -c Release -p:VintageStoryPath=$HOME/vs-game - name: Package ZIP - if: steps.check.outputs.exists == 'false' run: | VERSION="${{ steps.version.outputs.version }}" mkdir -p /tmp/package @@ -73,7 +103,6 @@ jobs: zip -r "$GITHUB_WORKSPACE/IceSkates-v${VERSION}.zip" . - name: Create GitHub Release - if: steps.check.outputs.exists == 'false' env: GH_TOKEN: ${{ github.token }} run: | diff --git a/modinfo.json b/modinfo.json index 7a89bf2..3f03311 100644 --- a/modinfo.json +++ b/modinfo.json @@ -4,7 +4,7 @@ "name": "Ice Skates", "authors": ["illmatix"], "description": "Forge ice skate blades, strap them up with hide, leather, or fur, and glide across frozen lakes!", - "version": "1.0.0", + "version": "0.0.0-dev", "requiredOnClient": true, "dependencies": { "game": ""