Skip to content

Commit 655ee2a

Browse files
Rajan MauryaRajan Maurya
authored andcommitted
fix(build): unblock gradle build — wrapper 9.5.0 + catalog sync + libs/mifos-passcode removal + sync-dirs heal
After commit ac2fbe2 (T0.1 quarantine) + da586a7 (16 alias catch-up), the Test Coverage Floor workflow on PR #2691 still failed at gradle script compilation. Local reproduction with openjdk@17 surfaced a chain of compounding issues; this commit fixes them so `./gradlew help` now succeeds. `--no-verify` used per user direction — detekt has many pre-existing violations across the codebase (long parameter lists, parameter order) unrelated to this commit's changes. Detekt cleanup is a separate wave. Major changes: 1. Gradle wrapper 8.13 → 9.5.0 (gradle/wrapper/*) — kmp-product-flavors:2.4.2 ships Kotlin 2.2 metadata; Gradle 8.13's kotlin-dsl uses Kotlin 2.0.21 which max-reads metadata 2.1. Matches template's wrapper version. 2. Root build.gradle.kts — added: - buildscript classpath R8 9.1.31 pin (understands Kotlin 2.3.20 metadata) - Root kover + kover.convention plugin registration so KoverConventionPlugin can apply at per-module level - subprojects resolutionStrategy forcing JetBrains androidx.lifecycle 2.9.6 + savedstate 1.3.6 (resolves KLIB resolver duplicate-warnings) - failOnNoDiscoveredTests = false per-test-task (Gradle 9 KMP compat) - roborazzi alias 3. gradle/libs.versions.toml — catalog catch-up: - Added missing version refs: appPackage - Added missing library alias: compottie (bare, alongside -lite/-resources; core-base/ui/build.gradle.kts uses `libs.compottie` directly which Gradle 9 rejected when only sub-aliases existed) - Stripped `version = "unspecified"` from 15 convention-plugin aliases (Gradle 9 rejects with "Error resolving plugin … plugin is already on the classpath with an unknown version") - Removed androidx-hilt-navigation-compose + androidxHiltNavigationCompose (field-officer is Koin-only per user direction; the only reference was in libs/mifos-passcode which is deleted in this commit) 4. Deleted libs/mifos-passcode/ entirely (109 files) — vendored legacy Hilt-based library excluded from build since 2024 (settings.gradle.kts had `//include(":libs:mifos-passcode")` commented). Functionality replaced by feature/passcode (Koin-based, scheduled W2 in active/feature-vertical-migration/PLAN.md). Removed commented include from settings.gradle.kts. 5. core/network/build.gradle.kts — removed `add("kspIosX64", libs.ktorfit.ksp)` (TS-2 dropped iosX64 target; this reference triggered "Configuration with name 'kspIosX64' not found" at config time). 6. sync-dirs self-heal (mirrors openMF/kmp-project-template PR #163): - .github/workflows/sync-dirs.yaml: new "Heal libs.versions.toml" step between sync + temp-branch cleanup. Detects build-logic `libs.<X>` refs unresolved in consumer catalog, pulls them (and their referenced version keys) from upstream via `git show $TEMP_BRANCH:gradle/libs.versions.toml`. - sync-dirs.sh: matching heal_libs_versions_toml() function for local CLI. Eliminates the failure mode that required this commit's manual catch-up. 7. File renames for ktlint compliance: - core/ui/.../ViewModelTypes.kt → BaseViewModel.kt (single typealias) - feature/document/.../DocumentRoute.kt → DocumentListRoute.kt - feature/path-tracking/.../PathTrackingRoute.kt → PathTrackingScreenRoute.kt - feature/search/.../SearchRoute.kt → SearchScreenRoute.kt 8. core/data/.../legacy/di/RepositoryModule.legacy.kt — added @file:Suppress "ktlint:standard:no-empty-file" + a private object marker. The file is intentionally a /* */ block-commented reference (legacy/ is gradle-excluded) but spotless still scans it. Verification (with openjdk@17): ✅ ./gradlew help — BUILD SUCCESSFUL ✅ ./gradlew -p build-logic help — BUILD SUCCESSFUL ✅ ./gradlew spotlessApply — BUILD SUCCESSFUL ⚠️ ./gradlew :cmp-android:assembleDemoDebug — 531/535 tasks succeed; real Kotlin compile errors remain in core/model (B6.10 leftover unresolved imports). Tracked for next commit. ⚠️ ./gradlew detekt — Many pre-existing violations. Separate cleanup wave. Run locally: export JAVA_HOME=/opt/homebrew/opt/openjdk@17 export PATH=$JAVA_HOME/bin:$PATH ./gradlew help # ← passes ./gradlew :cmp-android:assembleDemoDebug # ← reaches kotlin compile The build is unblocked at the gradle-script + catalog level. PR #2691 will now proceed further than commit da586a7 did in the Test Coverage Floor CI.
1 parent da586a7 commit 655ee2a

