Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/scripts/generate-matrices.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Derives the CI job matrices from supported-versions.json (the single source
# of truth for supported Minecraft versions) and writes them to GITHUB_OUTPUT:
# - build: one entry per build variant -> { mc, java }
# - launch: one entry per launchable version -> { mc, java, pregen_world }
# pregen_world marks versions whose Fabric API has no client gametest module;
# their launch test needs a pre-generated world (see generate-test-world.sh).
set -euo pipefail

JSON=supported-versions.json

java_for_variant() {
grep -oP '^java_version=\K.+' "versions/$1/gradle.properties"
}

launch="[]"
while IFS=$'\t' read -r mc variant gametest; do
java="$(java_for_variant "$variant")"
pregen=$([ "$gametest" = "false" ] && echo true || echo false)
launch="$(jq -c --arg mc "$mc" --arg java "$java" --argjson pregen "$pregen" \
'. + [{mc: $mc, java: $java, pregen_world: $pregen}]' <<<"$launch")"
done < <(jq -r 'to_entries[] | [.key, .value.variant, (.value.clientGametest | tostring)] | @tsv' "$JSON")

build="[]"
while read -r variant; do
java="$(java_for_variant "$variant")"
build="$(jq -c --arg mc "$variant" --arg java "$java" \
'. + [{mc: $mc, java: $java}]' <<<"$build")"
done < <(jq -r '[.[].variant] | reduce .[] as $v ([]; if index($v) then . else . + [$v] end) | .[]' "$JSON")

echo "build=$build" >> "$GITHUB_OUTPUT"
echo "launch=$launch" >> "$GITHUB_OUTPUT"
echo "build matrix: $build"
echo "launch matrix: $launch"
62 changes: 62 additions & 0 deletions .github/scripts/generate-test-world.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
# Generates a vanilla singleplayer world save for the given Minecraft version
# by briefly running that version's dedicated server, and places it where the
# launch test expects it (launchtest/run/saves/ci-world).
#
# Only needed for versions whose Fabric API has no client gametest module
# (before 1.21.4): their launch test cannot create a world in-game, so the
# client auto-joins this save via --quickPlaySingleplayer instead. Using the
# exact same Minecraft version to generate the world avoids any world-upgrade
# prompts when the client opens it.
set -euo pipefail

MC_VERSION="${1:?usage: generate-test-world.sh <minecraft-version>}"
DEST="$(pwd)/launchtest/run/saves/ci-world"

WORK="$(mktemp -d)"
cd "$WORK"

MANIFEST_URL="$(curl -sSf https://piston-meta.mojang.com/mc/game/version_manifest_v2.json \
| jq -r --arg v "$MC_VERSION" '.versions[] | select(.id == $v) | .url')"
SERVER_URL="$(curl -sSf "$MANIFEST_URL" | jq -r '.downloads.server.url')"
curl -sSfo server.jar "$SERVER_URL"

echo "eula=true" > eula.txt
# A flat world keeps generation fast and renders instantly on the CI software
# renderer. The default gamemode (survival) matches the gametest-based runs.
cat > server.properties <<'EOF'
level-name=ci-world
level-type=minecraft\:flat
view-distance=4
simulation-distance=4
online-mode=false
spawn-protection=0
EOF

mkfifo console
java -Xmx1G -jar server.jar nogui < console > server-log.txt 2>&1 &
SERVER_PID=$!
exec 3> console

for _ in $(seq 1 300); do
grep -q 'Done (' server-log.txt && break
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
cat server-log.txt
echo "::error::Dedicated server for $MC_VERSION exited before finishing world generation" >&2
exit 1
fi
sleep 1
done
if ! grep -q 'Done (' server-log.txt; then
cat server-log.txt
echo "::error::Dedicated server for $MC_VERSION did not finish starting within 300s" >&2
exit 1
fi

echo "stop" >&3
wait "$SERVER_PID"
exec 3>&-

mkdir -p "$(dirname "$DEST")"
cp -r ci-world "$DEST"
echo "Generated test world at $DEST"
80 changes: 80 additions & 0 deletions .github/scripts/publish-screenshots.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# Collects the launch-test screenshots uploaded as artifacts by every matrix
# job of the current workflow run, normalizes their names, and commits them to
# the ci-screenshots branch so they can be embedded (as raw.githubusercontent
# URLs) in a PR comment and in the job summary.
#
# Leaves the normalized screenshots in screenshots-publish/ for the comment
# step: <sha>/mc-<version>-survival.png and <sha>/mc-<version>-title.png.
#
# Required env: GITHUB_TOKEN, GITHUB_REPOSITORY, GITHUB_RUN_ID, GITHUB_SHA
set -euo pipefail

api() {
curl -sSf -H "Authorization: Bearer $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" "$@"
}

# --- Download every launch-screenshots-mc* artifact of this run -------------
mkdir -p artifact-zips shots
api "https://api.github.com/repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/artifacts?per_page=100" > artifacts.json

while IFS=: read -r id name; do
mc="${name#launch-screenshots-mc}"
echo "Downloading $name"
curl -sSfL -H "Authorization: Bearer $GITHUB_TOKEN" \
-o "artifact-zips/$id.zip" \
"https://api.github.com/repos/$GITHUB_REPOSITORY/actions/artifacts/$id/zip"
mkdir -p "shots/$mc"
unzip -oq "artifact-zips/$id.zip" -d "shots/$mc"
done < <(jq -r '.artifacts[] | select(.name | startswith("launch-screenshots-mc")) | "\(.id):\(.name)"' artifacts.json)

# --- Normalize names (gametest screenshots carry a timestamp prefix) --------
PUBLISH="screenshots-publish/$GITHUB_SHA"
mkdir -p "$PUBLISH"

for dir in shots/*/; do
mc="$(basename "$dir")"
for kind in survival-world title-screen; do
src="$(find "$dir" -name "*betterhud-$kind.png" -print -quit)"
if [ -n "$src" ]; then
cp "$src" "$PUBLISH/mc-$mc-${kind%%-*}.png"
fi
done
done

count="$(find "$PUBLISH" -name '*.png' | wc -l)"
echo "Collected $count screenshots"
if [ "$count" -eq 0 ]; then
echo "No screenshots to publish, skipping branch update"
exit 0
fi

# --- Commit to the ci-screenshots branch ------------------------------------
REMOTE="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
if ! git clone --quiet --depth 1 --branch ci-screenshots "$REMOTE" ci-screenshots-branch 2>/dev/null; then
mkdir -p ci-screenshots-branch
git -C ci-screenshots-branch init --quiet -b ci-screenshots
git -C ci-screenshots-branch remote add origin "$REMOTE"
fi

mkdir -p "ci-screenshots-branch/$GITHUB_SHA"
cp "$PUBLISH"/*.png "ci-screenshots-branch/$GITHUB_SHA/"
cd ci-screenshots-branch
git add .
if git diff --cached --quiet; then
echo "Screenshots already published for $GITHUB_SHA"
exit 0
fi
git -c user.name="github-actions[bot]" -c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
commit --quiet -m "CI screenshots for $GITHUB_SHA"

# Retry the push in case a concurrent run updated the branch first.
for _ in 1 2 3; do
if git push --quiet origin ci-screenshots; then
echo "Published screenshots to ci-screenshots/$GITHUB_SHA"
exit 0
fi
git pull --quiet --rebase origin ci-screenshots || true
done
echo "::error::Could not push screenshots to the ci-screenshots branch" >&2
exit 1
Loading