From ed02d61d942b43ad73bd14b10df947b1a73e28d7 Mon Sep 17 00:00:00 2001 From: Ryan Barlow <7389646+ryanbarlow97@users.noreply.github.com> Date: Tue, 22 Sep 2026 15:27:59 +0000 Subject: [PATCH] ci: build dated development jars and tagged draft releases --- .github/dependencies.sha256 | 7 ++ .github/scripts/prepare-release.sh | 13 +++ .github/workflows/build.yml | 104 +++++++-------------- .github/workflows/maven-release.yml | 135 ++++++++++++++++++++++++++++ .github/workflows/release.yml | 20 +++++ .gitignore | 3 + pom.xml | 57 +++++------- src/main/resources/plugin.yml | 2 +- 8 files changed, 232 insertions(+), 109 deletions(-) create mode 100644 .github/dependencies.sha256 create mode 100644 .github/scripts/prepare-release.sh create mode 100644 .github/workflows/maven-release.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/dependencies.sha256 b/.github/dependencies.sha256 new file mode 100644 index 0000000..b473f66 --- /dev/null +++ b/.github/dependencies.sha256 @@ -0,0 +1,7 @@ +bbac27e3055d135a4a7f6164ace5e32b7e6275cc8387575a8c8e1809fdc555fd libs/TLibs.jar +791bc29301b4250a0f7ef3053a1999ace7e2ff0ddae8e79ff52bef0fee8034ed libs/vehicleframework-1.1.12.jar +0fedc530aaa9cd9e0a452d0bde95fb9fa0ecc31564ec625e3a0e2cef57c0aec8 libs/rpcharacters-1.1.7.jar +64ea06ea92bf22785e6d541dd1b5f550edcdc4610d7a9748a91d715876ac079d libs/advancedcrafting-1.2.1.jar +5185b9e0ea8653ab61da07304f1573c6a9a5af97cf55a5d970c5a25f16bc743d libs/simplefactions-2.8.7.jar +a3f86a50d38296dd0a91d375f0a9433192e6e8d3e9dcae2751c801e67d24d9cd libs/MythicLib-dist-1.7.1.jar +14850d7454374d7312305d3e84a391be720301e5964963f869b27ae97f6264eb libs/MMOCore-1.13.1.jar diff --git a/.github/scripts/prepare-release.sh b/.github/scripts/prepare-release.sh new file mode 100644 index 0000000..f4dbc5f --- /dev/null +++ b/.github/scripts/prepare-release.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${GH_TOKEN:?Set DEPS_TOKEN with Contents read access to TF-Minecraft/ServerAssets}" +ref=8a44414cd5b74b7d1c7a258ccf5a86a5f6e0294b +mkdir -p libs +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/runtime/plugins/TLibs.jar?ref=$ref" > "libs/TLibs.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/791bc29301b4/vehicleframework-1.1.12.jar?ref=$ref" > "libs/vehicleframework-1.1.12.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/0fedc530aaa9/rpcharacters-1.1.7.jar?ref=$ref" > "libs/rpcharacters-1.1.7.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/64ea06ea92bf/advancedcrafting-1.2.1.jar?ref=$ref" > "libs/advancedcrafting-1.2.1.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/5185b9e0ea86/simplefactions-2.8.7.jar?ref=$ref" > "libs/simplefactions-2.8.7.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/a3f86a50d382/MythicLib-dist-1.7.1.jar?ref=$ref" > "libs/MythicLib-dist-1.7.1.jar" +curl --fail --location --silent --show-error --retry 3 -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github.raw+json" "https://api.github.com/repos/TF-Minecraft/ServerAssets/contents/jars/14850d745437/MMOCore-1.13.1.jar?ref=$ref" > "libs/MMOCore-1.13.1.jar" +sha256sum --check .github/dependencies.sha256 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a61e06f..66b7bea 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,96 +2,54 @@ name: Build on: push: - branches: ['**'] + branches: [main] pull_request: branches: [main] - workflow_dispatch: - -concurrency: - # Keep every push build, even when another commit is pushed immediately. - group: ${{ github.workflow }}-${{ github.run_id }} - cancel-in-progress: false permissions: contents: read jobs: build: - # Fork PRs and Dependabot do not receive the private dependency secret. - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) - runs-on: ubuntu-latest - timeout-minutes: 15 + runs-on: ubuntu-24.04 + timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - - - uses: actions/setup-java@v4 + - uses: actions/setup-java@v6 with: distribution: temurin - java-version: '21' - cache: maven - - - name: Fetch private dependencies + java-version: '25' + - name: Prepare pinned dependencies env: GH_TOKEN: ${{ secrets.DEPS_TOKEN }} + run: bash .github/scripts/prepare-release.sh + - name: Set dated development version + id: dev + shell: bash run: | - if [ -z "$GH_TOKEN" ]; then - echo "::error::Set DEPS_TOKEN to a token with Contents: read access to JustinasLa/tfmc-deps." - exit 1 - fi - mkdir -p libs - gh release download v1 --repo JustinasLa/tfmc-deps --dir libs --clobber \ - --pattern 'TLibs-1.0.jar' \ - --pattern 'vehicleframework-1.1.11.jar' \ - --pattern 'rpcharacters-1.1.6.jar' \ - --pattern 'advancedcrafting-1.1.7.jar' \ - --pattern 'simplefactions-2.8.7.jar' \ - --pattern 'MMOCore-1.13.1.jar' \ - --pattern 'MythicLib-dist-1.7.1.jar' - - - name: Verify private dependencies - run: sha256sum -c libs/SHA256SUMS - - - name: Build - run: mvn -B --no-transfer-progress -P'!deploy-live' clean package - - - uses: actions/upload-artifact@v4 + dev_version="DEV-$(date -u +%Y%m%d-%H%M)" + mvn -B --no-transfer-progress org.codehaus.mojo:versions-maven-plugin:2.22.0:set \ + -DnewVersion="$dev_version" -DgenerateBackupPoms=false + mvn -B --no-transfer-progress help:evaluate \ + -Dexpression=project.build.finalName -Doutput="$RUNNER_TEMP/final-name" + final_name=$(cat "$RUNNER_TEMP/final-name") + echo "name=$final_name" >> "$GITHUB_OUTPUT" + echo "jar=target/$final_name.jar" >> "$GITHUB_OUTPUT" + + - name: Run unit tests and build + run: mvn -B --no-transfer-progress clean verify -DskipTests=false -Dmaven.test.skip=false + - uses: actions/upload-artifact@v7 with: - name: tfmccore-jar-${{ github.sha }} - path: target/*.jar + name: ${{ steps.dev.outputs.name }}-${{ github.run_id }}-${{ github.run_attempt }} + path: ${{ steps.dev.outputs.jar }} if-no-files-found: error - retention-days: 90 - publish: - needs: build - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: write - concurrency: - group: publish-latest-release - steps: - - uses: actions/checkout@v4 + - name: Upload unit test reports + if: ${{ !cancelled() && hashFiles('target/surefire-reports/*.xml') != '' }} + uses: actions/upload-artifact@v7 with: - persist-credentials: false - - - uses: actions/download-artifact@v4 - with: - name: tfmccore-jar-${{ github.sha }} - path: target - - # --clobber only replaces an asset with the same filename; a pom.xml - # version bump changes the jar name, so old jars won't be pruned - # automatically and must be removed from the release manually. - - name: Publish latest release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - if gh release view latest >/dev/null 2>&1; then - gh release upload latest target/*.jar --clobber - else - gh release create latest target/*.jar \ - --title "Latest build" --notes "Auto-published from main" --latest=false - fi + name: unit-test-reports-${{ github.run_id }}-${{ github.run_attempt }} + path: target/surefire-reports/ + if-no-files-found: error diff --git a/.github/workflows/maven-release.yml b/.github/workflows/maven-release.yml new file mode 100644 index 0000000..3103b70 --- /dev/null +++ b/.github/workflows/maven-release.yml @@ -0,0 +1,135 @@ +name: Maven plugin release + +on: + workflow_call: + inputs: + java-version: + required: true + type: string + artifact-path: + description: Exact deployable JAR path, with optional {version} placeholder + required: true + type: string + secrets: + DEPS_TOKEN: + required: false + +permissions: + contents: read + +concurrency: + group: plugin-release-${{ github.repository }}-${{ github.ref }} + cancel-in-progress: false + +defaults: + run: + shell: bash + +jobs: + build: + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - uses: actions/setup-java@v6 + with: + distribution: temurin + java-version: ${{ inputs.java-version }} + + - name: Validate release version + env: + TAG: ${{ github.ref_name }} + run: | + [[ "$TAG" =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]] || { + echo '::error::Expected vMAJOR.MINOR or vMAJOR.MINOR.PATCH, with an optional prerelease suffix.' + exit 1 + } + [[ "${TAG^^}" != *SNAPSHOT* ]] || exit 1 + + - name: Prepare pinned dependencies + env: + GH_TOKEN: ${{ secrets.DEPS_TOKEN }} + run: | + if [[ -f .github/scripts/prepare-release.sh ]]; then + bash .github/scripts/prepare-release.sh + fi + + - name: Check Maven version and build + env: + TAG: ${{ github.ref_name }} + run: | + version_file="$RUNNER_TEMP/maven-release-version" + mvn -B --no-transfer-progress -P'!deploy-live' help:evaluate \ + -Dexpression=project.version -Doutput="$version_file" + [[ "$(cat "$version_file")" == "${TAG#v}" ]] || { + echo '::error::The tag must match project.version exactly.' + exit 1 + } + mvn -B --no-transfer-progress -P'!deploy-live' clean verify + + - name: Stage only the release JAR + env: + ARTIFACT_PATH: ${{ inputs.artifact-path }} + TAG: ${{ github.ref_name }} + run: | + python3 - <<'PY' + import hashlib, json, os, pathlib, shutil, zipfile + root = pathlib.Path.cwd().resolve() + source = (root / os.environ['ARTIFACT_PATH'].replace('{version}', os.environ['TAG'][1:])).resolve() + if not source.is_relative_to(root / 'target') or not source.is_file() or source.suffix != '.jar': + raise SystemExit('Expected one existing JAR inside target/') + with zipfile.ZipFile(source) as jar: + if not {'plugin.yml', 'paper-plugin.yml'}.intersection(jar.namelist()): + raise SystemExit('Release JAR has no plugin descriptor') + if jar.testzip() is not None: + raise SystemExit('Release JAR is corrupt') + dest = pathlib.Path(os.environ['RUNNER_TEMP']) / 'plugin-release' + dest.mkdir() + shutil.copyfile(source, dest / source.name) + digest = hashlib.sha256((dest / source.name).read_bytes()).hexdigest() + (dest / 'SHA256SUMS').write_text(f'{digest} {source.name}\n') + (dest / 'build.json').write_text(json.dumps({ + 'repository': os.environ['GITHUB_REPOSITORY'], + 'commit': os.environ['GITHUB_SHA'], + 'tag': os.environ['TAG'], + 'run': f"{os.environ['GITHUB_SERVER_URL']}/{os.environ['GITHUB_REPOSITORY']}/actions/runs/{os.environ['GITHUB_RUN_ID']}", + 'artifact': source.name, + 'sha256': digest, + }, indent=2) + '\n') + PY + + - uses: actions/upload-artifact@v7 + with: + name: plugin-release-${{ github.sha }} + path: ${{ runner.temp }}/plugin-release/ + if-no-files-found: error + retention-days: 30 + + publish: + needs: build + runs-on: ubuntu-24.04 + timeout-minutes: 5 + permissions: + contents: write + steps: + - uses: actions/download-artifact@v8 + with: + name: plugin-release-${{ github.sha }} + path: release + + - name: Create draft release + working-directory: release + env: + GH_TOKEN: ${{ github.token }} + GH_REPO: ${{ github.repository }} + TAG: ${{ github.ref_name }} + run: | + sha256sum --check SHA256SUMS + flags=() + if [[ "$TAG" == *-* ]]; then flags+=(--prerelease); fi + gh release create "$TAG" ./*.jar SHA256SUMS build.json \ + --verify-tag --draft --title "$TAG" --generate-notes "${flags[@]}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a807ca5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,20 @@ +name: Release + +on: + push: + tags: ['v*'] + +permissions: + contents: read + +jobs: + release: + permissions: + contents: write + uses: ./.github/workflows/maven-release.yml + with: + java-version: '25' + # Exact path, not a glob. {version} is replaced with the tag without v. + artifact-path: target/tfmccore-{version}.jar + secrets: + DEPS_TOKEN: ${{ secrets.DEPS_TOKEN }} diff --git a/.gitignore b/.gitignore index 598f188..71f25ef 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ Thumbs.db # Private jar-only deps: fetched from JustinasLa/tfmc-deps, never committed libs/* !libs/SHA256SUMS + +# Downloaded build dependencies +/libs/*.jar diff --git a/pom.xml b/pom.xml index 5f13211..a9b9daa 100644 --- a/pom.xml +++ b/pom.xml @@ -12,13 +12,6 @@ UTF-8 21 21 - D:/Dokumenter/My Plugins/Reference Libs - D:/Dokumenter/My Plugins/TFMC/TFMCCore - D:/Dokumenter/My Plugins/TFMC/TLibs - D:/Dokumenter/My Plugins/TFMC/VehicleFramework - D:/Dokumenter/My Plugins/TFMC/RPCharacters - D:/Dokumenter/My Plugins/TFMC/AdvancedCrafting - D:/Dokumenter/My Plugins/TFMC/SimpleFactions @@ -54,49 +47,49 @@ TLibs 1.0 system - ${tfmc.tlibs}/TLibs.jar + ${project.basedir}/libs/TLibs.jar local VehicleFramework - 1.1.11 + 1.1.12 system - ${tfmc.vehicleframework}/vehicleframework-1.1.11.jar + ${project.basedir}/libs/vehicleframework-1.1.12.jar local RPCharacters 1.1.7 system - ${tfmc.rpcharacters}/rpcharacters-1.1.7.jar + ${project.basedir}/libs/rpcharacters-1.1.7.jar local AdvancedCrafting - 1.1.7 + 1.2.1 system - ${tfmc.advancedcrafting}/advancedcrafting-1.1.7.jar + ${project.basedir}/libs/advancedcrafting-1.2.1.jar local SimpleFactions 2.8.7 system - ${tfmc.sf}/simplefactions-2.8.7.jar + ${project.basedir}/libs/simplefactions-2.8.7.jar local MythicLib 1.7.1 system - ${tfmc.refs}/MythicLib-dist-1.7.1.jar + ${project.basedir}/libs/MythicLib-dist-1.7.1.jar local MMOCore 1.13.1 system - ${tfmc.refs}/MMOCore-1.13.1.jar + ${project.basedir}/libs/MMOCore-1.13.1.jar @@ -134,7 +127,19 @@ - TFMCCore + + + src/main/resources + true + plugin.yml + + + src/main/resources + false + plugin.yml + + + ${project.artifactId}-${project.version} org.apache.maven.plugins @@ -146,24 +151,6 @@ maven-surefire-plugin 3.2.5 - - org.apache.maven.plugins - maven-antrun-plugin - 3.1.0 - - - package - run - - - - - - - - - diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ab07f12..c6fbc32 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ main: net.tfminecraft.tfmccore.TFMCCore api-version: 1.21 name: TFMCCore -version: 1.0 +version: ${project.version} author: Drefvelin depend: [TLibs]