Files
amethyst/.github/workflows/build.yml
T
Claude d2294247a7 fix(desktop): pin vlcVersion to 3.0.20 so Linux vlcDownload finds an artifact
The Linux build path of the vlc-setup plugin pulls vlc-plugins-linux from
Maven Central (ir.mahozad:vlc-plugins-linux), which only ships 3.0.20 and
3.0.20-2 — there is no 3.0.21 artifact yet. With vlcVersion set to 3.0.21,
both the CI pre-fetch step and the in-Gradle vlcDownload task hit a 404.

Match VLC_VERSION in build.yml and document the lag so future bumps wait
for the Maven artifact to catch up.

https://claude.ai/code/session_01GrZLMi3sdp6frwREmQ9cUi
2026-05-06 23:06:52 +00:00

269 lines
10 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Test/Build
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: 21
# Remote Gradle build cache: writes on push to main, reads on PRs and
# other branches. Caches both `~/.gradle/caches/` and individual task
# outputs, so dependency-only changes hit the cache and skip recompiling
# downstream modules / re-merging native libs (~600MB of work on
# :amethyst alone). Replaces the narrower `cache: gradle` previously on
# actions/setup-java, which only cached `modules-2`.
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
- name: Linter (gradle)
run: ./gradlew spotlessCheck
build-desktop:
needs: lint
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
desktop-task: packageDeb
desktop-artifact-name: Desktop Linux DEB
desktop-artifact-path: desktopApp/build/compose/binaries/main/deb/*.deb
- os: macos-latest
desktop-task: packageDmg
desktop-artifact-name: Desktop macOS DMG
desktop-artifact-path: desktopApp/build/compose/binaries/main/dmg/*.dmg
- os: windows-latest
desktop-task: packageMsi
desktop-artifact-name: Desktop Windows MSI
desktop-artifact-path: desktopApp/build/compose/binaries/main/msi/*.msi
runs-on: ${{ matrix.os }}
timeout-minutes: 60
defaults:
run:
shell: bash
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: 21
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
# Cache vlc-setup plugin downloads (VLC + UPX archives) keyed on the
# versions pinned in desktopApp/build.gradle.kts. Each OS gets its own
# cache namespace because the plugin downloads platform-specific archives.
# On a hit the vlcDownload / upxDownload tasks are up-to-date and we
# never touch get.videolan.org; on a miss (version bump or new runner)
# we fall back to fetching, which is what the in-build retry budget
# exists for.
- name: Cache vlc-setup downloads
uses: actions/cache@v4
with:
path: ~/.gradle/vlcSetup
key: vlcsetup-${{ runner.os }}-${{ hashFiles('desktopApp/build.gradle.kts') }}
restore-keys: |
vlcsetup-${{ runner.os }}-
# Pre-fetch VLC + UPX archives into ~/.gradle/vlcSetup before invoking
# Gradle. The vlc-setup plugin (ir.mahozad.vlc-setup 0.1.0) writes its
# downloads to ${gradleUserHomeDir}/vlcSetup/ and sets overwrite(false),
# so an existing file there makes vlcDownload / upxDownload up-to-date
# and Gradle never opens a socket to videolan.org.
#
# Why curl instead of relying on de.undercouch.gradle.tasks.download:
# curl --retry-all-errors with a long --retry-max-time tolerates a
# sustained get.videolan.org outage far better than the plugin's inner
# retry budget (retries(4) + 5min readTimeout in build.gradle.kts),
# which has been hitting SocketTimeoutException on Windows runners.
#
# Cache hit: the file is already on disk, fetch() short-circuits, this
# step takes <1s. Cache miss: curl downloads with aggressive retries,
# populating the cache for the next run.
#
# Versions are pinned to match desktopApp/build.gradle.kts (vlcVersion
# = 3.0.20) and the vlc-setup extension default (upxVersion = 4.2.4).
# NOTE: vlcVersion lags behind upstream VLC because the Linux plugins on
# Maven Central (ir.mahozad:vlc-plugins-linux) are only published for
# 3.0.20 / 3.0.20-2. Bump only after the Maven artifact is republished.
# macOS does not download UPX — UPX cannot compress .dylib files.
- name: Pre-fetch VLC + UPX archives
env:
VLC_VERSION: "3.0.20"
UPX_VERSION: "4.2.4"
run: |
set -euo pipefail
DEST="$HOME/.gradle/vlcSetup"
mkdir -p "$DEST"
fetch() {
local url="$1" out="$2"
if [[ -s "$out" ]]; then
echo "cached: $out"
return 0
fi
echo "fetching: $url"
curl -fL --retry 10 --retry-delay 5 --retry-all-errors \
--retry-max-time 900 --connect-timeout 30 \
-o "$out.part" "$url"
mv "$out.part" "$out"
}
case "${{ runner.os }}" in
Windows)
fetch "https://get.videolan.org/vlc/${VLC_VERSION}/win64/vlc-${VLC_VERSION}-win64.zip" \
"$DEST/vlc-${VLC_VERSION}.zip"
fetch "https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-win64.zip" \
"$DEST/upx-${UPX_VERSION}.zip"
;;
Linux)
fetch "https://repo1.maven.org/maven2/ir/mahozad/vlc-plugins-linux/${VLC_VERSION}/vlc-plugins-linux-${VLC_VERSION}.jar" \
"$DEST/vlc-${VLC_VERSION}.jar"
fetch "https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-amd64_linux.tar.xz" \
"$DEST/upx-${UPX_VERSION}.tar.xz"
;;
macOS)
fetch "https://get.videolan.org/vlc/${VLC_VERSION}/macosx/vlc-${VLC_VERSION}-universal.dmg" \
"$DEST/vlc-${VLC_VERSION}.dmg"
;;
esac
- name: Test + Build Desktop (gradle)
run: ./gradlew :quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}
# jpackage pins libicu to the build host's version (libicu74 on
# ubuntu-24.04). Rewrite the .deb so testers on other Debian/Ubuntu
# releases can install the uploaded artifact.
- name: Relax libicu dependency in .deb
if: matrix.desktop-task == 'packageDeb'
run: |
set -euo pipefail
chmod +x scripts/relax-deb-libicu.sh
scripts/relax-deb-libicu.sh desktopApp/build/compose/binaries/main/deb/*.deb
- name: Upload Desktop Distribution
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.desktop-artifact-name }}
path: ${{ matrix.desktop-artifact-path }}
test-and-build-android:
needs: lint
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: 'zulu'
java-version: 21
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
with:
cache-read-only: ${{ github.ref != 'refs/heads/main' }}
# Lint + focused unit tests + benchmark assembly in one Gradle invocation.
# Previously: one invocation for lint, one for `test` (which compiled all
# six amethyst variants × all flavors), one for `assembleBenchmark`
# (re-walking the same task graph). Combining them keeps the daemon hot
# across phases and lets task-level dedup (e.g. compileKotlin) only
# happen once.
#
# `-PdisableAbiSplits=true` produces a single non-split APK per
# (flavor, buildType) instead of 5 (4 ABIs + universal). The CI only
# uploads the universal-equivalent benchmark APK; per-ABI splits were
# being built and discarded, costing ~600MB of stripped_native_libs
# intermediates and several minutes per run.
#
# Test scope: only Debug unit tests for amethyst. The release/benchmark
# variants are compile-equivalent for unit-test purposes; running all six
# adds ~5× the kotlinc work without catching new defects on PRs. Push to
# main still gets the full test matrix via the production-build path.
- name: Test + Build Android (gradle)
run: |
./gradlew \
:amethyst:lintFdroidBenchmark \
:amethyst:lintPlayBenchmark \
:quartz:jvmTest \
:commons:jvmTest \
:nestsClient:jvmTest \
:ammolite:testDebugUnitTest \
:amethyst:testFdroidDebugUnitTest \
:amethyst:testPlayDebugUnitTest \
:amethyst:assembleBenchmark \
-PdisableAbiSplits=true
- name: Upload Android Lint Reports
uses: actions/upload-artifact@v7
if: always()
with:
name: Android Lint Reports
path: amethyst/build/reports/lint-results-*.html
- name: Android Test Report
uses: asadmansr/android-test-report-action@v1.2.0
if: always()
- name: Upload Test Results
uses: actions/upload-artifact@v7
if: failure()
with:
name: Test Reports
path: amethyst/build/reports
# With -PdisableAbiSplits=true the APK is named without the ABI/universal
# suffix: amethyst-<flavor>-benchmark.apk. Glob both forms so this still
# works if a contributor runs CI on a branch that doesn't pass the flag.
- name: Upload Play APK Benchmark
uses: actions/upload-artifact@v7
with:
name: Play Benchmark APK
path: |
amethyst/build/outputs/apk/play/benchmark/amethyst-play-benchmark.apk
amethyst/build/outputs/apk/play/benchmark/amethyst-play-universal-benchmark.apk
- name: Upload FDroid APK Benchmark
uses: actions/upload-artifact@v7
with:
name: FDroid Benchmark APK
path: |
amethyst/build/outputs/apk/fdroid/benchmark/amethyst-fdroid-benchmark.apk
amethyst/build/outputs/apk/fdroid/benchmark/amethyst-fdroid-universal-benchmark.apk
- name: Upload Compose Reports
uses: actions/upload-artifact@v7
with:
name: Compose Reports
path: amethyst/build/compose_compiler