Skip to content

Commit c3d4c5a

Browse files
jamesarichclaude
andauthored
ci: add HTTP build cache + merge_group trigger (#12)
* ci: add remote HTTP Gradle build cache Add a shared HTTP build cache (gradle/build-cache.settings.gradle), applied from settings.gradle.kts and configured from the GRADLE_CACHE_URL / GRADLE_CACHE_USERNAME / GRADLE_CACHE_PASSWORD env vars (CI secrets). Push is enabled only when credentials are present, so fork PRs (no secrets) are pull-only and cannot poison the cache. ci.yml now passes those secrets. Part of the Meshtastic KMP library standard alignment (shared build cache, matching meshtastic-sdk). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: add merge_group trigger to enable the merge queue Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: harden shared build cache (TLS-only, trusted-event pushes) Addresses CodeRabbit review of the shared build-cache script: - Drop allowInsecureProtocol/allowUntrustedServer — the cache server presents a valid public TLS cert, so enforce HTTPS + certificate validation. - Write to the cache only on trusted events (push/merge_group/local) with credentials present, so pull_request runs stay pull-only and cannot poison the cache. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 05a7098 commit c3d4c5a

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ on:
55
branches: [main]
66
pull_request:
77
branches: [main]
8+
merge_group:
9+
10+
env:
11+
GRADLE_CACHE_URL: ${{ secrets.GRADLE_CACHE_URL }}
12+
GRADLE_CACHE_USERNAME: ${{ secrets.GRADLE_CACHE_USERNAME }}
13+
GRADLE_CACHE_PASSWORD: ${{ secrets.GRADLE_CACHE_PASSWORD }}
814

915
jobs:
1016
test:

gradle/build-cache.settings.gradle

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Shared remote HTTP Gradle build cache for Meshtastic KMP libraries.
3+
*
4+
* Credentials come from the GRADLE_CACHE_URL / GRADLE_CACHE_USERNAME /
5+
* GRADLE_CACHE_PASSWORD environment variables (CI secrets), or a
6+
* local.properties / config.properties entry for local use. Writes to the
7+
* cache happen only from trusted events (local dev, push, merge_group) with
8+
* credentials present, so pull-request runs (and credential-less fork PRs)
9+
* stay pull-only and cannot poison the cache.
10+
*/
11+
12+
def getMeshProperty(String key) {
13+
def env = System.getenv(key)
14+
if (env) return env
15+
def currentDir = settingsDir
16+
while (currentDir != null) {
17+
for (name in ["local.properties", "config.properties"]) {
18+
def f = new File(currentDir, name)
19+
if (f.exists()) {
20+
def props = new Properties()
21+
f.withInputStream { props.load(it) }
22+
if (props.containsKey(key)) return props.getProperty(key)
23+
}
24+
}
25+
currentDir = currentDir.parentFile
26+
}
27+
return null
28+
}
29+
30+
buildCache {
31+
local {
32+
enabled = true
33+
}
34+
remote(HttpBuildCache) {
35+
// Some cache servers return 403 on "Expect: 100-continue".
36+
useExpectContinue = false
37+
def cacheUrl = getMeshProperty("GRADLE_CACHE_URL")?.trim()
38+
def cacheUsername = getMeshProperty("GRADLE_CACHE_USERNAME")?.trim()
39+
def cachePassword = getMeshProperty("GRADLE_CACHE_PASSWORD")?.trim()
40+
if (cacheUrl) {
41+
// HTTPS + valid TLS enforced (no allowInsecureProtocol / no
42+
// allowUntrustedServer): the cache server must present a trusted
43+
// certificate over TLS.
44+
url = cacheUrl.endsWith("/") ? cacheUrl : "${cacheUrl}/"
45+
if (cacheUsername && cachePassword) {
46+
credentials {
47+
username = cacheUsername
48+
password = cachePassword
49+
}
50+
}
51+
// Write only from trusted events (local dev, push to a protected
52+
// branch, or the merge queue) with credentials — never from
53+
// pull_request runs, so unmerged code can't poison the cache.
54+
def eventName = System.getenv("GITHUB_EVENT_NAME")
55+
def trustedForPush = eventName == null || eventName == "push" || eventName == "merge_group"
56+
push = (cacheUsername && cachePassword && trustedForPush)
57+
enabled = true
58+
} else {
59+
enabled = false
60+
}
61+
}
62+
}

settings.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ plugins {
1515
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
1616
}
1717

18+
apply(from = "gradle/build-cache.settings.gradle")
19+
1820
rootProject.name = "gradle-flatpak-sources"
1921
include(":plugin")

0 commit comments

Comments
 (0)