252 files changed

Lines changed: 717 additions & 2006 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/sync-dirs.yaml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,126 @@ jobs:
249249
250250
echo "Sync completed successfully!"
251251
252+
- name: Heal libs.versions.toml — pull missing build-logic aliases from upstream
253+
shell: bash
254+
run: |
255+
set -uo pipefail
256+
# Self-healing step (matches openMF/kmp-project-template PR #163).
257+
# `build-logic/` (+ feature build.gradle.kts files) are sync'd from upstream,
258+
# but `gradle/libs.versions.toml` is intentionally consumer-local (it carries
259+
# project-specific package names + version overrides). When upstream adds
260+
# new `libs.<X>` accessors with their matching catalog entries, only the
261+
# build files get sync'd — the consumer catalog falls behind. This step
262+
# detects that gap and pulls the missing alias entries (and their referenced
263+
# version keys) directly from the upstream catalog.
264+
265+
LIBS_TOML="gradle/libs.versions.toml"
266+
TEMP_BRANCH="${{ env.TEMP_BRANCH }}"
267+
268+
if [[ ! -f "$LIBS_TOML" ]]; then
269+
echo "ℹ️ Consumer has no $LIBS_TOML — nothing to heal."
270+
exit 0
271+
fi
272+
273+
# Extract every libs.<ref> usage in build files (both build.gradle.kts and
274+
# build-logic Kotlin source).
275+
raw_refs=$(grep -rhoE '\blibs\.[a-zA-Z][a-zA-Z0-9._]*' \
276+
--include='*.kt' --include='*.kts' \
277+
. 2>/dev/null \
278+
| sed -E 's/^libs\.//' \
279+
| sort -u)
280+
281+
# Method-call accessors are not alias references — they take string args.
282+
method_re='^(findLibrary|findVersion|findBundle|findPlugin)([(.]|$)'
283+
284+
# Cache upstream's catalog content once.
285+
upstream_toml=$(git show "${TEMP_BRANCH}:${LIBS_TOML}" 2>/dev/null || true)
286+
if [[ -z "$upstream_toml" ]]; then
287+
echo "⚠️ Upstream has no ${LIBS_TOML} — skipping heal."
288+
exit 0
289+
fi
290+
291+
insert_into_section() {
292+
local section_name="$1"
293+
local line="$2"
294+
local line_no
295+
line_no=$(grep -n "^\[${section_name}\]" "$LIBS_TOML" | head -1 | cut -d: -f1)
296+
if [[ -z "$line_no" ]]; then
297+
echo " ⚠️ No [$section_name] section header in $LIBS_TOML — skipping '$line'"
298+
return 1
299+
fi
300+
{ head -n "$line_no" "$LIBS_TOML"; echo "$line"; tail -n +$((line_no + 1)) "$LIBS_TOML"; } > "${LIBS_TOML}.tmp"
301+
mv "${LIBS_TOML}.tmp" "$LIBS_TOML"
302+
}
303+
304+
healed=0
305+
warnings=0
306+
while IFS= read -r ref; do
307+
[[ -z "$ref" ]] && continue
308+
[[ "$ref" =~ $method_re ]] && continue
309+
# Skip `versions.X.get` — `libs.versions.X.get()` is a method call;
310+
# the actual key is X.
311+
if [[ "$ref" =~ ^versions\..*\.get$ ]]; then
312+
ref="${ref%.get}"
313+
fi
314+
315+
section="libraries"
316+
lookup="$ref"
317+
case "$ref" in
318+
plugins.*)
319+
section="plugins"
320+
lookup="${ref#plugins.}"
321+
;;
322+
versions.*)
323+
section="versions"
324+
lookup="${ref#versions.}"
325+
[[ "$lookup" == "toml" ]] && continue
326+
;;
327+
bundles.*)
328+
section="bundles"
329+
lookup="${ref#bundles.}"
330+
;;
331+
esac
332+
key=$(echo "$lookup" | sed 's/\./-/g')
333+
334+
if grep -qE "^${key}[[:space:]]*=" "$LIBS_TOML"; then
335+
continue
336+
fi
337+
338+
upstream_line=$(echo "$upstream_toml" | grep -E "^${key}[[:space:]]*=" | head -1)
339+
if [[ -z "$upstream_line" ]]; then
340+
echo " ⚠️ Missing alias '$key' (for libs.$ref) not present in upstream catalog either — manual fix needed."
341+
warnings=$((warnings + 1))
342+
continue
343+
fi
344+
345+
ref_version=$(echo "$upstream_line" | grep -oE 'version\.ref = "[^"]+"' | sed -E 's/version\.ref = "([^"]+)"/\1/' | head -1)
346+
if [[ -n "$ref_version" ]] && ! grep -qE "^${ref_version}[[:space:]]*=" "$LIBS_TOML"; then
347+
ver_line=$(echo "$upstream_toml" | grep -E "^${ref_version}[[:space:]]*=" | head -1)
348+
if [[ -n "$ver_line" ]]; then
349+
if insert_into_section "versions" "$ver_line"; then
350+
echo " ✅ Added version '$ref_version' (referenced by '$key') to [versions]"
351+
healed=$((healed + 1))
352+
fi
353+
fi
354+
fi
355+
356+
if insert_into_section "$section" "$upstream_line"; then
357+
echo " ✅ Added '$key' to [$section] from upstream"
358+
healed=$((healed + 1))
359+
fi
360+
done <<< "$raw_refs"
361+
362+
echo
363+
if [[ $healed -gt 0 ]]; then
364+
echo "🩹 Healed $healed entries in $LIBS_TOML — they will be included in the sync PR."
365+
elif [[ $warnings -gt 0 ]]; then
366+
echo "⚠️ $warnings missing aliases could not be auto-healed (not in upstream either). Manual fix needed."
367+
exit 1
368+
else
369+
echo "✅ libs.versions.toml already in sync with build-logic — no heal needed."
370+
fi
371+
252372
- name: Clean up temporary branch
253373
if: always()
254374
run: git branch -D "${{ env.TEMP_BRANCH }}" 2>/dev/null || true

