Files
sanderling/bug.md
T
pj 6b1c17328c fix(sample-app): make it standalone, no repo_root assumptions (#8)
* fix(cli): fall back to node_modules for @uatu/spec resolution

Drop the hard failure when the uatu source tree is not reachable from
the spec file. Users integrating uatu in their own app have @uatu/spec
installed via npm; esbuild now resolves it from node_modules.

* build(gradle): drop :sample-app include from root settings

The sample now has its own Gradle project in examples/sample-app/android.

* build(sample-app): vendor gradle wrapper

Users running the sample build the APK via ./gradlew from inside the
sample-app's own android/ directory, no repo-root wrapper required.

* build(sample-app): make gradle project standalone

Drop the project(':sdk-android') dependency in favor of the Maven
Central coordinate io.github.priyanshujain:sdk-android. The sample now
owns its settings.gradle.kts and gradle.properties, so it builds
without any pieces of the uatu source tree.

* chore(sample-app): declare @uatu/spec npm dependency

Mirrors what a downstream user would put in their own package.json.
Uses file: for pre-release development; becomes a normal semver pin
once @uatu/spec ships to npm.

* docs(sample-app): rewrite justfile and add README

Justfile drops repo_root; all recipes run against the local gradle
wrapper and uatu from PATH. README is scoped to what a user needs to
run the sample against their own device.

* docs(manual): update sample install steps to standalone layout

./gradlew :sample-app:installDebug no longer exists; the sample owns
its own wrapper under android/.

* feat(sdk): log when Uatu.start succeeds

Silent SDK start makes the "SDK didn't connect" failure mode
impossible to debug. One INFO line at start time is enough.

* fix(sidecar): launch via am start -W instead of monkey

monkey -p <pkg> -c LAUNCHER 1 is unreliable on API 36+: it reports no
error but silently fails to start the activity, so the SDK never runs
and the CLI times out on the SDK-accept handshake.

Resolve the launcher activity via `cmd package resolve-activity
--brief` and launch it with `am start -W -n`. -W makes the call block
until the activity is up, which also makes the subsequent SDK
accept timing deterministic.

* feat(cli): auto-resolve Android device; boot AVD if none connected

--avd becomes optional. Resolution order:
 - use any already-connected adb device;
 - else if --avd names an existing AVD, boot it and wait for boot;
 - else if --avd is missing or names no AVD, error with a clear message.

Falls back to $ANDROID_HOME/emulator/emulator when the binary is not on
PATH, so a standard Android SDK install works without extra shell setup.

* docs(sample-app): AVD is optional; document both paths

just test runs against any connected device. If none, pass AVD=<name>
to have uatu boot the emulator for you.

* feat(cli): auto-discover Android SDK; auto-pick the lone AVD

adb and emulator are looked up via PATH, then $ANDROID_HOME,
$ANDROID_SDK_ROOT, ~/Library/Android/sdk, ~/Android/Sdk, and the
Homebrew cask path. The discovered platform-tools directory is
prepended to the sidecar's PATH so its adb subprocess calls work too.

When --avd isn't passed and no device is connected, the CLI picks the
sole local AVD and boots it. Multiple AVDs → error listing them.

* build(make): add `make install` that go-installs uatu onto PATH

Puts `uatu` into $GOBIN (or $GOPATH/bin) so the sample and any local
dev flow can call it without PATH= prefixes.

* docs(sample-app): zero-config just test; dotenv-load for persistence

Drop the expectation that users prefix commands with PATH=, ANDROID_HOME=,
or AVD=. `just test` now works as-is; optional knobs can be pinned in a
.env file alongside the justfile.

* fix(sample-app): auto-detect ANDROID_HOME for Gradle tasks

The Go CLI finds the SDK itself, but AGP still needs ANDROID_HOME to
resolve `sdk.dir`. The justfile now resolves it from env or canonical
install paths before invoking ./gradlew, so `just install` works out
of the box on a standard Android SDK setup.

* gitignore runs directory for sample app
2026-04-18 15:31:47 +07:00

3.5 KiB

Dokka / Java 25 publish failure

What fails

Running ./gradlew :sdk-android:publishToMavenLocal (or any task that triggers javaDocReleaseGeneration) on a JDK 25 host crashes with:

Execution failed for task ':sdk-android:javaDocReleaseGeneration'.
> A failure occurred while executing com.android.build.gradle.tasks.JavaDocGenerationTask$DokkaWorkAction
...
Caused by: java.lang.IllegalArgumentException: 25.0.2
    at com.intellij.util.lang.JavaVersion.parse(JavaVersion.java:298)

Why it happens

The publish flow is:

  1. com.vanniktech.maven.publish:0.30.0 (declared in sdk/android/build.gradle.kts:7) configures an AndroidSingleVariantLibrary with publishJavadocJar = true.
  2. That wires AGP's JavaDocGenerationTask into the release publication. The task runs Dokka in a WorkAction.
  3. Dokka ships a vendored copy of IntelliJ's platform SDK. When it boots, it probes the JDK version by calling com.intellij.util.lang.JavaVersion.parse(System.getProperty("java.version")).
  4. On the host JDK the property is literally the string "25.0.2". Dokka's bundled JavaVersion.parse (an older IntelliJ build) only understands the legacy patterns (1.8.0_x, 9, 11.0.x, etc.) and refuses version 25's format, throwing IllegalArgumentException: 25.0.2.
  5. The worker dies, Gradle marks javaDocReleaseGeneration failed, and the whole publish lifecycle aborts before any POM or AAR is written.

Why it's latent in CI

CI runs on JDK 17 per build.gradle.kts compile targets and whatever actions/setup-java installs. "17.0.x" matches the old format, so the bundled JavaVersion.parse doesn't blow up. The bug only surfaces on developer machines running JDK 21+ where the version string format changed, and reliably on JDK 25.

Workaround

./gradlew :sdk-android:publishToMavenLocal -x javaDocReleaseGeneration

The AAR, sources jar, and POM publish cleanly; only the Javadoc jar is skipped. That produces a usable 0.0.0-dev artifact for local testing but is not a substitute for a real release publish, since Maven Central validation requires the Javadoc jar.

Possible fixes

  1. Bump the vanniktech.maven.publish plugin to a version that ships a newer Dokka. The 0.30.0 version pinned here is from mid-2024. Newer releases (0.33+) bundle Dokka 2.x, which has rewritten the JDK detection path and handles modern version strings. One line in sdk/android/build.gradle.kts, no build config change. Requires verifying the plugin's breaking changes for the publish config.

  2. Pin a compatible Dokka directly. Add id("org.jetbrains.dokka") version "1.9.20" (or later) so the plugin picks up Dokka's own fix for IntelliJ JavaVersion.parse. Slightly more invasive; you now manage Dokka independently from the publish plugin.

  3. Force a JDK toolchain for the javadoc task. Add a java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } block scoped to the SDK module (or use tasks.withType<JavaDocGenerationTask> { javaLauncher.set(...) }). Gradle downloads JDK 17 and runs Dokka under it regardless of the host JDK. Robust but adds a toolchain dependency to every dev machine's first build.

  4. Don't generate a Javadoc jar. Flip publishJavadocJar = false in the vanniktech config. Kills the problem by removing the failing path. Not viable for Maven Central release (they require a Javadoc jar).

Recommendation

Option 1. Smallest diff, addresses the root cause, keeps the publish pipeline intact for Central releases, and newer plugin versions also bring AGP 8.x compatibility improvements.