Skip to content

Commit 295335f

Browse files
authored
fix(app): pin AboutLibraries license JSON so F-Droid reproduces (#90)
Stop generating res/raw/aboutlibraries.json at build time (registerAndroidTasks=false) and check in a pinned release-only JSON so every builder packages identical bytes. Fixes the F-Droid reproducible-build failure on res/M7.json. Adds a CI drift check.
1 parent ec7d521 commit 295335f

3 files changed

Lines changed: 42 additions & 4 deletions

File tree

.github/workflows/android-ci.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,22 @@ jobs:
160160
echo "::error::Rename guard found un-allowlisted OPDS_SYNC / opds-sync / opds_sync references."
161161
exit 1
162162
fi
163+
- name: AboutLibraries JSON drift check
164+
run: |
165+
set -e
166+
# app/src/main/res/raw/aboutlibraries.json is checked in and packaged
167+
# as-is (registerAndroidTasks=false in app/build.gradle.kts) so F-Droid's
168+
# reproducible-build check passes — the plugin's build-time collector is
169+
# environment-dependent and produced a non-reproducible res/M7.json.
170+
# Fail if the committed file drifts from the current release dep graph.
171+
tmpdir="$(mktemp -d)"
172+
./gradlew :app:exportLibraryDefinitions \
173+
-PaboutLibraries.exportVariant=release \
174+
-PaboutLibraries.exportPath="$tmpdir" --stacktrace
175+
if ! diff -u app/src/main/res/raw/aboutlibraries.json "$tmpdir/aboutlibraries.json"; then
176+
echo "::error::app/src/main/res/raw/aboutlibraries.json is stale. Regenerate: scripts/dgradle :app:exportLibraryDefinitions -PaboutLibraries.exportVariant=release -PaboutLibraries.exportPath=src/main/res/raw"
177+
exit 1
178+
fi
163179
- name: Assemble debug APK
164180
run: ./gradlew assembleDebug --stacktrace
165181
- name: Unit tests

app/build.gradle.kts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,33 @@ plugins {
1010
val appVersionName: String = project.property("VERSION_NAME") as String
1111
val appVersionCode: Int = (project.property("VERSION_CODE") as String).toInt()
1212

13-
// Drop the build timestamp from the AboutLibraries-generated license JSON
14-
// so the resource is byte-identical across rebuilds (matters for F-Droid's
15-
// reproducible-build verification). Disabled by default in AboutLibraries
16-
// 14+; explicit on 11.x.
13+
// AboutLibraries' build-time collector is not reproducible: it scans whatever
14+
// dependency configurations happen to be resolvable in a given build, so the
15+
// generated license JSON (res/raw/aboutlibraries.json, obfuscated to res/M7.json
16+
// by resource shrinking) varies by environment — debug/test artifacts leak in
17+
// locally while F-Droid's isolated builder under-collects. That made F-Droid's
18+
// reproducible-build verification fail on the res/M7.json contents.
19+
//
20+
// Fix: don't generate the resource at build time. We check in a pre-generated,
21+
// release-only JSON and package that fixed file, so every builder (dev, CI,
22+
// F-Droid) embeds byte-identical bytes. `LibrariesContainer` in LicensesScreen
23+
// reads R.raw.aboutlibraries, which resolves to the committed file.
24+
//
25+
// Regenerate after changing dependencies (CI enforces this — see the
26+
// "AboutLibraries JSON drift check" step in android-ci.yaml). exportPath is
27+
// resolved relative to this module, so `src/main/res/raw` lands the file at
28+
// app/src/main/res/raw/aboutlibraries.json:
29+
// scripts/dgradle :app:exportLibraryDefinitions \
30+
// -PaboutLibraries.exportVariant=release \
31+
// -PaboutLibraries.exportPath=src/main/res/raw
32+
//
33+
// `excludeFields=["generated"]` drops the build timestamp (default in
34+
// AboutLibraries 14+; explicit on 11.x); `filterVariants` keeps the
35+
// regenerated file release-only.
1736
aboutLibraries {
1837
excludeFields = arrayOf("generated")
38+
filterVariants = arrayOf("release")
39+
registerAndroidTasks = false
1940
}
2041

2142
android {

app/src/main/res/raw/aboutlibraries.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)