Skip to content

feat: Support for MC 26.1 #1373

feat: Support for MC 26.1

feat: Support for MC 26.1 #1373

Workflow file for this run

name: Build and Release
on:
push:
branches:
- root
pull_request:
workflow_dispatch:
inputs:
version:
description: 'Version (without "v" prefix)'
required: true
type: string
bypass-test:
description: 'Disable test'
default: false
required: false
type: boolean
bypass-mod-publish:
description: 'Disable publishing the mods to mod hosts (Modrinth, CurseForge)'
default: false
required: false
type: boolean
jobs:
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
changelog: ${{ steps.changelog.outputs.changelog }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup matrix
id: matrix
run: echo "matrix=$(jq -cr . ./versions.json)" >> $GITHUB_OUTPUT
- name: Setup CHANGELOG parser
uses: taiki-e/install-action@parse-changelog
- name: Retrieve changelog
if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
id: changelog
run: |
# extended SemVer (major.minor.patch.hotfix)
VERSION_FORMAT='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))?(-[0-9A-Za-z\.-]+)?(\+[0-9A-Za-z\.-]+)?$|^Unreleased$'
CHANGELOG="$(parse-changelog CHANGELOG.md ${{ github.event.inputs.version == '' && 'INVALID' || github.event.inputs.version }} --version-format $VERSION_FORMAT || parse-changelog CHANGELOG.md Unreleased --version-format $VERSION_FORMAT || echo "")"
[ "$CHANGELOG" = "" ] && exit 1
{
echo "changelog<<END_OF_FILE"
echo "$CHANGELOG"
echo ""
echo "END_OF_FILE"
} >> $GITHUB_OUTPUT 2> /dev/null
# To reduce api request, so we don't hit rate-limit
- name: Retrieve JSON
run: |
curl -Ls -o "headlessmc.json" "https://api.github.com/repos/3arthqu4ke/headlessmc/releases/tags/2.7.1" --header "Authorization: ${{ secrets.GITHUB_TOKEN }}"
curl -Ls -o "mc-runtime-test.json" "https://api.github.com/repos/null2264/mc-runtime-test/releases/tags/5.2.5" --header "Authorization: ${{ secrets.GITHUB_TOKEN }}"
- name: Upload jar files
uses: actions/upload-artifact@v4
with:
name: runtime-test-kit
path: |
headlessmc.json
mc-runtime-test.json
if-no-files-found: error
retention-days: 1
build:
name: Build
needs: setup
runs-on: ubuntu-latest
strategy:
fail-fast: false # Don't cancel if one failed
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v4
# - name: Cache build
# if: github.event.repository != null && github.ref_name == github.event.repository.default_branch
# uses: actions/cache@v4
# with:
# path: cobblegen/build
# key: build-${{ hashFiles(format('{0}/[a-z]**', 'cobblegen/build'), 'mclib/**') }}-${{ matrix.mc }}-${{ matrix.loader }}
- name: Setup Gradle
uses: null2264/actions/gradle-java-setup@363cb9cf3d66bd9c72ed6860142c6b2c121d7e94
with:
distro: temurin
java: |
8
17
21
25
gradle-no-cache-if: true
- name: Setup properties
run: |
echo "org.gradle.java.installations.fromEnv=JAVA_HOME,JAVA_HOME_8_X64,JAVA_HOME_17_X64,JAVA_HOME_21_X64" >> gradle.properties
- name: Build with Gradle
run: |
# Retry 5 times because TerraformersMC's Maven keep having a stroke
# and there's no way to workaround it through Gradle as there are no
# public API for it. So we just need to deal with it I guess.
#
# REF: https://discuss.gradle.org/t/how-to-deal-with-network-flakiness-impacting-gradle-builds/25705/3
# REF: https://github.com/gradle/gradle/issues/4629
# REF: https://github.com/gradle/gradle/issues/2779
tries=1
c="0"
while [ $tries -le 5 ];
do
./gradlew build -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" && exit 0
c="$?"
echo "Try $tries failed. (code:$c)"
sleep 5s
tries=$((tries+1))
done
[ "$c" = "0" ] || exit 1
env:
VERSION: ${{ github.event.inputs.version == '' && '0.0.0' || github.event.inputs.version }}
- name: Archive build results
run: tar -I zstd -cf build.tar.zst cobblegen/build/libs/*
- name: Upload build folder
uses: actions/upload-artifact@v4
with:
name: build-artifacts-mc${{ matrix.mc }}-${{ matrix.loader }}
path: build.tar.zst
if-no-files-found: error
retention-days: 3
- name: Upload jar files
uses: actions/upload-artifact@v4
with:
name: jar-mc${{ matrix.mc }}-${{ matrix.loader }}
path: cobblegen/build/libs/*
if-no-files-found: error
retention-days: 3
- name: GameTest with Gradle
if: github.event.inputs.bypass-test != 'true' && matrix.gradleGameTest
run: |
echo "# GameTest results" >> $GITHUB_STEP_SUMMARY;
echo "<table>" >> $GITHUB_STEP_SUMMARY;
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
echo "<th>Status</th>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
timeout 20m ./gradlew runGametest -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}" && (
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
echo "<td>🟩 Complete</td>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
) || (
EXIT_CODE="$?"
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
STATUS="Unknown error ($EXIT_CODE)";
case "$EXIT_CODE" in
"-1")
STATUS="🟥 Test failed"
;;
"125" | "124")
STATUS="🟨 Timed out"
;;
"255" | "1")
STATUS="🟥 Crashed"
;;
*)
;;
esac
echo "<td>$STATUS</td>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
case "$EXIT_CODE" in
"255" | "1")
echo "</table>" >> $GITHUB_STEP_SUMMARY
exit $EXIT_CODE
;;
*)
;;
esac
)
env:
VERSION: ${{ github.event.inputs.version == '' && '0.0.0' || github.event.inputs.version }}
- name: Download build artifact
if: github.event.inputs.bypass-test != 'true'
uses: actions/download-artifact@v4
with:
name: runtime-test-kit
- name: Setup HeadlessMC
if: github.event.inputs.bypass-test != 'true'
id: setup-headlessmc
run: |
mkdir -p HeadlessMC run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods run/test-${{ matrix.mc }}-${{ matrix.loader }}/config
cat <<EOF >> HeadlessMC/config.properties
hmc.java.versions=$JAVA_HOME_${{ matrix.java }}_X64/bin/java
hmc.gamedir=$PWD/run/test-${{ matrix.mc }}-${{ matrix.loader }}
hmc.offline=true
hmc.rethrow.launch.exceptions=true
hmc.exit.on.failed.command=true
EOF
cat <<EOF >> run/test-${{ matrix.mc }}-${{ matrix.loader }}/options.txt
onboardAccessibility:false
pauseOnLostFocus:false
EOF
json="$(cat ./headlessmc.json)"
url="$(echo $json | jq -r '.assets[].browser_download_url' | grep .jar | grep launcher | grep -v jfx | grep -v wrapper)"
curl -Ls -o "headlessmc-launcher.jar" $url
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y x11-xserver-utils
- name: Tests with HeadlessMC
if: github.event.inputs.bypass-test != 'true'
env:
ENABLE_NULL2264_COBBLEGEN_GAMETEST: true
run: |
VERSION=v4.45.1
BINARY=yq_linux_amd64
wget https://github.com/mikefarah/yq/releases/download/${VERSION}/${BINARY}.tar.gz -O - |\
tar xz && sudo mv ${BINARY} /usr/bin/yq
cp cobblegen/build/libs/cobblegen-*+${{ matrix.mc }}*-BETA-${{ matrix.loader }}.jar run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods
echo "# [$(echo "${{ matrix.loader }}" | tr '[:lower:]' '[:upper:]') - ${{ matrix.mc }}] Test results" >> $GITHUB_STEP_SUMMARY;
echo "<table>" >> $GITHUB_STEP_SUMMARY;
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
echo "<th>Runtime Version</th><th>Status</th>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
echo "[TEST] Initializing..."
TEST_VERSIONS=(${{ join(matrix.testVersions, ' ') }})
for i in "${TEST_VERSIONS[@]}"; do
echo "[TEST] Testing MC $i (${{ matrix.loader }})..."
echo "[TEST] Downloading Runtime Test Mod... [0/3]"
json="$(cat ./mc-runtime-test.json)"
echo "[TEST] Downloading Runtime Test Mod... [1/3]"
TARGET=$i
url="$(echo $json | jq -r '.assets[].browser_download_url' | grep ${TARGET//\./\\.} | grep ${{ matrix.loader == 'forge' && 'lexforge' || matrix.loader }} || echo "[FAIL]")"
[ "$url" = "[FAIL]" ] && (
>&2 echo "[FAIL] There's no Runtime Test Mod for MC $i!";
exit 1;
)
echo "[TEST] Downloading Runtime Test Mod... [2/3]"
curl -Ls -o "mc-runtime-test.jar" $url
echo "[TEST] Downloading Runtime Test Mod... [3/3]"
mv -f ./mc-runtime-test.jar run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods
[ "${{ matrix.loader }}" = "fabric" ] && (
fapi="$(yq -M ".[\"$i\"]" fabric-versions.yaml || echo 'null')"
[ "$fapi" = "null" ] || (
url="https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api/$fapi+$i/fabric-api-$fapi+$i.jar"
curl -Ls -o "fapi.jar" $url
mv -f ./fapi.jar run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods
)
gametest="$(yq -M ".[\"$i\"]" fabric-gametest-versions.yaml || echo 'null')"
[ "$gametest" = "null" ] || (
rm -f run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods/fapi-resource.jar
resource="$(yq -M ".[\"$i\"]" fabric-resource-versions.yaml || echo 'null')"
[ "$resource" = "null" ] || (
url="https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-resource-loader-v0/$resource/fabric-resource-loader-v0-$resource.jar"
curl -Ls -o "fapi-resource.jar" $url
mv -f ./fapi-resource.jar run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods
)
url="https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-gametest-api-v1/$gametest/fabric-gametest-api-v1-$gametest.jar"
curl -Ls -o "fapi-gametest.jar" $url
mv -f ./fapi-gametest.jar run/test-${{ matrix.mc }}-${{ matrix.loader }}/mods
)
)
echo "[TEST] Downloading MC..."
java -jar ./headlessmc-launcher.jar --command download $i
echo "[TEST] Downloading Mod Loader..."
java -jar ./headlessmc-launcher.jar --command ${{ matrix.loader }} $i
echo "[TEST] Launching MC Headless..."
timeout 20m xvfb-run java -Dhmc.check.xvfb=true -jar ./headlessmc-launcher.jar --command launch ${{ matrix.loader }}:$i --retries 3 --jvm "-Djava.awt.headless=true -DMcRuntimeGameTestMinExpectedGameTests=1" && (
echo "[TEST] Test complete ($i)"; true;
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
echo "<td>$i</td><td>🟩 Complete</td>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
) || (
EXIT_CODE="$?"
echo "[TEST] Test failed or timed out ($i)"; true;
echo "<tr>" >> $GITHUB_STEP_SUMMARY;
STATUS="Unknown error ($EXIT_CODE)";
case "$EXIT_CODE" in
"-1")
STATUS="🟥 Test failed"
;;
"125" | "124")
STATUS="🟨 Timed out"
;;
"255" | "1")
STATUS="🟥 Crashed"
;;
*)
;;
esac
echo "<td>$i</td><td>$STATUS</td>" >> $GITHUB_STEP_SUMMARY;
echo "</tr>" >> $GITHUB_STEP_SUMMARY;
case "$EXIT_CODE" in
"255" | "1")
echo "</table>" >> $GITHUB_STEP_SUMMARY
exit $EXIT_CODE
;;
*)
;;
esac
)
done
echo "</table>" >> $GITHUB_STEP_SUMMARY;
- name: Release
if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != '' && github.event.inputs.bypass-mod-publish != 'true'
shell: bash
run: |
./gradlew publishMods -PmcVer="${{ matrix.mc }}" -Pnull2264.platform="${{ matrix.loader }}"
env:
VERSION: ${{ github.event.inputs.version == '' && '0.0.0' || github.event.inputs.version }}
CHANGELOG: ${{ needs.setup.outputs.changelog }}
CURSEFORGE: ${{ secrets.CURSEFORGE }}
MODRINTH: ${{ secrets.MODRINTH }}
release:
name: Release to GitHub
needs: [setup, build]
if: github.event_name == 'workflow_dispatch' && github.event.inputs.version != ''
runs-on: ubuntu-latest
steps:
- name: Setup CHANGELOG parser
uses: taiki-e/install-action@parse-changelog
- name: Merge build artifacts
uses: actions/upload-artifact/merge@v4
with:
name: build-artifacts
pattern: build-artifacts-*
delete-merged: true
- name: Merge jar artifacts
uses: actions/upload-artifact/merge@v4
with:
name: jars
pattern: jar-*
delete-merged: true
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: jars
- name: Deploy to GitHub
if: needs.setup.outputs.changelog != ''
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{github.event.inputs.version}}
name: v${{github.event.inputs.version}}
body: |
${{ needs.setup.outputs.changelog }}
files: |
./!(*-dev-shade|*-sources).jar