build.gradle.kts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
import org.gradle.kotlin.dsl.libs
22

33
// Top-level build file where you can add configuration options common to all sub-projects/modules.
4+
buildscript {
5+
repositories {
6+
google {
7+
content {
8+
includeGroupByRegex("com\\.android.*")
9+
includeGroupByRegex("com\\.google.*")
10+
includeGroupByRegex("androidx.*")
11+
}
12+
}
13+
mavenCentral()
14+
gradlePluginPortal()
15+
}
16+
dependencies {
17+
// Pin R8 to a version that understands Kotlin 2.3 metadata. The R8 bundled
18+
// with AGP 8.12.3 reads up to Kotlin metadata 2.1 only, so every release-mode
19+
// build with Kotlin 2.3.20 emits "R8: An error occurred when parsing kotlin
20+
// metadata" warnings for almost every class. Override it with R8 9.1.x stable.
21+
classpath("com.android.tools:r8:9.1.31")
22+
}
23+
}
24+
425
plugins {
526
alias(libs.plugins.kotlinCocoapods) apply false
627
alias(libs.plugins.android.application) apply false
@@ -28,6 +49,14 @@ plugins {
2849
alias(libs.plugins.kotlinMultiplatform) apply false
2950
alias(libs.plugins.wire) apply false
3051
alias(libs.plugins.ktorfit) apply false
52+
53+
// Kover — root-level registration so the plugin is on the classpath for
54+
// KoverConventionPlugin (build-logic) to apply per-module. Per-module kover
55+
// application happens via `org.convention.kover.plugin` chained from base
56+
// convention plugins (AndroidApplication / KMPLibrary / KMPCoreBaseLibrary).
57+
// cmp-desktop applies it directly. Tasks: koverHtmlReport / koverXmlReport.
58+
alias(libs.plugins.kover) apply false
59+
alias(libs.plugins.kover.convention)
3160
}
3261

3362
object DynamicVersion {
@@ -47,8 +76,33 @@ tasks.register("versionFile") {
4776
// Used by module graph generator script
4877
tasks.register("printModulePaths") {
4978
subprojects {
50-
if (subprojects.size == 0) {
79+
if (subprojects.isEmpty()) {
5180
println(this.path)
5281
}
5382
}
83+
}
84+
85+
// Force consistent versions across all subprojects to fix KLIB resolver duplicate warnings.
86+
// The conflict is between org.jetbrains.androidx.* (CMP) and androidx.* (Google) transitive deps.
87+
subprojects {
88+
configurations.all {
89+
resolutionStrategy.eachDependency {
90+
if (requested.group == "org.jetbrains.androidx.lifecycle") {
91+
useVersion("2.9.6")
92+
}
93+
if (requested.group == "org.jetbrains.androidx.savedstate") {
94+
useVersion("1.3.6")
95+
}
96+
}
97+
}
98+
99+
// Gradle 9+ defaults Test.failOnNoDiscoveredTests to true. AGP unit-test
100+
// tasks (testDemoDebugUnitTest, testProdReleaseUnitTest, etc.) then fail
101+
// on KMP `androidUnitTest` source sets that contain expect/actual TEST
102+
// HELPERS but no @Test classes — those test classes legitimately live in
103+
// `commonTest` or `desktopTest`. Disabling per-task unblocks the kover
104+
// coverage gate without weakening real-test signal.
105+
tasks.withType<org.gradle.api.tasks.testing.Test>().configureEach {
106+
failOnNoDiscoveredTests = false
107+
}
54108
}

cmp-android/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
import com.android.build.api.instrumentation.InstrumentationScope
1111
import org.convention.AppBuildType

cmp-android/lint-baseline.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
If a copy of the MPL was not distributed with this file,
77
You can obtain one at https://mozilla.org/MPL/2.0/.
88
9-
See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
9+
See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
1010
-->
1111
<issues format="6" by="lint 8.5.2" type="baseline" client="gradle" dependencies="true" name="AGP (8.5.2)" variant="all" version="8.5.2">
1212

cmp-android/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
If a copy of the MPL was not distributed with this file,
77
You can obtain one at https://mozilla.org/MPL/2.0/.
88
9-
See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
9+
See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
1010
-->
1111
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
1212
xmlns:tools="http://schemas.android.com/tools">

cmp-android/src/main/kotlin/cmp/android/app/AndroidApp.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
package cmp.android.app
1111

cmp-android/src/main/kotlin/cmp/android/app/AppThemeExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
package cmp.android.app
1111

cmp-android/src/main/kotlin/cmp/android/app/BuildConfigUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
package cmp.android.app
1111

cmp-android/src/main/kotlin/cmp/android/app/ComponentActivityExtensions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
package cmp.android.app
1111

cmp-android/src/main/kotlin/cmp/android/app/ConfigurationExtension.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* License, v. 2.0. If a copy of the MPL was not distributed with this
66
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
77
*
8-
* See See https://github.com/openMF/kmp-project-template/blob/main/LICENSE
8+
* See https://github.com/openMF/mifos-x-field-officer-app/blob/master/LICENSE.md
99
*/
1010
package cmp.android.app
1111

0 commit comments

Comments
 (0)