Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,28 @@ jobs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0

- name: Read the Robolectric version
id: robolectric
run: echo "version=$(grep -oP 'org\.robolectric:robolectric:\K[0-9.]+' app/build.gradle.kts)" >> "$GITHUB_OUTPUT"

- name: Restore the Robolectric Android SDK jars
id: robolectric-cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.m2/repository/org/robolectric
key: robolectric-sdks-${{ runner.os }}-${{ steps.robolectric.outputs.version }}

- name: Run unit tests with coverage
run: ./gradlew --no-daemon testGplayDebugUnit

# Saved even when the suite fails, so a red run still leaves the jars behind.
- name: Save the Robolectric Android SDK jars
if: ${{ always() && steps.robolectric-cache.outputs.cache-hit != 'true' }}
Comment on lines +53 to +55

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

sed -n '1,115p' .github/workflows/unit-tests.yml
rg -n 'robolectric|mavenCentral|mavenLocal|dependencyResolutionManagement|repositories' app/build.gradle.kts settings.gradle.kts build.gradle.kts gradle.properties

Repository: nextcloud/talk-android

Length of output: 2967


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- PR diff ---'
git diff --no-ext-diff --unified=30 cd6970664f6e79404bf41b4610fc5a60e04a556a 740caa8bf8d86ead37f22330732136c738069152 -- .github/workflows/unit-tests.yml app/build.gradle.kts
printf '%s\n' '--- Robolectric and SDK references ---'
rg -n -i --glob '!**/build/**' --glob '!**/.gradle/**' 'robolectric|androidsdk|sdk[-_ ]?level|mavenCentral|repositories' . | head -250
printf '%s\n' '--- Gradle files ---'
rg --files -g '*.gradle' -g '*.gradle.kts' -g 'gradle.properties' | sort

Repository: nextcloud/talk-android

Length of output: 32084


🌐 Web query:

official actions/cache restore save exact key cache-hit existing cache behavior

💡 Result:

For **`actions/cache/restore` + `actions/cache/save`**, the key point is that **restore doesn’t save anything; save doesn’t overwrite an existing cache**.

