From 2aeebac38b99806afdd567be01acaef679106210 Mon Sep 17 00:00:00 2001 From: Philipp Wagner Date: Sun, 25 Oct 2026 00:15:02 +0200 Subject: [PATCH] ci: fail hanging tests by name instead of holding the job Nightly #302 and the PR check for #147 hung in :app-desktop:test for over an hour, and the log named only the task. Thirteen reruns of the same commit passed, so the hang is rare and still unidentified. Every test now gets a two-minute JUnit timeout in a separate thread, so even an uninterruptible hang fails with the test's name and the stack where it stood. The test jobs are capped at 20 minutes for a hang outside any test. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/nightly-artifacts.yml | 3 +++ .github/workflows/pr-compile-check.yml | 3 +++ .github/workflows/tagged-release.yml | 3 +++ build.gradle.kts | 10 ++++++++++ 4 files changed, 19 insertions(+) diff --git a/.github/workflows/nightly-artifacts.yml b/.github/workflows/nightly-artifacts.yml index b8890e0a..a22b4773 100644 --- a/.github/workflows/nightly-artifacts.yml +++ b/.github/workflows/nightly-artifacts.yml @@ -32,6 +32,9 @@ jobs: test: name: Test (Java 21, headless) runs-on: ubuntu-latest + # A healthy run takes about four minutes. The per-test limit in build.gradle.kts names + # a hanging test; this cap covers a hang outside any test, such as in Gradle itself. + timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/pr-compile-check.yml b/.github/workflows/pr-compile-check.yml index 5b62bdaf..e0e1239b 100644 --- a/.github/workflows/pr-compile-check.yml +++ b/.github/workflows/pr-compile-check.yml @@ -155,6 +155,9 @@ jobs: test: name: Test (Java 21, headless) runs-on: ubuntu-latest + # A healthy run takes about four minutes. The per-test limit in build.gradle.kts names + # a hanging test; this cap covers a hang outside any test, such as in Gradle itself. + timeout-minutes: 20 steps: - name: Checkout diff --git a/.github/workflows/tagged-release.yml b/.github/workflows/tagged-release.yml index 09b73a6a..1818a350 100644 --- a/.github/workflows/tagged-release.yml +++ b/.github/workflows/tagged-release.yml @@ -24,6 +24,9 @@ jobs: test: name: Test (Java 21, headless) runs-on: ubuntu-latest + # A healthy run takes about four minutes. The per-test limit in build.gradle.kts names + # a hanging test; this cap covers a hang outside any test, such as in Gradle itself. + timeout-minutes: 20 steps: - name: Checkout diff --git a/build.gradle.kts b/build.gradle.kts index 636abeb8..bf9eba28 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -141,6 +141,16 @@ subprojects { } testUserHome.mkdirs() } + /* + * A test that never returns must fail by name instead of holding the job until + * GitHub kills it after six hours: Nightly #302 hung in :app-desktop:test for over + * an hour, and the log named only the task. The limit is far above the slowest test + * (under four seconds). SEPARATE_THREAD also ends a test whose thread ignores + * interruption, such as a busy loop or a blocked native call, and the failure's + * cause carries that thread's stack, so it shows where the test stood. + */ + systemProperty("junit.jupiter.execution.timeout.default", "2m") + systemProperty("junit.jupiter.execution.timeout.thread.mode.default", "SEPARATE_THREAD") finalizedBy(checkTestUserHome) }