Files
sharedinbox/ISSUE-555.md

3.7 KiB

Background

PR #554 fixed the Firebase Test Lab build by chaining ./gradlew --stop after flutter build apk so the daemon releases its journal-cache lock before Dagger snapshots the layer. This issue asks whether that daemon is useful in the first place — and if not, suppress it instead of cleaning up after it.

Answer to the question

The daemon provides zero benefit in this CI path, and there is no "existing daemon" for it to reuse.

  • Each Dagger WithExec runs in its own ephemeral container. When flutter build apk returns, the container is torn down and the daemon process is killed. The only thing that survives is on-disk state on the gradle-cache volume mount (/home/ci/.gradle), including the journal-cache lock file naming the now-dead PID.
  • The next exec (./gradlew --no-daemon app:assembleAndroidTest) runs in a fresh container with PID 1 = gradlew. There is no live daemon process to connect to, and --no-daemon would refuse to anyway — but it still has to acquire the journal-cache lock and times out because the stale lock file is still there.
  • So the daemon's one job (persist between invocations to amortize JVM startup) cannot happen here: invocation boundaries are container boundaries. The daemon only exists long enough to perform a single build, then is killed — i.e., it behaves like --no-daemon but with extra cleanup hazards.

Proposed change

Prevent the daemon from spawning in CI instead of stopping it afterward. This makes flutter build apk behave the same way ./gradlew --no-daemon app:assembleAndroidTest already does, removes the bash -c "... && ./gradlew --stop" wrapper, and eliminates the class of stale-lock failures rather than the one observed instance.

ci/main.go

  1. In firebaseBase() (and androidBase() for consistency — same cache mount, same risk surface), add an env var that disables the Gradle daemon for every invocation in those containers:

    WithEnvVariable("GRADLE_OPTS", "-Dorg.gradle.daemon=false")
    

    Scoped to CI containers only, so local ./gradlew still gets a daemon.

  2. In BuildAndroidDebugApks(), revert the first WithExec to its pre-#554 form:

    WithExec([]string{"flutter", "build", "apk", "--debug", "--no-pub"}).
    

    Drop the bash -c "... && ./gradlew --stop" wrapper and the comment block explaining the lock-file workaround.

  3. In the second WithExec, drop the --no-daemon flag since GRADLE_OPTS now covers it. Update the adjacent comment (currently explaining stale-daemon-registry reuse) to point at the env-var approach instead, or remove it.

Why GRADLE_OPTS=-Dorg.gradle.daemon=false and not gradle.properties

android/gradle.properties is checked into the repo and read on every developer machine. Setting org.gradle.daemon=false there would slow down local Android builds (every flutter run would pay full JVM startup). The env var keeps the change inside the CI module.

Verification

  • dagger call test-android-firebase ... (or whatever invocation #554 was validated against): build APK + androidTest APK succeed end-to-end with no --stop step and no journal-lock timeout.
  • Confirm the Gradle log from flutter build apk shows Daemon will be stopped at the end of the build / no "Starting a Gradle Daemon" line, or at minimum that no daemon process is left running before container teardown.
  • assembleAndroidTest continues to succeed on a warm gradle-cache (dependencies still cached on the volume; only the daemon state is disabled).

Out of scope

  • Touching gradle.properties (developer-facing, daemon still wanted locally).
  • Changing the gradle-cache mount to non-persistent — defeats the dependency-caching benefit, which is the actual reason the mount exists.