Skip to content
Merged
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
108 changes: 10 additions & 98 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,6 @@ jobs:
- name: Setup Gradle (cache)
uses: gradle/actions/setup-gradle@v4

# Packaging is a release artifact, not a pull-request gate. Keeping it on
# master avoids paying for a second full build on every PR update.
- name: Package slim runtime (fail fast)
if: github.event_name == 'push'
shell: bash
run: ./gradlew packageSlimCompilerDist --no-daemon --stacktrace

- name: Prepare bundled Lua runtime (Linux)
if: runner.os == 'Linux'
shell: bash
Expand All @@ -114,6 +107,16 @@ jobs:
shell: bash
run: brew install lua

- name: Test release gate
if: runner.os == 'Linux'
shell: bash
run: python ../scripts/test-release.py

- name: Test compiler version metadata
if: runner.os == 'Linux'
shell: bash
run: python ../scripts/test-version-metadata.py

- name: Test game-data helpers
shell: bash
run: ./gradlew -p ../HelperScripts test --no-daemon --stacktrace --quiet
Expand Down Expand Up @@ -157,94 +160,3 @@ jobs:
de.peeeq.wurstscript/test-output/determinism-second.lua
if-no-files-found: ignore
retention-days: 14

- name: Upload packaged artifact (per-OS)
if: github.event_name == 'push'
uses: actions/upload-artifact@v4
with:
name: wurst-compiler-${{ matrix.os }}
path: |
de.peeeq.wurstscript/build/releases/*.zip
de.peeeq.wurstscript/build/releases/*.tar.gz
de.peeeq.wurstscript/build/releases/*.sha256
if-no-files-found: error
retention-days: 7

nightly_release:
name: Nightly prerelease (master)
needs: build
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout (to update nightly tag)
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Move 'nightly' tag to this commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -f nightly "$GITHUB_SHA"
git push origin nightly --force

- name: Download all packaged artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Gather files (zip only)
shell: bash
run: |
set -euo pipefail
mkdir -p upload
find artifacts -type f -name '*.zip' -print0 | xargs -0 -I{} cp "{}" upload/

- name: Verify we have all platform zips
shell: bash
run: |
shopt -s nullglob
zips=(upload/*.zip)
echo "Found ${#zips[@]} zip(s):"; ls -alh upload
if (( ${#zips[@]} < 4 )); then
echo "ERROR: expected Win + Linux + macOS arm64 + macOS x64 zips (got ${#zips[@]})."
exit 1
fi

- name: Normalize nightly filenames
shell: bash
run: |
set -euo pipefail
for f in upload/*.zip; do
base="$(basename "$f")"
stem="${base%.zip}"
new_stem="$(echo "$stem" | sed -E 's/-[0-9]+(\.[0-9]+)*-/-nightly-/' )"
new="upload/${new_stem}.zip"
if [[ "upload/$base" != "$new" ]]; then mv -f "upload/$base" "$new"; fi
done
echo "Renamed to:"; ls -alh upload

# Keep the existing release metadata and stable download URLs. The release
# action PATCHes the release before uploading, which GitHub currently
# rejects for the Actions integration even with contents: write.
- name: Ensure Nightly Release exists
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
if ! gh release view nightly >/dev/null 2>&1; then
gh release create nightly \
--verify-tag \
--prerelease \
--title "Nightly Build (master)" \
--notes $'Nightly build for the latest commit on `master`.\nThis release is automatically updated on each push.'
fi

- name: Publish Nightly Release assets
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: gh release upload nightly upload/*.zip --clobber
181 changes: 142 additions & 39 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
name: Release slim runtimes (jlink)
name: Release versioned compiler

on:
push:
tags:
- 'v*'
workflow_dispatch:
tags: ['v*']

permissions:
contents: write
contents: read

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
validate:
name: Validate release tag on master
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
fetch-depth: 0
- name: Test release gate
run: python scripts/test-release.py
- name: Validate tag and version
id: version
env:
RELEASE_REF: ${{ github.ref }}
run: |
git fetch origin master
version=$(python scripts/validate-release.py "$RELEASE_REF")
echo "version=$version" >> "$GITHUB_OUTPUT"

build:
name: Build ${{ matrix.plat }}
name: Test and package ${{ matrix.plat }}
needs: validate
permissions:
contents: read
checks: write
strategy:
fail-fast: false
# keep four platforms as you had
matrix:
include:
- os: windows-latest
Expand All @@ -25,52 +51,129 @@ jobs:
plat: macos-x64
- os: macos-latest
plat: macos-arm64

runs-on: ${{ matrix.os }}
permissions:
contents: write
env:
GRADLE_OPTS: -Dorg.gradle.daemon=false
JAVA_TOOL_OPTIONS: --enable-native-access=ALL-UNNAMED
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
defaults:
run:
working-directory: de.peeeq.wurstscript

shell: bash
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
fetch-depth: 0 # your version task uses git describe

ref: ${{ github.sha }}
fetch-depth: 0
- name: Setup JDK 27
uses: actions/setup-java@v4
with:
# Temurin 27 has no macOS x64 build; Zulu keeps the Intel artifact supported.
distribution: ${{ matrix.os == 'macos-15-intel' && 'zulu' || 'temurin' }}
java-version: '27'
# Ubuntu's system-modified JDK cannot always serve as a jlink input.
- name: Install portable Temurin for Linux packaging
if: runner.os == 'Linux'
run: |
set -euo pipefail
mkdir -p "$RUNNER_TEMP/temurin27"
curl -fsSL 'https://github.com/adoptium/temurin27-binaries/releases/download/jdk-27%2B35/OpenJDK27U-jdk_x64_linux_hotspot_27_35.tar.gz' -o "$RUNNER_TEMP/temurin27/jdk.tar.gz"
tar -xzf "$RUNNER_TEMP/temurin27/jdk.tar.gz" -C "$RUNNER_TEMP/temurin27"
PORTABLE_JAVA_HOME=$(find "$RUNNER_TEMP/temurin27" -maxdepth 1 -type d -name 'jdk-27*' | head -n1)
echo "PORTABLE_JAVA_HOME=$PORTABLE_JAVA_HOME" >> "$GITHUB_ENV"
echo "$PORTABLE_JAVA_HOME/bin" >> "$GITHUB_PATH"
- name: Pin Gradle toolchain
run: |
ACTIVE_JAVA_HOME="${PORTABLE_JAVA_HOME:-$JAVA_HOME}"
echo "JAVA_HOME=${ACTIVE_JAVA_HOME}" >> "$GITHUB_ENV"
echo "${ACTIVE_JAVA_HOME}/bin" >> "$GITHUB_PATH"
echo "org.gradle.java.installations.paths=${ACTIVE_JAVA_HOME}" >> gradle.properties
echo "org.gradle.java.installations.auto-detect=false" >> gradle.properties
- uses: gradle/actions/wrapper-validation@v4
- uses: gradle/actions/setup-gradle@v4
- name: Install Lua 5.3 for Linux tests
if: runner.os == 'Linux'
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends lua5.3
chmod +x src/test/resources/lua53 src/test/resources/luac53
- name: Install Lua for macOS tests
if: runner.os == 'macOS'
env:
HOMEBREW_NO_AUTO_UPDATE: '1'
run: brew install lua
- name: Test game-data helpers
run: ./gradlew -p ../HelperScripts test --no-daemon --stacktrace --quiet
- name: Test compiler and package runtime
run: ./gradlew test packageSlimCompilerDist --no-daemon --stacktrace
- name: Verify packaged compiler version
run: |
set -euo pipefail
JAVA_BIN=build/dist/slim-${{ matrix.plat }}/wurst-runtime/bin/java
if [[ "$RUNNER_OS" == "Windows" ]]; then JAVA_BIN="$JAVA_BIN.exe"; fi
actual=$("$JAVA_BIN" -jar build/dist/slim-${{ matrix.plat }}/wurst-compiler/wurstscript.jar -version)
# Native Java prints CRLF on Windows; remove any CR left by command substitution.
actual=${actual%$'\r'}
test "$actual" = "$RELEASE_VERSION"
Comment on lines +114 to +117

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Normalize Windows version output before comparing

In the windows-latest matrix job, this runs native java.exe under Git Bash. System.out.println emits CRLF on Windows, while Bash command substitution strips the trailing LF but retains the \r, so actual becomes 2.0.0\r and cannot equal RELEASE_VERSION. Because publish requires the entire build matrix, every release is blocked at this check; strip the carriage return or otherwise normalize the captured output before comparing.

Useful? React with 👍 / 👎.

- uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.plat }}
path: de.peeeq.wurstscript/build/releases/wurst-compiler-${{ needs.validate.outputs.version }}-${{ matrix.plat }}.zip
if-no-files-found: error
retention-days: 14
- name: Report test results
if: always()
uses: mikepenz/action-junit-report@v4
with:
report_paths: de.peeeq.wurstscript/build/test-results/**/*.xml
check_name: Release tests (${{ matrix.plat }})

