Skip to content

Release client

Release client #11

name: Release client
on:
push:
tags: ["client-v*"]
schedule:
- cron: "7 18 * * 0" # Sundays 18:07 UTC (weekly pre-alpha snapshot of master)
workflow_dispatch:
inputs:
version:
description: "Version core, e.g. 0.2.0 (blank = bump patch from latest)"
required: false
default: ""
env:
CARGO_TERM_COLOR: always
MC_VERSION: "26.2"
permissions:
contents: write
jobs:
check:
runs-on: ubuntu-latest
outputs:
should_release: ${{ steps.check.outputs.should_release }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Check for new commits since last release
id: check
shell: bash
run: |
# Only the weekly cron skips an unchanged master; manual/tag runs always release.
if [ "${{ github.event_name }}" != "schedule" ]; then
echo "should_release=true" >> "$GITHUB_OUTPUT"
exit 0
fi
git fetch --tags --force
last_tag=$(git tag --list 'client-v*' --sort=-v:refname | head -n1)
if [ -z "$last_tag" ] || [ -n "$(git rev-list "${last_tag}..HEAD")" ]; then
echo "should_release=true" >> "$GITHUB_OUTPUT"
else
echo "should_release=false" >> "$GITHUB_OUTPUT"
echo "No new commits on master since ${last_tag}; skipping weekly release."
fi
build-client:
needs: check
if: needs.check.outputs.should_release == 'true'
strategy:
matrix:
include:
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact: pomme-client.exe
name: pomme-client-windows-x64
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: pomme-client
name: pomme-client-linux-x64-gnu
- os: macos-latest
target: aarch64-apple-darwin
artifact: pomme-client
name: pomme-client-macos-arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- uses: dtolnay/rust-toolchain@nightly
with:
targets: ${{ matrix.target }}
- name: Install Vulkan SDK
uses: jakoch/install-vulkan-sdk-action@37effcfa045411f8bfbbda26df2fd1b3bf3436fa
with:
vulkan_version: 1.4.341.0
install_runtime: false
cache: true
stripdown: true
- name: Install Linux dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libvulkan-dev cmake libxkbcommon-dev libwayland-dev libasound2-dev libudev-dev
- name: Build
run: cargo build -p pomme-client --release --target ${{ matrix.target }}
- name: Package (Unix)
if: matrix.os != 'windows-latest'
shell: bash
run: |
mkdir -p dist bundle
cp "target/${{ matrix.target }}/release/${{ matrix.artifact }}" bundle/
# macOS has no system Vulkan, so ship the loader + MoltenVK + ICD next
# to the binary (build.rs gives it an @executable_path rpath).
if [ "${{ matrix.os }}" = "macos-latest" ]; then
findlib() { find "$VULKAN_SDK" -name "$1" | head -n1; }
loader=$(findlib libvulkan.1.dylib)
mvk=$(findlib libMoltenVK.dylib)
icd=$(findlib MoltenVK_icd.json)
if [ -z "$loader" ] || [ -z "$mvk" ] || [ -z "$icd" ]; then
echo "::error::Vulkan runtime not found under VULKAN_SDK=$VULKAN_SDK (loader='$loader' mvk='$mvk' icd='$icd')"
exit 1
fi
cp "$loader" "$mvk" bundle/
sed -E 's#("library_path"[[:space:]]*:[[:space:]]*)"[^"]*"#\1"./libMoltenVK.dylib"#' \
"$icd" > bundle/MoltenVK_icd.json
fi
(cd bundle && zip -j "../dist/${{ matrix.name }}.zip" ./*)
- name: Package (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
New-Item -ItemType Directory -Force dist | Out-Null
Compress-Archive -Path "target/${{ matrix.target }}/release/${{ matrix.artifact }}" -DestinationPath "dist/${{ matrix.name }}.zip"
- uses: actions/upload-artifact@v7
with:
name: ${{ matrix.name }}
path: dist/
if-no-files-found: error
release-client:
needs: [check, build-client]
if: needs.check.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Resolve release tag
id: rel
shell: bash
run: |
git fetch --tags --force
tags=$(git tag --list 'client-v*')
if [ "${{ github.event_name }}" = "push" ]; then
tag="${{ github.ref_name }}"
else
core="${{ inputs.version }}"
if [ -z "$core" ]; then
latest=$(echo "$tags" \
| sed -nE 's/^client-v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/p' \
| sort -V | tail -n1)
if [ -z "$latest" ]; then
core="0.1.0"
else
IFS=. read -r ma mi pa <<< "$latest"
core="$ma.$mi.$((pa + 1))"
fi
fi
tag="client-v${core}+${MC_VERSION}"
fi
prev=$(echo "$tags" | grep -vFx "$tag" | sort -V | tail -n1 || true)
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "prev=$prev" >> "$GITHUB_OUTPUT"
- uses: actions/download-artifact@v8
with:
path: dist
merge-multiple: true
- name: Generate checksums
run: |
cd dist
sha256sum *.zip > sha256sums.txt
- uses: softprops/action-gh-release@v3
with:
tag_name: ${{ steps.rel.outputs.tag }}
prerelease: false
# Keep the "Latest" badge on the launcher release, not the weekly client.
make_latest: false
previous_tag: ${{ steps.rel.outputs.prev }}
files: dist/*
generate_release_notes: ${{ steps.rel.outputs.prev != '' }}
- name: Announce release on Discord
if: steps.rel.outputs.prev != ''
continue-on-error: true
env:
GH_TOKEN: ${{ github.token }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
TAG: ${{ steps.rel.outputs.tag }}
shell: bash
run: |
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
echo "No DISCORD_WEBHOOK_URL secret set; skipping Discord announcement."
exit 0
fi
body=$(gh release view "$TAG" --json body --jq .body)
url=$(gh release view "$TAG" --json url --jq .url)
# Discord embed descriptions cap at 4096 chars; trim and link to the full notes.
max=3900
if [ "${#body}" -gt "$max" ]; then
body="${body:0:$max}"$'\n\n'"…[full changelog]($url)"
fi
role_id="1513130412367675523"
payload=$(jq -n \
--arg title "Pomme $TAG" \
--arg desc "$body" \
--arg url "$url" \
--arg content "<@&$role_id> New Pomme release is out!" \
--arg role "$role_id" \
'{
username: "Pomme Releases",
content: $content,
allowed_mentions: { roles: [$role] },
embeds: [{ title: $title, url: $url, description: $desc, color: 5763719 }]
}')
curl -fsS -X POST -H "Content-Type: application/json" -d "$payload" "$DISCORD_WEBHOOK_URL"