Skip to content

CI: compile the Kotlin plugin and run the unit tests - #143

Merged
oristanovic merged 3 commits into
MOBILE-3815from
ci-compile-kotlin-and-run-tests
Aug 21, 2026
Merged

CI: compile the Kotlin plugin and run the unit tests#143
oristanovic merged 3 commits into
MOBILE-3815from
ci-compile-kotlin-and-run-tests

Conversation

@oristanovic

@oristanovic oristanovic commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Two coverage gaps found while chasing a compile failure on #142. Base is MOBILE-3815 so the in-flight release work picks these checks up immediately.

What CI missed

Area Before After
C# (AirshipSDK.dll) Compiled Compiled
Unit test assembly Compiled, never run Run (EditMode)
Kotlin (unity-plugin) Not compiled at all Compiled
Swift (Assets/Plugins/iOS) Not compiled Still not compiled — see below

The Kotlin gap is the bigger of the two. No AAR is checked in, and the existing Unity player build never invokes the unity-plugin gradle module, so every Kotlin change to date reached review without a compiler ever looking at it. #142 changes the Android event pump, trackScreen's nullability and the live-update payload shape — none of that is currently verified by anything.

The tests have existed and been compiled for a while, they just could not fail a PR.

The two jobs

android-library./gradlew :unity-plugin:assembleRelease, run inside the game-ci editor image.

I first wrote this as a plain ubuntu job on the premise that an Android library needs no Unity. That was wrong, and the first CI run said so: unity-plugin compiles against compileOnly files('libs/unity-classes.jar'), the jar is gitignored, and copyUnityClassesJar sources it from $UNITY_CLASSES_JAR or else a macOS Unity Hub path — the same shape as getUnityExePath() in the root build.gradle. On a bare Linux runner the Copy task finds nothing, no-ops silently, and Kotlin compilation fails on a missing classpath entry.

The job now runs in the editor image purely to obtain that jar, located with find rather than a hardcoded Variations/<backend>/Release/Classes path since that layout has moved between editor versions. No Unity process is launched, so it still consumes no license seat — unlike ci and tests. The image tag is pinned and checked against ProjectVersion.txt, same as release.yaml.

testsgame-ci/unity-test-runner@v4, testMode: EditMode because Tests.asmdef is Editor-only. unityVersion defaults to auto, which reads ProjectSettings/ProjectVersion.txt, so there is no editor version pinned here to drift.

Why tests has needs: ci

A Unity serial has a fixed seat count, and each Unity job holds one for its whole duration. The ci matrix already holds two concurrently — which is the most this repo has ever demonstrated working. Running tests in parallel would need a third simultaneous seat, and the failure mode is ugly: activation fails with an error that reads as a broken workflow rather than a capacity limit.

Sequencing keeps peak concurrency at two. The cost is wall-clock — tests waits for both player legs.

Note this does add one more activate/return cycle per PR run. Peak concurrency is unchanged, but it is one more round trip to Unity's licensing service, and one more place a hard-killed runner can leak a seat.

Swift is deliberately out of scope

Assets/Plugins/iOS/*.swift is still compiled by nothing, and the changes in #142 touch it. Two options, neither a config tweak:

  • Full path — macOS runner, Unity installed via unity-hub on every run (no prebuilt macOS image), Xcode project generated, then xcodebuild. Roughly 30–45 minutes against ~5 for the Linux legs, plus SPM resolution, the post-build script and another license seat. Slow and fragile.
  • SwiftPM type-check harness — a Package.swift depending on AirshipFrameworkProxy that includes the plugin's Swift sources with a stub for AirshipUnityCBridge. No Unity, no seat, a few minutes, and it gives real type checking. Needs the stub written and maintained, and it would not catch problems in the generated Xcode project or the post-build script.

A swiftc -parse syntax check is not worth adding: it would miss type errors, which is exactly where the risk in #142 sits, so a green result would be false confidence.

I'd suggest the harness as a follow-up ticket rather than blocking on it here.

Suggested order

Merge this before #142, so #142's next run compile-checks its Kotlin and runs its tests.

First-run risks

Neither job has run yet — no way to exercise a pull_request workflow without a PR.

  • android-library may need compileSdk 36 downloaded inside the container. The image accepts SDK licences and makes the SDK dir writable, so AGP should handle it, but it's the most likely remaining wrinkle.
  • unity-test-runner passes coverageOptions by default; if the code-coverage package isn't present Unity should ignore the arguments, but that's the second thing to look at.

🤖 Generated with Claude Code

Two gaps found while chasing a compile failure on #142: CI builds Unity players but has
never compiled the Android plugin module, and it compiles the test assembly without
ever running the tests.

android-library compiles unity-plugin with plain gradle. The module is an ordinary
Android library, so this needs no Unity and no license seat, and it closes the larger
gap of the two -- no AAR is checked in and the existing Unity build never invokes this
module, so every Kotlin change so far has reached review unverified.

tests runs the EditMode suite through game-ci/unity-test-runner. The tests have existed
and been compiled for a while but could not fail a PR. unityVersion defaults to auto,
reading ProjectSettings/ProjectVersion.txt, so there is no editor version pinned here.

tests is sequenced after ci rather than run alongside it. Every Unity job holds a serial
license seat for its duration and the ci matrix already holds two, so running it in
parallel would require a third simultaneous seat. This keeps peak concurrency at the two
that CI already demonstrates, at the cost of wall-clock.

Not covered by this change: the Swift under Assets/Plugins/iOS is still compiled by
nothing. That needs macOS plus either a full Unity install or a SwiftPM type-check
harness, and belongs in its own change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oristanovic
oristanovic requested a review from a team as a code owner August 21, 2026 12:08
Ognjen Ristanovic and others added 2 commits August 21, 2026 14:12
First run of android-library failed: JetifyTransform could not find
unity-plugin/libs/unity-classes.jar. The module compiles against it
(compileOnly files('libs/unity-classes.jar')), the jar is gitignored, and
copyUnityClassesJar sources it from $UNITY_CLASSES_JAR or else a macOS Unity Hub path --
the same shape as getUnityExePath() in the root build.gradle. On a bare Linux runner the
Copy task finds nothing, no-ops silently, and Kotlin compilation then fails on a missing
classpath entry.

So my "this needs no Unity" premise was wrong: the jar only exists inside a Unity
install. Run the job in the game-ci editor image to get it. No Unity process is launched,
so this still consumes no license seat, unlike the ci and tests jobs.

The jar is located with find rather than hardcoded, because the
Variations/<backend>/Release/Classes layout has moved between editor versions. The image
tag is pinned and, as in release.yaml, checked against ProjectVersion.txt so it cannot
drift silently.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…owing

First run of the new tests job: 46 tests, 45 passed, 1 failed.

    Unhandled log message: '[Error] Airship: unable to parse push message: JSON
    parse error: Invalid value.'. Use UnityEngine.TestTools.LogAssert.Expect

The test feeds deliberately malformed JSON, FromJson logs the parse failure before
returning null as designed, and Unity's test runner fails any test that emits an
unexpected error log. A test-authoring bug, not a defect in PushMessage -- and one that
was invisible while nothing ran the suite.

Matched with a regex rather than the full string: the tail of the message is
JsonUtility's own wording and can change between editor versions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oristanovic
oristanovic merged commit 7678829 into MOBILE-3815 Aug 21, 2026
5 checks passed
@oristanovic
oristanovic deleted the ci-compile-kotlin-and-run-tests branch August 21, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants