fix(ci): use available Android SDK platform

Restores Android CI to a publicly installable SDK platform and keeps Gradle compileSdk aligned with the workflow install/cache key. Rolls back the API-37-only AndroidX core slice until Android 37 is available to hosted CI, while preserving the unrelated Kotlin dependency bump.

Verification:
- Google SDK repository index check: android-36 exists; android-37/android-37.0 do not.
- git diff --check
- Testbox changed gate: tbx_01kvs3r1bc925pxya94zey23c8
- PR CI: 68 successful, 12 skipped, 0 failing, 0 pending; Android build/play and both Android unit-test lanes passed.
This commit is contained in:
Vincent Koc
2026-06-23 10:18:28 +08:00
committed by GitHub
parent a84d3b6853
commit 33206ee583
6 changed files with 31 additions and 17 deletions
+2 -2
View File
@@ -2233,7 +2233,7 @@ jobs:
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: ~/.android-sdk
key: ${{ runner.os }}-android-sdk-v1-cmdline-14742923-platform-37.0-build-tools-36.0.0
key: ${{ runner.os }}-android-sdk-v1-cmdline-14742923-platform-36-build-tools-36.0.0
restore-keys: |
${{ runner.os }}-android-sdk-v1-
@@ -2263,7 +2263,7 @@ jobs:
yes | sdkmanager --sdk_root="${ANDROID_SDK_ROOT}" --licenses >/dev/null
sdkmanager --sdk_root="${ANDROID_SDK_ROOT}" --install \
"platform-tools" \
"platforms;android-37.0" \
"platforms;android-36" \
"build-tools;36.0.0"
- name: Run Android ${{ matrix.task }}
+1 -1
View File
@@ -59,7 +59,7 @@ plugins {
android {
namespace = "ai.openclaw.app"
compileSdk = 37
compileSdk = 36
// Release signing is local-only; keep the keystore path and passwords out of the repo.
signingConfigs {
@@ -49,18 +49,8 @@ import java.util.concurrent.Executors
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
private fun createDnsResolver(context: Context): DnsResolver =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN) {
createContextDnsResolver(context)
} else {
createLegacyDnsResolver()
}
@RequiresApi(Build.VERSION_CODES.CINNAMON_BUN)
private fun createContextDnsResolver(context: Context): DnsResolver = DnsResolver(context, null)
@Suppress("DEPRECATION")
private fun createLegacyDnsResolver(): DnsResolver = DnsResolver.getInstance()
private fun createDnsResolver(): DnsResolver = DnsResolver.getInstance()
/**
* Watches local DNS-SD and optional wide-area DNS-SD for reachable OpenClaw gateways.
@@ -71,7 +61,7 @@ class GatewayDiscovery(
) {
private val nsd = context.getSystemService(NsdManager::class.java)
private val connectivity = context.getSystemService(ConnectivityManager::class.java)
private val dns = createDnsResolver(context)
private val dns = createDnsResolver()
private val serviceType = "_openclaw-gw._tcp."
private val wideAreaDomain = System.getenv("OPENCLAW_WIDE_AREA_DOMAIN")
private val logTag = "OpenClaw/GatewayDiscovery"
+1 -1
View File
@@ -5,7 +5,7 @@ plugins {
android {
namespace = "ai.openclaw.app.benchmark"
compileSdk = 37
compileSdk = 36
defaultConfig {
minSdk = 31
+1 -1
View File
@@ -4,7 +4,7 @@ androidx-activity = "1.13.0"
androidx-benchmark = "1.4.1"
androidx-camera = "1.6.0"
androidx-compose-bom = "2026.05.01"
androidx-core = "1.19.0"
androidx-core = "1.18.0"
androidx-exifinterface = "1.4.2"
androidx-lifecycle = "2.10.0"
androidx-security = "1.1.0"
+24
View File
@@ -23,6 +23,14 @@ function readCriticalQualityWorkflow() {
return readFileSync(".github/workflows/codeql-critical-quality.yml", "utf8");
}
function readAndroidCompileSdk(path: string): number {
const match = readFileSync(path, "utf8").match(/^\s*compileSdk\s*=\s*(\d+)\s*$/mu);
if (!match) {
throw new Error(`Missing compileSdk in ${path}`);
}
return Number(match[1]);
}
function findYamlFiles(directory: string): string[] {
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
const path = `${directory}/${entry.name}`;
@@ -134,6 +142,22 @@ describe("ci workflow guards", () => {
expect(workflow.jobs.android.strategy["max-parallel"]).toBe(2);
});
it("installs the Android SDK platform used by Gradle", () => {
const workflow = readCiWorkflow();
const appCompileSdk = readAndroidCompileSdk("apps/android/app/build.gradle.kts");
const benchmarkCompileSdk = readAndroidCompileSdk("apps/android/benchmark/build.gradle.kts");
const cacheStep = workflow.jobs.android.steps.find((step) => step.name === "Cache Android SDK");
const installStep = workflow.jobs.android.steps.find(
(step) => step.name === "Install Android SDK packages",
);
const packageId = `platforms;android-${appCompileSdk}`;
expect(appCompileSdk).toBe(benchmarkCompileSdk);
expect(cacheStep.with.key).toContain(`platform-${appCompileSdk}-`);
expect(installStep.run).toContain(`"${packageId}"`);
expect(installStep.run).not.toContain(`${packageId}.0`);
});
it("debounces canonical main pushes before Blacksmith admission", () => {
const workflow = readCiWorkflow();
const source = readFileSync(".github/workflows/ci.yml", "utf8");