mirror of
https://github.com/praktimarc/kst4contest.git
synced 2026-10-19 05:42:58 +02:00
* Move remaining references to the HamRadioOnline organisation The repository moved from praktimarc/kst4contest to HamRadioOnline/kst4contest. Document the move in the German and English changelog, point manuals, README, website, AUR packaging and the version-feed tooling at the new address, and keep accepting pre-move release URLs in the update-feed validator because published feeds still carry the old owner. Personal identities (Ko-Fi account, contact e-mail) stay unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WFGQ7wkSPo21itLMHPi8Yw * Lowercase the owner in the generated Flatpak Pages URL GITHUB_REPOSITORY_OWNER is now the mixed-case HamRadioOnline, and the next build would write that spelling into the published flatpakrepo and flatpakref files. Hostnames are case-insensitive, but the published metadata should match the documented lowercase address. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WFGQ7wkSPo21itLMHPi8Yw * Build the Flatpak against org.freedesktop.Platform 25.08 Runtime branch 24.08 is end-of-life and no longer receives security updates, so every flatpak update now prints an EOL warning. 25.08 is the current supported branch on Flathub. The app bundles its own Java runtime, so the platform bump only changes the base libraries. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WFGQ7wkSPo21itLMHPi8Yw --------- Co-authored-by: Claude <noreply@anthropic.com>
710 lines
27 KiB
YAML
710 lines
27 KiB
YAML
name: Nightly Runtime Artifacts
|
||
|
||
on:
|
||
push:
|
||
branches:
|
||
- main
|
||
paths:
|
||
- "packaging/icons/**"
|
||
- "packaging/macos/**"
|
||
- "core/**"
|
||
- "app-desktop/**"
|
||
- "*.gradle.kts"
|
||
- "gradle.properties"
|
||
- "gradle/**"
|
||
- "gradlew"
|
||
- "gradlew.bat"
|
||
- ".github/workflows/nightly-artifacts.yml"
|
||
workflow_dispatch:
|
||
|
||
env:
|
||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
||
|
||
permissions:
|
||
contents: write
|
||
packages: write
|
||
|
||
jobs:
|
||
# Same job as in pr-compile-check.yml, copied rather than shared: a reusable workflow
|
||
# would be one more indirection to read, and the comments belong next to the steps they
|
||
# explain. Every packaging job below needs this one, so a commit whose tests fail builds
|
||
# no artifact (#62). Edit all three copies together.
|
||
test:
|
||
name: Test (Java 21, headless)
|
||
runs-on: ubuntu-latest
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
# Skiko's native library links against libGL, so it has to be loadable even though
|
||
# nothing here renders through it: the drawing tests use Skia's software backend and
|
||
# runComposeUiTest never opens a window. Without this the whole Compose half of the
|
||
# suite dies with "libskiko-linux-x64.so: libGL.so.1: cannot open shared object
|
||
# file" -- which reads like a missing display and is not one. Found by running this
|
||
# job under act, where the container has no libGL; GitHub's own runner image happens
|
||
# to ship it, so the step is what makes the job reproducible off GitHub.
|
||
- name: Install the OpenGL client library skiko links against
|
||
run: |
|
||
sudo apt-get update
|
||
sudo apt-get install -y --no-install-recommends libgl1
|
||
|
||
# No Xvfb, deliberately. Everything that pins behaviour runs without a display:
|
||
# runComposeUiTest reaches the semantics tree headless (measured before this job was
|
||
# written), and the ImageComposeScene drawing tests render in software. The handful
|
||
# of tests that open a real window guard themselves with assumeFalse(isHeadless) and
|
||
# skip here; the summary below prints the skip count, so that is visible rather than
|
||
# assumed.
|
||
#
|
||
# Software GL under Xvfb was considered and rejected: a missing Skia GL context is
|
||
# the hardest failure in this codebase to read, and importing that class of flake
|
||
# into CI would cost more than the few window tests are worth here.
|
||
|
||
# All three modules. The translation generator is a Gradle module and not buildSrc
|
||
# precisely so that its 42 tests run here: buildSrc tests do not run on `./gradlew
|
||
# build` -- measured, not assumed. The summary below globs */build/test-results, so
|
||
# the module was counted the moment it existed.
|
||
- name: Test
|
||
run: ./gradlew -S test
|
||
|
||
- name: Summarise the test results
|
||
if: always()
|
||
run: |
|
||
set -euo pipefail
|
||
shopt -s nullglob
|
||
files=(*/build/test-results/test/TEST-*.xml)
|
||
if [ ${#files[@]} -eq 0 ]; then
|
||
echo "No test result XML was produced -- the test task did not run." >&2
|
||
exit 1
|
||
fi
|
||
# Counted from the XML and not from Gradle's console output: this project's own
|
||
# rule is never to infer "all tests passed" from an exit code.
|
||
summary=$(grep -h "<testsuite " "${files[@]}" \
|
||
| sed 's/.*tests="\([0-9]*\)".*skipped="\([0-9]*\)".*failures="\([0-9]*\)".*errors="\([0-9]*\)".*/\1 \2 \3 \4/' \
|
||
| awk '{t+=$1; s+=$2; f+=$3; e+=$4} END {print t" "s" "f" "e}')
|
||
read -r total skipped failures errors <<< "$summary"
|
||
echo "tests=$total skipped=$skipped failures=$failures errors=$errors"
|
||
{
|
||
echo "### Tests"
|
||
echo ""
|
||
echo "| total | skipped | failures | errors |"
|
||
echo "|---|---|---|---|"
|
||
echo "| $total | $skipped | $failures | $errors |"
|
||
echo ""
|
||
echo "Skipped are the tests that need a display, plus the deliberately"
|
||
echo "disabled reference-data generator. This job runs headless on purpose."
|
||
} >> "$GITHUB_STEP_SUMMARY"
|
||
if [ "$failures" != "0" ] || [ "$errors" != "0" ]; then
|
||
echo "The result XML reports failures or errors." >&2
|
||
exit 1
|
||
fi
|
||
|
||
- name: Keep the test reports on a failure
|
||
if: failure()
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: test-results
|
||
path: |
|
||
*/build/test-results/test/
|
||
*/build/reports/tests/test/
|
||
if-no-files-found: ignore
|
||
retention-days: 7
|
||
|
||
build-windows-zip:
|
||
name: Build Windows ZIP
|
||
runs-on: windows-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
shell: pwsh
|
||
run: |
|
||
$version = (Select-String -Path gradle.properties -Pattern '^version=').Line.Split('=')[1]
|
||
$shortSha = "${{ github.sha }}".Substring(0, 7)
|
||
Add-Content -Path $env:GITHUB_ENV -Value "VERSION=$version"
|
||
Add-Content -Path $env:GITHUB_ENV -Value "SHORT_SHA=$shortSha"
|
||
Add-Content -Path $env:GITHUB_ENV -Value "ASSET_BASENAME=praktiKST-$version-$shortSha"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Install WiX Toolset
|
||
shell: pwsh
|
||
run: choco install wixtoolset --no-progress -y
|
||
|
||
- name: Build app-image
|
||
shell: pwsh
|
||
run: |
|
||
.\gradlew.bat -S :app-desktop:createDistributable
|
||
New-Item -ItemType Directory -Force -Path dist | Out-Null
|
||
# The next step reads dist/KST4Contest, so the Compose output goes
|
||
# there. The module list now lives in app-desktop/build.gradle.kts.
|
||
if (Test-Path dist/KST4Contest) { Remove-Item -Recurse -Force dist/KST4Contest }
|
||
Copy-Item -Recurse app-desktop/build/compose/binaries/main/app/KST4Contest dist/KST4Contest
|
||
|
||
- name: Create Windows ZIP
|
||
shell: pwsh
|
||
run: |
|
||
if (-not (Test-Path dist/KST4Contest)) {
|
||
throw "No Windows app-image produced by createDistributable"
|
||
}
|
||
Compress-Archive -Path dist/KST4Contest -DestinationPath "dist/$env:ASSET_BASENAME-windows-x64.zip" -Force
|
||
|
||
- name: Upload Windows artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: windows-zip
|
||
path: dist/praktiKST-*-windows-x64.zip
|
||
retention-days: 14
|
||
|
||
build-linux-appimage:
|
||
name: Build Linux AppImage
|
||
runs-on: ubuntu-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Build app-image
|
||
run: |
|
||
./gradlew -S :app-desktop:createDistributable
|
||
mkdir -p dist
|
||
# The following steps read dist/KST4Contest, so the Compose output goes
|
||
# there. The module list now lives in app-desktop/build.gradle.kts.
|
||
rm -rf dist/KST4Contest
|
||
cp -a app-desktop/build/compose/binaries/main/app/KST4Contest dist/
|
||
|
||
- name: Create AppDir metadata
|
||
run: |
|
||
mkdir -p target
|
||
rm -rf target/KST4Contest.AppDir
|
||
cp -a dist/KST4Contest target/KST4Contest.AppDir
|
||
|
||
cat > target/KST4Contest.AppDir/AppRun << 'EOF'
|
||
#!/bin/sh
|
||
HERE="$(dirname "$(readlink -f "$0")")"
|
||
exec "$HERE/bin/KST4Contest" "$@"
|
||
EOF
|
||
chmod +x target/KST4Contest.AppDir/AppRun
|
||
|
||
cat > target/KST4Contest.AppDir/KST4Contest.desktop << 'EOF'
|
||
[Desktop Entry]
|
||
Type=Application
|
||
Name=KST4Contest
|
||
Exec=KST4Contest
|
||
Icon=KST4Contest
|
||
Categories=Network;HamRadio;
|
||
Terminal=false
|
||
EOF
|
||
|
||
if [ -f target/KST4Contest.AppDir/lib/KST4Contest.png ]; then
|
||
cp target/KST4Contest.AppDir/lib/KST4Contest.png target/KST4Contest.AppDir/KST4Contest.png
|
||
fi
|
||
|
||
- name: Build AppImage
|
||
run: |
|
||
mkdir -p target
|
||
wget -q -O target/appimagetool.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
|
||
chmod +x target/appimagetool.AppImage
|
||
APPIMAGE_EXTRACT_AND_RUN=1 ARCH=x86_64 target/appimagetool.AppImage target/KST4Contest.AppDir "dist/${ASSET_BASENAME}-linux-x86_64.AppImage"
|
||
|
||
- name: Upload Linux artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: linux-appimage
|
||
path: dist/KST4Contest-*-linux-x86_64.AppImage
|
||
retention-days: 14
|
||
|
||
build-linux-deb:
|
||
name: Build Debian package
|
||
runs-on: ubuntu-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Install packaging dependencies
|
||
run: |
|
||
sudo apt-get update -qq
|
||
sudo apt-get install -y --no-install-recommends fakeroot
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Build Debian package
|
||
run: |
|
||
./gradlew -S :app-desktop:packageDeb
|
||
mkdir -p dist
|
||
DEB="$(ls app-desktop/build/compose/binaries/main/deb/*.deb | head -n 1)"
|
||
if [ -z "$DEB" ]; then
|
||
echo "No DEB produced by packageDeb" && exit 1
|
||
fi
|
||
mv "$DEB" "dist/${ASSET_BASENAME}-debian-amd64.deb"
|
||
|
||
- name: Upload Debian artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: linux-debian
|
||
path: dist/KST4Contest-*-debian-amd64.deb
|
||
retention-days: 14
|
||
|
||
build-linux-rpm:
|
||
name: Build Fedora package
|
||
runs-on: ubuntu-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Install packaging dependencies
|
||
run: |
|
||
sudo apt-get update -qq
|
||
sudo apt-get install -y --no-install-recommends rpm
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Build Fedora package
|
||
run: |
|
||
./gradlew -S :app-desktop:packageRpm
|
||
mkdir -p dist
|
||
RPM="$(ls app-desktop/build/compose/binaries/main/rpm/*.rpm | head -n 1)"
|
||
if [ -z "$RPM" ]; then
|
||
echo "No RPM produced by packageRpm" && exit 1
|
||
fi
|
||
mv "$RPM" "dist/${ASSET_BASENAME}-fedora-x86_64.rpm"
|
||
|
||
- name: Upload Fedora artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: linux-fedora
|
||
path: dist/KST4Contest-*-fedora-x86_64.rpm
|
||
retention-days: 14
|
||
|
||
build-linux-arch:
|
||
name: Build Arch Linux package
|
||
runs-on: ubuntu-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
||
echo "SHORT_SHA=$SHORT_SHA" >> "$GITHUB_ENV"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Install packaging dependencies
|
||
run: |
|
||
sudo apt-get update -qq
|
||
sudo apt-get install -y --no-install-recommends zstd
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Build app-image
|
||
run: |
|
||
./gradlew -S :app-desktop:createDistributable
|
||
mkdir -p dist
|
||
# The following steps read dist/KST4Contest, so the Compose output goes
|
||
# there. The module list now lives in app-desktop/build.gradle.kts.
|
||
rm -rf dist/KST4Contest
|
||
cp -a app-desktop/build/compose/binaries/main/app/KST4Contest dist/
|
||
|
||
- name: Build Arch Linux package artifact
|
||
run: |
|
||
mkdir -p target
|
||
ARCH=$(uname -m)
|
||
PKGVER=$(printf '%s' "${VERSION}-${SHORT_SHA}" | sed 's/[^[:alnum:].+_]/_/g')
|
||
PKGROOT="target/archpkg"
|
||
rm -rf "$PKGROOT"
|
||
mkdir -p "$PKGROOT/usr/lib/KST4Contest" "$PKGROOT/usr/bin"
|
||
cp -a dist/KST4Contest/. "$PKGROOT/usr/lib/KST4Contest/"
|
||
cat > "$PKGROOT/usr/bin/KST4Contest" << 'EOF'
|
||
#!/bin/sh
|
||
exec /usr/lib/KST4Contest/bin/KST4Contest "$@"
|
||
EOF
|
||
chmod 755 "$PKGROOT/usr/bin/KST4Contest"
|
||
mkdir -p "$PKGROOT/usr/share/applications" "$PKGROOT/usr/share/icons/hicolor/256x256/apps"
|
||
cat > "$PKGROOT/usr/share/applications/KST4Contest.desktop" << 'EOF'
|
||
[Desktop Entry]
|
||
Type=Application
|
||
Name=KST4Contest
|
||
Comment=ON4KST Chat Client for VHF/UHF contest operation
|
||
Exec=KST4Contest
|
||
Icon=KST4Contest
|
||
Categories=Network;HamRadio;
|
||
Terminal=false
|
||
EOF
|
||
if [ -f "$PKGROOT/usr/lib/KST4Contest/lib/KST4Contest.png" ]; then
|
||
cp "$PKGROOT/usr/lib/KST4Contest/lib/KST4Contest.png" "$PKGROOT/usr/share/icons/hicolor/256x256/apps/KST4Contest.png"
|
||
fi
|
||
INSTALLED_SIZE=$(du -sb "$PKGROOT" | cut -f1)
|
||
BUILDDATE=$(date +%s)
|
||
WORKFLOW_SHA256=$(sha256sum "$GITHUB_WORKSPACE/.github/workflows/nightly-artifacts.yml" | awk '{print $1}')
|
||
{
|
||
echo "pkgname = kst4contest"
|
||
echo "pkgbase = kst4contest"
|
||
echo "xdata = pkgtype=pkg"
|
||
echo "pkgver = ${PKGVER}-1"
|
||
echo "pkgdesc = KST4Contest amateur radio contest logger"
|
||
echo "url = https://github.com/${{ github.repository }}"
|
||
echo "builddate = ${BUILDDATE}"
|
||
echo "packager = GitHub Actions"
|
||
echo "size = ${INSTALLED_SIZE}"
|
||
echo "arch = ${ARCH}"
|
||
echo "license = custom"
|
||
echo "depend = java-runtime"
|
||
echo "depend = gst-plugins-base"
|
||
echo "depend = gst-plugins-good"
|
||
} > "$PKGROOT/.PKGINFO"
|
||
{
|
||
echo "format = 2"
|
||
echo "pkgname = kst4contest"
|
||
echo "pkgbase = kst4contest"
|
||
echo "pkgver = ${PKGVER}-1"
|
||
echo "pkgarch = ${ARCH}"
|
||
echo "pkgbuild_sha256sum = ${WORKFLOW_SHA256}"
|
||
echo "packager = GitHub Actions"
|
||
echo "builddate = ${BUILDDATE}"
|
||
echo "builddir = /build"
|
||
echo "startdir = /build"
|
||
echo "buildtool = makepkg"
|
||
echo "buildtoolver = 7.0.0-1-x86_64"
|
||
echo "buildenv = !distcc !color !ccache check !sign"
|
||
echo "options = !strip docs libtool staticlibs emptydirs zipman purge !debug !lto"
|
||
} > "$PKGROOT/.BUILDINFO"
|
||
tar --zstd --transform 's|^\./||' -cf "dist/${ASSET_BASENAME}-archlinux-${ARCH}.pkg.tar.zst" -C "$PKGROOT" .
|
||
|
||
- name: Upload Arch Linux artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: linux-arch
|
||
path: dist/KST4Contest-*-archlinux-*.pkg.tar.zst
|
||
retention-days: 14
|
||
|
||
build-flatpak:
|
||
name: Build Flatpak
|
||
runs-on: ubuntu-latest
|
||
needs: test
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
||
echo "SHORT_SHA=$SHORT_SHA" >> "$GITHUB_ENV"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Install Flatpak tooling
|
||
run: |
|
||
sudo apt-get update -qq
|
||
sudo apt-get install -y --no-install-recommends flatpak flatpak-builder elfutils
|
||
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
||
flatpak --user install -y flathub org.freedesktop.Platform//25.08 org.freedesktop.Sdk//25.08
|
||
|
||
- name: Build app-image
|
||
run: |
|
||
./gradlew -S :app-desktop:createDistributable
|
||
mkdir -p target/flatpak-src
|
||
# The manifest's source is flatpak-src/KST4Contest.
|
||
rm -rf target/flatpak-src/KST4Contest
|
||
cp -a app-desktop/build/compose/binaries/main/app/KST4Contest target/flatpak-src/
|
||
|
||
- name: Create Flatpak manifest
|
||
run: |
|
||
mkdir -p target
|
||
mkdir -p dist
|
||
cat > target/de.x08.KST4Contest.yml << 'EOF'
|
||
app-id: de.x08.KST4Contest
|
||
runtime: org.freedesktop.Platform
|
||
runtime-version: "25.08"
|
||
sdk: org.freedesktop.Sdk
|
||
command: KST4Contest
|
||
finish-args:
|
||
- --socket=wayland
|
||
- --socket=x11
|
||
- --socket=pulseaudio
|
||
- --share=network
|
||
- --share=ipc
|
||
- --device=dri
|
||
- --filesystem=~/.praktiKST
|
||
- --env=ALSA_CONFIG_PATH=/app/share/alsa/asound.conf
|
||
modules:
|
||
- name: kst4contest
|
||
buildsystem: simple
|
||
build-commands:
|
||
- install -d /app/lib/KST4Contest /app/bin /app/share/applications /app/share/alsa
|
||
- printf '@include /usr/share/alsa/alsa.conf\npcm.!default { type pulse }\nctl.!default { type pulse }\n' > /app/share/alsa/asound.conf
|
||
- cp -a . /app/lib/KST4Contest/
|
||
- printf '#!/bin/sh\nexec /app/lib/KST4Contest/bin/KST4Contest "$@"\n' > /app/bin/KST4Contest
|
||
- chmod 755 /app/bin/KST4Contest
|
||
- echo '[Desktop Entry]' > /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Type=Application' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Name=KST4Contest' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Comment=ON4KST Chat Client for VHF/UHF contest operation' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Exec=KST4Contest' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Icon=de.x08.KST4Contest' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- printf 'Categories=Network;HamRadio;\n' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- echo 'Terminal=false' >> /app/share/applications/de.x08.KST4Contest.desktop
|
||
- test -f /app/lib/KST4Contest/lib/KST4Contest.png && install -Dm644 /app/lib/KST4Contest/lib/KST4Contest.png /app/share/icons/hicolor/256x256/apps/de.x08.KST4Contest.png || true
|
||
sources:
|
||
- type: dir
|
||
path: flatpak-src/KST4Contest
|
||
EOF
|
||
|
||
- name: Import Flatpak signing key
|
||
run: |
|
||
echo "${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}" | gpg --batch --import
|
||
FLATPAK_GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr/{print $10; exit}')
|
||
echo "FLATPAK_GPG_KEY_ID=$FLATPAK_GPG_KEY_ID" >> "$GITHUB_ENV"
|
||
|
||
- name: Build Flatpak repo (nightly)
|
||
run: |
|
||
mkdir -p target
|
||
flatpak-builder --force-clean target/flatpak-build target/de.x08.KST4Contest.yml
|
||
flatpak build-export --gpg-sign="$FLATPAK_GPG_KEY_ID" target/flatpak-repo target/flatpak-build nightly
|
||
flatpak build-update-repo --gpg-sign="$FLATPAK_GPG_KEY_ID" target/flatpak-repo
|
||
|
||
- name: Create flatpakref (nightly)
|
||
run: |
|
||
REPO_NAME="${GITHUB_REPOSITORY#*/}"
|
||
PAGES_URL="https://${GITHUB_REPOSITORY_OWNER,,}.github.io/${REPO_NAME}/"
|
||
GPG_KEY_B64=$(gpg --export "$FLATPAK_GPG_KEY_ID" | base64 -w 0)
|
||
cat > "dist/de.x08.KST4Contest.nightly.flatpakref" << EOF
|
||
[Flatpak Ref]
|
||
Name=de.x08.KST4Contest
|
||
Branch=nightly
|
||
Title=KST4Contest (Nightly) – ON4KST Chat Client
|
||
Url=${PAGES_URL}
|
||
RuntimeRepo=https://flathub.org/repo/flathub.flatpakrepo
|
||
GPGKey=${GPG_KEY_B64}
|
||
IsRuntime=false
|
||
EOF
|
||
|
||
- name: Upload flatpakref
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: flatpakref
|
||
path: dist/de.x08.KST4Contest.nightly.flatpakref
|
||
|
||
- name: Upload Flatpak OSTree repo
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: flatpak-ostree-repo
|
||
path: target/flatpak-repo/
|
||
|
||
publish-flatpak-repo:
|
||
name: Publish Flatpak OSTree Repo (nightly)
|
||
runs-on: ubuntu-latest
|
||
needs: build-flatpak
|
||
concurrency:
|
||
group: flatpak-repo-publish
|
||
cancel-in-progress: false
|
||
|
||
steps:
|
||
- name: Install Flatpak tooling
|
||
run: |
|
||
sudo apt-get update -qq
|
||
sudo apt-get install -y --no-install-recommends flatpak
|
||
|
||
- name: Import Flatpak signing key
|
||
run: |
|
||
echo "${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}" | gpg --batch --import
|
||
echo "FLATPAK_GPG_KEY_ID=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr/{print $10; exit}')" >> "$GITHUB_ENV"
|
||
|
||
- name: Download OSTree repo artifact
|
||
uses: actions/download-artifact@v8.0.2
|
||
with:
|
||
name: flatpak-ostree-repo
|
||
path: flatpak-ostree-repo/
|
||
|
||
- name: Checkout existing flatpak-repo branch
|
||
uses: actions/checkout@v7
|
||
with:
|
||
ref: flatpak-repo
|
||
path: existing-flatpak-repo
|
||
|
||
- name: Merge nightly build into flatpak-repo
|
||
run: |
|
||
cd existing-flatpak-repo
|
||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||
git config user.name "github-actions[bot]"
|
||
# Copy the new OSTree build into the repo
|
||
rsync -a ../flatpak-ostree-repo/ ./
|
||
# Regenerate summary with all branches
|
||
flatpak build-update-repo --gpg-sign="$FLATPAK_GPG_KEY_ID" .
|
||
# Generate .flatpakrepo with embedded GPG key so users can do remote-add without errors
|
||
REPO_NAME="${GITHUB_REPOSITORY#*/}"
|
||
PAGES_URL="https://${GITHUB_REPOSITORY_OWNER,,}.github.io/${REPO_NAME}/"
|
||
GPG_KEY_B64=$(gpg --export "$FLATPAK_GPG_KEY_ID" | base64 -w 0)
|
||
cat > kst4contest.flatpakrepo << EOF
|
||
[Flatpak Repo]
|
||
Title=KST4Contest
|
||
Url=${PAGES_URL}
|
||
Homepage=https://github.com/${GITHUB_REPOSITORY}
|
||
Comment=KST4Contest – ON4KST Chat Client for VHF/UHF contests
|
||
GPGKey=${GPG_KEY_B64}
|
||
EOF
|
||
# Stage all changes (new/updated refs, summary, objects in OSTree)
|
||
git add -A
|
||
if git diff --cached --quiet; then
|
||
echo "No changes to commit"
|
||
else
|
||
git commit -m "Nightly flatpak: $(echo ${{ github.sha }} | cut -c1-7)"
|
||
git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:flatpak-repo
|
||
fi
|
||
|
||
build-macos-dmg:
|
||
name: Build macOS DMG (${{ matrix.os }})
|
||
runs-on: ${{ matrix.os }}
|
||
needs: test
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
os: [macos-latest, macos-15-intel]
|
||
|
||
steps:
|
||
- name: Checkout
|
||
uses: actions/checkout@v7
|
||
|
||
- name: Resolve nightly version info
|
||
run: |
|
||
VERSION=$(grep -m1 '^version=' gradle.properties | cut -d= -f2)
|
||
SHORT_SHA="${GITHUB_SHA::7}"
|
||
ARCH=$(uname -m)
|
||
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
|
||
echo "SHORT_SHA=$SHORT_SHA" >> "$GITHUB_ENV"
|
||
echo "ASSET_BASENAME=KST4Contest-${VERSION}-${SHORT_SHA}" >> "$GITHUB_ENV"
|
||
echo "ARCH=$ARCH" >> "$GITHUB_ENV"
|
||
|
||
- name: Set up Java 21
|
||
uses: actions/setup-java@v6.1.0
|
||
with:
|
||
distribution: temurin
|
||
java-version: "21"
|
||
|
||
- name: Ensure gradlew is executable
|
||
run: chmod +x gradlew
|
||
|
||
- name: Import signing certificate
|
||
env:
|
||
MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }}
|
||
MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
|
||
run: ./packaging/macos/ci-import-cert.sh
|
||
|
||
# Builds the jar, signs the app bundle and every native library inside it,
|
||
# wraps it into a DMG and has Apple notarize the result. Same script the
|
||
# local Mac uses, so the two cannot drift apart.
|
||
- name: Build signed and notarized DMG
|
||
env:
|
||
MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }}
|
||
NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }}
|
||
NOTARY_ISSUER: ${{ secrets.MACOS_NOTARY_ISSUER }}
|
||
run: |
|
||
printf '%s' "$MACOS_NOTARY_KEY" | base64 --decode > "$RUNNER_TEMP/notary.p8"
|
||
export NOTARY_KEY="$RUNNER_TEMP/notary.p8"
|
||
./packaging/macos/build-signed-dmg.sh
|
||
|
||
- name: Remove signing credentials
|
||
if: always()
|
||
run: |
|
||
rm -f "$RUNNER_TEMP/notary.p8"
|
||
if [ -n "${SIGNING_KEYCHAIN:-}" ]; then
|
||
security delete-keychain "$SIGNING_KEYCHAIN" || true
|
||
fi
|
||
|
||
- name: Rename DMG artifact
|
||
run: |
|
||
DMG=$(ls dist/*.dmg | head -n 1)
|
||
if [ -z "$DMG" ]; then
|
||
echo "No DMG produced by the build" && exit 1
|
||
fi
|
||
mv "$DMG" "dist/${ASSET_BASENAME}-macos-${ARCH}.dmg"
|
||
|
||
- name: Upload macOS artifact
|
||
uses: actions/upload-artifact@v7
|
||
with:
|
||
name: macos-dmg-${{ matrix.os }}
|
||
path: dist/KST4Contest-*-macos-*.dmg
|
||
retention-days: 14 |