- name: Validate Gradle wrapper
uses: gradle/actions/wrapper-validation@v4

- name: Setup Gradle cache
uses: gradle/actions/setup-gradle@v4

# Build fat jar + jdeps + jlink + package + checksum for this OS
- name: Package slim runtime (per-OS)
run: ./gradlew --no-daemon --stacktrace packageSlimCompilerDist

- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
publish:
name: Publish complete versioned release
needs: [validate, build]
runs-on: ubuntu-latest
permissions:
contents: write
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ github.ref_name }}
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
steps:
- uses: actions/checkout@v4
with:
# Attaches the per-OS files produced on this runner
files: |
de.peeeq.wurstscript/build/releases/wurst-compiler-*-*.zip
de.peeeq.wurstscript/build/releases/wurst-compiler-*-*.tar.gz
de.peeeq.wurstscript/build/releases/*.sha256
tag_name: ${{ github.ref_name }} # ensures assets attach to the pushed v* tag
name: ${{ github.ref_name }}
draft: false
prerelease: false
generate_release_notes: true
ref: ${{ github.sha }}
fetch-depth: 0
- name: Revalidate release commit
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

RELEASE_REF: ${{ github.ref }}
run: |
git fetch origin master
python scripts/validate-release.py "$RELEASE_REF"
- uses: actions/download-artifact@v4
with:
pattern: release-*
path: release-assets
merge-multiple: true
- name: Verify complete platform set and checksum assets
working-directory: release-assets
run: |
set -euo pipefail
for platform in win-x64 linux-x64 macos-x64 macos-arm64; do
file="wurst-compiler-$RELEASE_VERSION-$platform.zip"
test -s "$file"
sha256sum "$file" > "$file.sha256"
done
# Publish only after every platform passed; never update a published release.
- name: Publish release
run: |
set -euo pipefail
if gh release view "$RELEASE_TAG" --json isDraft > release-state.json; then
if ! python -c 'import json,sys; sys.exit(0 if json.load(open("release-state.json"))["isDraft"] else 1)'; then
echo "Release $RELEASE_TAG is already published; refusing to replace its assets."
exit 1
fi
else
gh release create "$RELEASE_TAG" --verify-tag --draft --title "$RELEASE_TAG" --generate-notes
fi
gh release upload "$RELEASE_TAG" release-assets/* --clobber
gh release edit "$RELEASE_TAG" --draft=false --latest
16 changes: 9 additions & 7 deletions de.peeeq.wurstscript/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ import java.util.regex.Pattern

ext.mainClassName = "de.peeeq.wurstio.Main"

version = "1.9.0.0"
version = providers.fileContents(layout.projectDirectory.file('version.txt')).asText.get().trim()
if (!(version ==~ /(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)\.(?:0|[1-9][0-9]*)/)) {
throw new GradleException('version.txt must contain MAJOR.MINOR.PATCH')
}

java {
toolchain {
Expand Down Expand Up @@ -247,22 +250,21 @@ tasks.register('versionInfoFile') {
workingDir(repoDir)
commandLine('git', 'rev-parse', '--short=8', 'HEAD')
}.standardOutput.asText.map { it.trim() }
def description = providers.exec {
def releaseTag = providers.exec {
workingDir(repoDir)
commandLine('git', 'describe', '--tags', '--always')
commandLine('git', 'tag', '--points-at', 'HEAD', '--list', "v${versionString}")
}.standardOutput.asText.map { it.trim() }

inputs.property("projectVersion", versionString)
inputs.property("gitRevision", revision)
inputs.property("gitShortRevision", shortRevision)
inputs.property("gitDescription", description)
inputs.property("releaseTag", releaseTag)

doLast {
def rev8 = shortRevision.get()
def revLong = revision.get()
def tag = description.get()

def wurstVersion = "${versionString}-${tag}"
def wurstVersion = releaseTag.get() == "v${versionString}"
? versionString : "${versionString}-dev+${rev8}"

dir.mkdirs()
out.text = """
Expand Down
1 change: 1 addition & 0 deletions de.peeeq.wurstscript/version.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.0.0
Loading
Loading