Skip to content

Release

Release #47

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Release version, e.g. 0.1.0"
required: true
type: string
channel:
description: "Update channel"
required: true
default: "stable"
type: choice
options:
- stable
- beta
- alpha
prerelease:
description: "Publish as prerelease"
required: true
default: false
type: boolean
permissions:
contents: write
jobs:
build-natives:
name: native ${{ matrix.label }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: true
matrix:
include:
- label: linux-x64
runner: ubuntu-latest
target: x86_64-unknown-linux-gnu
lib: librapier_moud.so
- label: linux-arm64
runner: ubuntu-latest
target: aarch64-unknown-linux-gnu
lib: librapier_moud.so
apt: gcc-aarch64-linux-gnu
linker: aarch64-linux-gnu-gcc
- label: windows-x64
runner: windows-latest
target: x86_64-pc-windows-msvc
lib: rapier_moud.dll
- label: macos-x64
runner: macos-14
target: x86_64-apple-darwin
lib: librapier_moud.dylib
- label: macos-arm64
runner: macos-14
target: aarch64-apple-darwin
lib: librapier_moud.dylib
steps:
- uses: actions/checkout@v4
- name: install rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: install cross-linker (linux-arm64)
if: matrix.apt != ''
run: sudo apt-get update && sudo apt-get install -y ${{ matrix.apt }}
- name: configure linker (linux-arm64)
if: matrix.linker != ''
run: |
mkdir -p .cargo
printf '[target.%s]\nlinker = "%s"\n' "${{ matrix.target }}" "${{ matrix.linker }}" > .cargo/config.toml
working-directory: physics-natives
- name: cargo build
run: cargo build --release --target ${{ matrix.target }}
working-directory: physics-natives
- name: upload artifact
uses: actions/upload-artifact@v4
with:
name: native-${{ matrix.label }}
path: physics-natives/target/${{ matrix.target }}/release/${{ matrix.lib }}
if-no-files-found: error
build-release:
needs: build-natives
runs-on: ubuntu-latest
environment: Production
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download native artifacts
uses: actions/download-artifact@v4
with:
path: native-artifacts
- name: Stage native binaries into physics-rapier
shell: bash
run: |
set -eux
stage() {
local label="$1" lib="$2" dir="$3"
install -Dm755 "native-artifacts/native-${label}/${lib}" \
"physics-rapier/src/main/resources/natives/${dir}/${lib}"
}
stage linux-x64 librapier_moud.so linux-x64
stage linux-arm64 librapier_moud.so linux-arm64
stage windows-x64 rapier_moud.dll windows-x64
stage macos-x64 librapier_moud.dylib macos-x64
stage macos-arm64 librapier_moud.dylib macos-arm64
- name: Set up Java 25
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "25-ea"
- name: Set up Java 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: gradle
- name: Make Gradle executable
run: chmod +x ./gradlew
- name: Install vendored libs to mavenLocal
shell: bash
run: |
for spec in "com/miry/miry:libs/miry-1.0-SNAPSHOT.jar:1.0-SNAPSHOT" \
"fr/mrqsdf/BbModelReader:libs/BbModelReader-1.0-SNAPSHOT.jar:1.0-SNAPSHOT" \
"moud/vendored/luau-natives-windows-x64:libs/luau-natives-windows-x64-1.0.0-moud.jar:1.0.0"; do
IFS=: read -r coords jar version <<< "$spec"
group="${coords%/*}"
artifact="${coords##*/}"
dest="$HOME/.m2/repository/${coords}/${version}"
mkdir -p "$dest"
cp "$jar" "$dest/${artifact}-${version}.jar"
cat > "$dest/${artifact}-${version}.pom" <<POMEOF
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"><modelVersion>4.0.0</modelVersion>
<groupId>${group//\//.}</groupId><artifactId>${artifact}</artifactId><version>${version}</version>
</project>
POMEOF
done
- name: Resolve release metadata
id: meta
shell: bash
run: |
set -euo pipefail
if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then
TAG="${GITHUB_REF_NAME}"
VERSION="${TAG#v}"
CHANNEL="stable"
PRERELEASE="false"
else
VERSION="${{ inputs.version }}"
VERSION="${VERSION#v}"
TAG="v${VERSION}"
CHANNEL="${{ inputs.channel }}"
PRERELEASE="${{ inputs.prerelease }}"
fi
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "channel=${CHANNEL}" >> "$GITHUB_OUTPUT"
echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
- name: Build artifacts
run: |
./gradlew \
:moud-bootstrap:remapJar \
:client-launcher:shadowJar \
:client-fabric:remapRuntimeJar \
:server-minestom:shadowJar \
:server-supervisor:shadowJar \
-Pmoud.server.enableLuau=true \
-Pmoud.server.java=25
- name: Package release archives
id: package
shell: bash
run: |
set -euo pipefail
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
CLIENT_JAR="$(find client-fabric/build/libs -maxdepth 1 -type f -name '*-runtime.jar' ! -name '*-sources.jar' | sort | head -n1)"
BOOTSTRAP_JAR="$(find moud-bootstrap/build/libs -maxdepth 1 -type f -name '*.jar' ! -name '*-sources.jar' | sort | head -n1)"
CLIENT_LAUNCHER_JAR="$(find client-launcher/build/libs -maxdepth 1 -type f -name '*.jar' ! -name '*-sources.jar' | sort | head -n1)"
SERVER_JAR="$(find server-minestom/build/libs -maxdepth 1 -type f -name '*.jar' ! -name '*-plain.jar' ! -name '*-sources.jar' | sort | head -n1)"
SUPERVISOR_JAR="$(find server-supervisor/build/libs -maxdepth 1 -type f -name '*.jar' ! -name '*-plain.jar' ! -name '*-sources.jar' | sort | head -n1)"
if [[ -z "${CLIENT_JAR}" || ! -f "${CLIENT_JAR}" ]]; then
echo "Client jar not found" >&2; exit 1
fi
if [[ -z "${BOOTSTRAP_JAR}" || ! -f "${BOOTSTRAP_JAR}" ]]; then
echo "Bootstrap jar not found" >&2; exit 1
fi
if [[ -z "${CLIENT_LAUNCHER_JAR}" || ! -f "${CLIENT_LAUNCHER_JAR}" ]]; then
echo "Client launcher jar not found" >&2; exit 1
fi
if [[ -z "${SERVER_JAR}" || ! -f "${SERVER_JAR}" ]]; then
echo "Server jar not found" >&2; exit 1
fi
rm -rf dist
mkdir -p dist/stage/client/engine/mods
mkdir -p dist/stage/server/engine
cp "${CLIENT_JAR}" "dist/stage/client/engine/mods/moud-client.jar"
cp "${SERVER_JAR}" "dist/stage/server/engine/moud-server.jar"
printf '%s\n' "${VERSION}" > dist/stage/client/engine/VERSION
printf '%s\n' "${VERSION}" > dist/stage/server/engine/VERSION
printf '%s\n' "${TAG}" > dist/stage/client/engine/RELEASE_TAG
printf '%s\n' "${TAG}" > dist/stage/server/engine/RELEASE_TAG
CLIENT_ARCHIVE="moud-client-${VERSION}.tar.gz"
SERVER_ARCHIVE="moud-server-${VERSION}.tar.gz"
tar --sort=name --mtime='UTC 2024-01-01' --owner=0 --group=0 --numeric-owner \
-C dist/stage/client -czf "dist/${CLIENT_ARCHIVE}" engine
tar --sort=name --mtime='UTC 2024-01-01' --owner=0 --group=0 --numeric-owner \
-C dist/stage/server -czf "dist/${SERVER_ARCHIVE}" engine
echo "client_archive=${CLIENT_ARCHIVE}" >> "$GITHUB_OUTPUT"
echo "server_archive=${SERVER_ARCHIVE}" >> "$GITHUB_OUTPUT"
cp "${BOOTSTRAP_JAR}" "dist/moud-bootstrap-${VERSION}.jar"
echo "bootstrap_jar=moud-bootstrap-${VERSION}.jar" >> "$GITHUB_OUTPUT"
cp "${CLIENT_LAUNCHER_JAR}" "dist/moud-client-launcher-${VERSION}.jar"
echo "client_launcher_jar=moud-client-launcher-${VERSION}.jar" >> "$GITHUB_OUTPUT"
if [[ -n "${SUPERVISOR_JAR}" && -f "${SUPERVISOR_JAR}" ]]; then
cp "${SUPERVISOR_JAR}" "dist/moud-supervisor-${VERSION}.jar"
echo "supervisor_jar=moud-supervisor-${VERSION}.jar" >> "$GITHUB_OUTPUT"
fi
- name: Generate signed release metadata
shell: bash
env:
RELEASE_SIGNING_PRIVATE_KEY: ${{ secrets.MOUD_RELEASE_SIGNING_PRIVATE_KEY }}
run: |
set -euo pipefail
if [[ -z "${RELEASE_SIGNING_PRIVATE_KEY:-}" ]]; then
echo "Missing secret MOUD_RELEASE_SIGNING_PRIVATE_KEY" >&2
exit 1
fi
VERSION="${{ steps.meta.outputs.version }}"
CHANNEL="${{ steps.meta.outputs.channel }}"
TAG="${{ steps.meta.outputs.tag }}"
BASE_URL="https://github.com/${{ github.repository }}/releases/download/${TAG}"
python3 tools/release_manifest.py \
--version "${VERSION}" \
--channel "${CHANNEL}" \
--base-download-url "${BASE_URL}" \
--client-archive "dist/${{ steps.package.outputs.client_archive }}" \
--server-archive "dist/${{ steps.package.outputs.server_archive }}" \
--output "dist/release.json"
echo "${RELEASE_SIGNING_PRIVATE_KEY}" | base64 -d > dist/release-key.pem
openssl pkey -in dist/release-key.pem -noout 2>/dev/null || {
echo "Invalid private key — store the PEM file as base64 in the secret" >&2
exit 1
}
openssl pkeyutl -sign -rawin -inkey dist/release-key.pem -in dist/release.json -out dist/release.sig.bin
base64 -w0 dist/release.sig.bin > dist/release.sig
rm -f dist/release-key.pem dist/release.sig.bin
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.meta.outputs.tag }}
name: Moud ${{ steps.meta.outputs.version }}
draft: false
prerelease: ${{ steps.meta.outputs.prerelease == 'true' }}
generate_release_notes: true
files: |
dist/${{ steps.package.outputs.client_archive }}
dist/${{ steps.package.outputs.server_archive }}
dist/${{ steps.package.outputs.bootstrap_jar }}
dist/${{ steps.package.outputs.client_launcher_jar }}
dist/${{ steps.package.outputs.supervisor_jar }}
dist/release.json
dist/release.sig