Skip to content

Commit 0c926ac

Browse files
test(oss-licenses): add standalone testapp for plugin verification (#388)
* feat(testapp): Add oss-licenses test app and CI integration * Cleanup
1 parent a707e11 commit 0c926ac

21 files changed

Lines changed: 1102 additions & 18 deletions

File tree

.github/workflows/main.yml

Lines changed: 92 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ name: CI
66
on:
77
# Triggers the workflow on push or pull request events but only for the main branch
88
push:
9-
branches: [ main ]
9+
branches: [main]
1010
pull_request:
11-
branches: [ main ]
1211

1312
# Allows you to run this workflow manually from the Actions tab
1413
workflow_dispatch:
@@ -19,46 +18,121 @@ jobs:
1918
lint-and-check:
2019
runs-on: ubuntu-latest
2120
steps:
22-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6.0.2
2322
- name: Validate Gradle Wrapper
24-
uses: gradle/actions/wrapper-validation@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2
23+
uses: gradle/actions/wrapper-validation@0723195856401067f7a2779048b490ace7a47d7c # ratchet:gradle/actions/wrapper-validation@v5.0.2
2524
- name: Lint GitHub Actions
26-
uses: abcxyz/actions/.github/actions/lint-github-actions@e32ec3bd6af6d87d79fe7c441f435eb7ad11d527 # main
25+
uses: abcxyz/actions/.github/actions/lint-github-actions@e32ec3bd6af6d87d79fe7c441f435eb7ad11d527 # ratchet:abcxyz/actions/.github/actions/lint-github-actions@main
2726
- name: Ratchet Check
28-
uses: sethvargo/ratchet@8b4ca256dbed184350608a3023620f267f0a5253 # main
27+
uses: sethvargo/ratchet@8b4ca256dbed184350608a3023620f267f0a5253 # ratchet:sethvargo/ratchet@main
2928
with:
3029
files: .github/workflows/*.yml
3130

32-
# This workflow contains a single job called "build"
31+
# Build the simple plugins (no special test infrastructure needed)
3332
build:
3433
needs: lint-and-check
35-
# The type of runner that the job will run on
3634
runs-on: ubuntu-latest
37-
38-
# Runs this job in parallel for each sub-project
3935
strategy:
4036
matrix:
4137
project-dir:
4238
- strict-version-matcher-plugin
4339
- google-services-plugin
44-
- oss-licenses-plugin
45-
46-
# Steps represent a sequence of tasks that will be executed as part of the job
4740
steps:
48-
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
49-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
41+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6.0.2
42+
5043
- name: Set up JDK 17
51-
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
44+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # ratchet:actions/setup-java@v5.2.0
5245
with:
5346
java-version: '17'
5447
distribution: 'temurin'
5548

5649
- name: Setup Gradle
57-
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5.0.2
50+
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # ratchet:gradle/actions/setup-gradle@v5.0.2
5851
with:
5952
dependency-graph: generate-and-submit
6053

61-
# Runs a build which includes `check` and `test` tasks
6254
- name: Perform a Gradle build
6355
run: ./gradlew build
6456
working-directory: ./${{ matrix.project-dir }}
57+
58+
# Build and test the oss-licenses plugin, then publish for downstream jobs.
59+
oss-licenses-build:
60+
needs: lint-and-check
61+
runs-on: ubuntu-latest
62+
steps:
63+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6.0.2
64+
65+
- name: Set up JDK 17
66+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # ratchet:actions/setup-java@v5.2.0
67+
with:
68+
java-version: '17'
69+
distribution: 'temurin'
70+
71+
- name: Set up JDK 21
72+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # ratchet:actions/setup-java@v5.2.0
73+
with:
74+
java-version: '21'
75+
distribution: 'temurin'
76+
77+
- name: Setup Gradle
78+
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # ratchet:gradle/actions/setup-gradle@v5.0.2
79+
with:
80+
dependency-graph: generate-and-submit
81+
82+
- name: Build and test
83+
run: ./gradlew build
84+
working-directory: ./oss-licenses-plugin
85+
86+
- name: Publish to local repo
87+
run: ./gradlew publish
88+
working-directory: ./oss-licenses-plugin
89+
90+
- name: Upload local repo artifact
91+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # ratchet:actions/upload-artifact@v4.6.2
92+
with:
93+
name: oss-licenses-local-repo
94+
path: oss-licenses-plugin/build/repo/
95+
96+
# Build the testapp and verify configuration cache store → clean → reuse.
97+
# CC strictness flags are in testapp/gradle.properties (always on).
98+
oss-licenses-testapp:
99+
needs: oss-licenses-build
100+
runs-on: ubuntu-latest
101+
env:
102+
ANDROID_USER_HOME: /home/runner/.android
103+
steps:
104+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # ratchet:actions/checkout@v6.0.2
105+
106+
- name: Download local repo artifact
107+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # ratchet:actions/download-artifact@v4.3.0
108+
with:
109+
name: oss-licenses-local-repo
110+
path: oss-licenses-plugin/build/repo/
111+
112+
- name: Set up JDK 21
113+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # ratchet:actions/setup-java@v5.2.0
114+
with:
115+
java-version: '21'
116+
distribution: 'temurin'
117+
118+
- name: Setup Gradle
119+
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # ratchet:gradle/actions/setup-gradle@v5.0.2
120+
121+
- name: Pre-create Android SDK cache directory
122+
run: mkdir -p "$ANDROID_USER_HOME/cache"
123+
124+
- name: Build testapp (store configuration cache)
125+
run: ./gradlew build -PusePublishedPluginFrom=../build/repo
126+
working-directory: oss-licenses-plugin/testapp
127+
128+
- name: Clean testapp outputs
129+
run: ./gradlew clean -PusePublishedPluginFrom=../build/repo
130+
working-directory: oss-licenses-plugin/testapp
131+
132+
- name: Rebuild testapp (verify configuration cache reuse)
133+
working-directory: oss-licenses-plugin/testapp
134+
run: |
135+
OUTPUT=$(./gradlew build -PusePublishedPluginFrom=../build/repo 2>&1)
136+
echo "$OUTPUT"
137+
echo "$OUTPUT" | grep -q "Configuration cache entry reused" || \
138+
{ echo "::error::Configuration cache was NOT reused"; exit 1; }

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.idea/
22
repo/
33
.kotlin/
4+
.DS_Store
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#This file is generated by updateDaemonJvm
2+
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect
3+
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect
4+
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect
5+
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect
6+
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/46949723aaa20c7b64d7ecfed7207034/redirect
7+
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d6690dfd71c4c91e08577437b5b2beb0/redirect
8+
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/4945f00643ec68e7c7a6b66f90124f89/redirect
9+
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/93aeea858331bd6bb00ba94759830234/redirect
10+
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/3cd7045fca9a72cd9bc7d14a385e594c/redirect
11+
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/552c7bffe0370c66410a51c55985b511/redirect
12+
toolchainVersion=21
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
plugins {
2+
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
3+
}
4+
15
rootProject.name = 'oss-licenses-plugin'
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import com.android.build.api.variant.HostTestBuilder
18+
import org.gradle.api.tasks.testing.Test
19+
import org.gradle.jvm.toolchain.JavaToolchainService
20+
21+
plugins {
22+
alias(libs.plugins.android.application)
23+
alias(libs.plugins.kotlin.android)
24+
alias(libs.plugins.kotlin.compose)
25+
alias(libs.plugins.oss.licenses)
26+
}
27+
28+
android {
29+
namespace = "com.google.android.gms.oss.licenses.testapp"
30+
compileSdk = libs.versions.compileSdk.get().toInt()
31+
testBuildType = "release"
32+
33+
defaultConfig {
34+
applicationId = "com.google.android.gms.oss.licenses.testapp"
35+
minSdk = libs.versions.minSdk.get().toInt()
36+
targetSdk = libs.versions.targetSdk.get().toInt()
37+
versionCode = 1
38+
versionName = "1.0"
39+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
40+
}
41+
42+
buildTypes {
43+
debug { isMinifyEnabled = false }
44+
release {
45+
signingConfig = signingConfigs.getByName("debug")
46+
isMinifyEnabled = true
47+
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"))
48+
}
49+
}
50+
compileOptions {
51+
sourceCompatibility = JavaVersion.VERSION_21
52+
targetCompatibility = JavaVersion.VERSION_21
53+
}
54+
testOptions { unitTests { isIncludeAndroidResources = true } }
55+
lint {
56+
abortOnError = true
57+
checkDependencies = true
58+
ignoreWarnings = false
59+
}
60+
}
61+
62+
tasks.withType<Test>().configureEach {
63+
val javaToolchains = project.extensions.getByType<JavaToolchainService>()
64+
javaLauncher.set(javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(21)) })
65+
66+
// Enable parallel execution for faster Robolectric runs
67+
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1)
68+
69+
testLogging {
70+
events("passed", "skipped", "failed", "standardOut", "standardError")
71+
showStandardStreams = true
72+
}
73+
}
74+
75+
androidComponents {
76+
beforeVariants { variantBuilder ->
77+
// AGP 9.0 only enables unit tests for the "tested build type" by default.
78+
// We explicitly enable them for all variants to ensure both Debug and Release coverage.
79+
variantBuilder.hostTests[HostTestBuilder.UNIT_TEST_TYPE]?.enable = true
80+
}
81+
}
82+
83+
kotlin {
84+
jvmToolchain(21)
85+
compilerOptions { jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21) }
86+
}
87+
88+
dependencies {
89+
implementation(libs.play.services.oss.licenses)
90+
implementation(libs.androidx.appcompat)
91+
implementation(libs.androidx.activity)
92+
implementation("androidx.activity:activity-compose:${libs.versions.androidx.activity.get()}")
93+
implementation(platform(libs.androidx.compose.bom))
94+
implementation("androidx.compose.material3:material3")
95+
96+
97+
testImplementation(libs.junit)
98+
testImplementation(libs.androidx.test.ext.junit)
99+
testImplementation(libs.androidx.test.espresso.core)
100+
testImplementation(libs.androidx.test.espresso.contrib)
101+
testImplementation(libs.androidx.test.core)
102+
testImplementation(libs.robolectric)
103+
104+
// Compose Test (required for testing the V2 activity)
105+
testImplementation(platform(libs.androidx.compose.bom))
106+
testImplementation(libs.androidx.compose.ui.test.junit4)
107+
debugImplementation(libs.androidx.compose.ui.test.manifest)
108+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
<application
4+
android:allowBackup="true"
5+
android:label="OSS Licenses Test App"
6+
android:supportsRtl="true"
7+
android:theme="@style/Theme.AppCompat.Light">
8+
<activity
9+
android:name=".MainActivity"
10+
android:exported="true">
11+
<intent-filter>
12+
<action android:name="android.intent.action.MAIN" />
13+
<category android:name="android.intent.category.LAUNCHER" />
14+
</intent-filter>
15+
</activity>
16+
</application>
17+
</manifest>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.android.gms.oss.licenses.testapp
18+
19+
import android.content.Intent
20+
import android.os.Bundle
21+
import androidx.activity.ComponentActivity
22+
import androidx.activity.compose.setContent
23+
import androidx.compose.foundation.layout.Arrangement
24+
import androidx.compose.foundation.layout.Column
25+
import androidx.compose.foundation.layout.Spacer
26+
import androidx.compose.foundation.layout.fillMaxSize
27+
import androidx.compose.foundation.layout.height
28+
import androidx.compose.material3.Button
29+
import androidx.compose.material3.MaterialTheme
30+
import androidx.compose.material3.Text
31+
import androidx.compose.ui.Alignment
32+
import androidx.compose.ui.Modifier
33+
import androidx.compose.ui.unit.dp
34+
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity as V1Activity
35+
import com.google.android.gms.oss.licenses.v2.OssLicensesMenuActivity as V2Activity
36+
37+
class MainActivity : ComponentActivity() {
38+
override fun onCreate(savedInstanceState: Bundle?) {
39+
super.onCreate(savedInstanceState)
40+
setContent {
41+
MaterialTheme {
42+
Column(
43+
modifier = Modifier.fillMaxSize(),
44+
verticalArrangement = Arrangement.Center,
45+
horizontalAlignment = Alignment.CenterHorizontally,
46+
) {
47+
Button(onClick = { startActivity(Intent(this@MainActivity, V1Activity::class.java)) }) {
48+
Text("Launch V1 Licenses")
49+
}
50+
Spacer(modifier = Modifier.height(16.dp))
51+
Button(onClick = { startActivity(Intent(this@MainActivity, V2Activity::class.java)) }) {
52+
Text("Launch V2 Licenses")
53+
}
54+
}
55+
}
56+
}
57+
}
58+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Global Robolectric Configuration
2+
# Note: SDK 36 (Baklava) requires Java 21+ — Robolectric will fail to run it on older JVMs.
3+
sdk=24, 33, 34, 35, 36

0 commit comments

Comments
 (0)