- **Restore:** An exact match for `key` restores that cache and sets `cache-hit` to `true`. A match via `restore-keys` is only a partial match, so `cache-hit` is `false`; a miss also means no exact hit. ([github.com](https://github.com/actions/cache?utm_source=openai))
- **Save:** If a cache already exists for the same key, version, and scope, it cannot be replaced. To save changed contents, use a new key. If the key is new, save can create a cache, assuming the run has write access. ([github.com](https://github.com/actions/cache?utm_source=openai))
- **Typical pattern:** Reuse the restore action’s primary key in the save step. If you want to save only after an exact miss, condition the save step on `cache-hit != 'true'`; otherwise an existing cache may make the save redundant or unsuccessful. ([github.com](https://github.com/osy/actions-cache/blob/main/restore/README.md?utm_source=openai))

```yaml
- uses: actions/cache/restore@v6
  id: cache
  with:
    path: build
    key: build-${{ hashFiles('**/lockfile') }}

# Build/update files in build...

- uses: actions/cache/save@v6
  if: steps.cache.outputs.cache-hit != 'true'
  with:
    path: build
    key: ${{ steps.cache.outputs.cache-primary-key }}
```

An exact hit is scoped not just by key, but also by cache version and branch/scope, so the same text key alone doesn’t guarantee a usable match. ([github.com](https://github.com/actions/cache?utm_source=openai))

Citations:

- 1: https://github.com/actions/cache?utm_source=openai
- 2: https://github.com/actions/cache?utm_source=openai
- 3: https://github.com/osy/actions-cache/blob/main/restore/README.md?utm_source=openai
- 4: https://github.com/actions/cache?utm_source=openai

🏁 Script executed:

printf '%s\n' '--- repository build and Robolectric configuration ---'
sed -n '1,80p' build.gradle
sed -n '1,90p' settings.gradle
cat app/src/test/resources/robolectric.properties 2>/dev/null || true
printf '%s\n' '--- representative Robolectric test declarations ---'
sed -n '1,90p' app/src/test/java/com/nextcloud/talk/utils/DisplayCutoutPaddingTest.kt
sed -n '1,95p' app/src/test/java/com/nextcloud/talk/utils/ssl/TrustManagerTest.kt

Repository: nextcloud/talk-android

Length of output: 9059


🌐 Web query:

Robolectric 4.16.1 MavenDependencyResolver Android SDK download local repository partial download

💡 Result:

For **Robolectric 4.16.1**, the SDK JARs are **Maven artifacts**, not Android Studio SDK-platform downloads. `DefaultSdkProvider` asks its `DependencyResolver` for the required `android-all-instrumented` artifact by Maven coordinate. ([github.com](https://github.com/robolectric/robolectric/blob/master/robolectric/src/main/java/org/robolectric/plugins/DefaultSdkProvider.java?utm_source=openai))

If you’re seeing a **partial or failed download**, the relevant cache is typically Robolectric’s own temporary cache—not just Maven’s or Gradle’s dependency cache. Robolectric’s runner source shows it wrapping `MavenDependencyResolver` in a cached resolver under `${java.io.tmpdir}/robolectric`; in offline mode it instead uses `robolectric.dependency.dir`. ([chromium.googlesource.com](https://chromium.googlesource.com/external/robolectric/%2B/shadow_context_wrapper/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java?utm_source=openai))

Try removing the incomplete artifact/cache and rerunning the test with network access. On Unix-like systems, for example:

```sh
rm -rf "${TMPDIR:-/tmp}/robolectric"
```

If using offline mode, ensure the required SDK JAR is fully present in the configured dependency directory. **Caveat:** the cache-path source found here is not pinned to the 4.16.1 tag, so confirm the exact path against your runtime/configuration before deleting anything. Robolectric 4.16.1 was released on January 21, 2026. ([github.com](https://github.com/robolectric/robolectric/releases?after=robolectric-4.4-beta-1&utm_source=openai))

If you share the exact error and the partially downloaded filename/path, I can narrow down whether it’s Robolectric’s cache, Gradle’s cache, or a repository/proxy issue.

Citations:

- 1: https://github.com/robolectric/robolectric/blob/master/robolectric/src/main/java/org/robolectric/plugins/DefaultSdkProvider.java?utm_source=openai
- 2: https://chromium.googlesource.com/external/robolectric/%2B/shadow_context_wrapper/robolectric/src/main/java/org/robolectric/RobolectricTestRunner.java?utm_source=openai
- 3: https://github.com/robolectric/robolectric/releases?after=robolectric-4.4-beta-1&utm_source=openai

🏁 Script executed:

printf '%s\n' '--- repository build and Robolectric configuration ---'
sed -n '1,80p' build.gradle
sed -n '1,90p' settings.gradle
if test -f app/src/test/resources/robolectric.properties; then cat app/src/test/resources/robolectric.properties; fi
printf '%s\n' '--- representative Robolectric test declarations ---'
sed -n '1,90p' app/src/test/java/com/nextcloud/talk/utils/DisplayCutoutPaddingTest.kt

Repository: nextcloud/talk-android

Length of output: 5157


🌐 Web query:

site:github.com/robolectric/robolectric tag robolectric-4.16.1 DefaultSdkProvider MavenDependencyResolver CachingResolver

💡 Result:

At tag **`robolectric-4.16.1`**:

- `DefaultSdkProvider` hard-codes the supported SDK entries and uses its injected `DependencyResolver` to obtain each SDK jar. It builds an `android-all-instrumented` dependency by default (or `android-all` when preinstrumented jars are disabled). ([github.com](https://github.com/robolectric/robolectric/blob/robolectric-4.16.1/robolectric/src/main/java/org/robolectric/plugins/DefaultSdkProvider.java))
- `MavenDependencyResolver` fetches dependencies into a local Maven repository and uses a file lock while fetching. The resolver implementation shown does **not** contain `CachingResolver`. ([github.com](https://github.com/robolectric/robolectric/blob/robolectric-4.16.1/plugins/maven-dependency-resolver/src/main/java/org/robolectric/internal/dependency/MavenDependencyResolver.java))
- So, for this tag, the source supports describing the Maven resolver’s local-repository/fetch behavior, but not attributing a `CachingResolver` class or wrapper to it. That class’s presence elsewhere in the repository remains unverified here.

Citations:

- 1: https://github.com/robolectric/robolectric/blob/robolectric-4.16.1/robolectric/src/main/java/org/robolectric/plugins/DefaultSdkProvider.java
- 2: https://github.com/robolectric/robolectric/blob/robolectric-4.16.1/plugins/maven-dependency-resolver/src/main/java/org/robolectric/internal/dependency/MavenDependencyResolver.java

Do not save an incomplete SDK cache after a download failure.

Robolectric 4.16.1 resolves each requested android-all-instrumented SDK jar through MavenDependencyResolver into the local Maven repository. If initialization fetches some SDK levels before a TLS failure, the save step can publish that partial directory.

A later exact-key hit sets cache-hit to true, so this workflow skips the save step. Robolectric can still download missing jars during that run, but those jars cannot refresh the existing cache. This creates repeated network downloads, not a permanently nonfunctional test suite.

Keep saving after failed tests when the required SDK jars are complete, or use a cache key that can be renewed after the directory is augmented.

uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.m2/repository/org/robolectric
key: robolectric-sdks-${{ runner.os }}-${{ steps.robolectric.outputs.version }}

- name: Upload test artifacts
if: ${{ failure() }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
Expand Down
Loading