Skip to content

Housekeep (dependencies and other improvements)#132

Open
matejsemancik wants to merge 27 commits intodevelopfrom
feature/bump-dependencies
Open

Housekeep (dependencies and other improvements)#132
matejsemancik wants to merge 27 commits intodevelopfrom
feature/bump-dependencies

Conversation

@matejsemancik
Copy link
Member

@matejsemancik matejsemancik commented Nov 1, 2025

Summary by CodeRabbit

  • Chores

    • Updated many build tool and library versions; increased JVM metaspace and separated Kotlin daemon JVM options.
    • Added Makefile targets for building/cleaning the shared KMP artifact.
  • New Features

    • New themed Showcase container and preview helpers across Android and shared UI; added no-op action factories for previews.
    • Added a KMP static/dynamic switch with config and default tweaks; Xcode config updated per build type.
  • Compatibility

    • Removed iOS x64 target; iOS targets now arm64 and simulator arm64 only.
  • Chores

    • Updated many build tool and library versions; increased JVM metaspace and separated Kotlin daemon JVM options.
    • Added Makefile targets for building/cleaning the shared KMP artifact.
  • New Features

    • New themed Showcase container and preview helpers across Android and shared UI; added no-op action factories for previews.
    • Added a KMP static/dynamic switch with config and default tweaks; Xcode config updated per build type.
  • Compatibility

    • Removed iOS x64 target; iOS targets now arm64 and simulator arm64 only.

@coderabbitai
Copy link

coderabbitai bot commented Nov 1, 2025

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds ProjectSettings.Android.BuildTypes.all and IOS.IsStaticFrameworkProperty. Extends the annotations-processor plugin with properties useKoin, useComponentFactory, and androidBuildTypes and adds manual wiring to derive KSP variant task names from androidBuildTypes with mustRunAfter ordering against kspCommonMainKotlinMetadata. Sets androidBuildTypes = ProjectSettings.Android.BuildTypes.all in many shared modules. Removes iosX64 from multiple KMP targets. Introduces KMP static/dynamic control (KMP_IS_STATIC) across xcconfigs, Makefile, and shared Gradle iOS framework binaries. Adds Compose Showcase component, preview helpers/noOpActions for screens, README updates, gradle.properties and version catalog bumps, and deletes iOS UI tests.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant ProjectBuild as Project build.gradle.kts
participant AnnotationsExt as AnnotationsExtension (plugin)
participant Gradle as Gradle runtime
participant KSPCommon as kspCommonMainKotlinMetadata
participant KSPVariant as kspKotlinMetadata

ProjectBuild->>AnnotationsExt: set androidBuildTypes = ProjectSettings.Android.BuildTypes.all
AnnotationsExt->>Gradle: evaluate androidBuildTypes list
loop for each buildType
AnnotationsExt->>Gradle: compute variant task name (ksp + Uppercase(buildType) + KotlinMetadata)
Gradle->>KSPVariant: locate/create kspKotlinMetadata
AnnotationsExt->>KSPVariant: configure mustRunAfter KSPCommon
end
KSPVariant->>KSPCommon: enforced ordering (mustRunAfter)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'Housekeep (dependencies and other improvements)' is vague and overly broad, using non-descriptive language that doesn't convey meaningful information about the specific changes made. Consider using a more specific title that highlights the primary change, such as 'Update dependencies and configure static/dynamic framework linking for iOS' or 'Bump dependency versions and add KMP static framework configuration'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/bump-dependencies
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the tone of the review comments and chat replies.

Configure the tone_instructions setting to customize the tone of the review comments and chat replies. For example, you can set the tone to Act like a strict teacher, Act like a pirate and more.

@matejsemancik matejsemancik added android Android-related issues kmp KMP-related issues labels Nov 1, 2025
This commit adds support for build variant-aware KSP (Kotlin Symbol Processing) tasks.

Key changes:
- Adds a mechanism to the `conventions-annotations-processor` to correctly wire KSP task dependencies for different Android build types (e.g., debug, release).
- Updates all relevant `build.gradle.kts` files to pass the build types to the convention plugin.
- Bumps the `ksp` version to `2.3.0`.
Comment on lines -22 to +36
arg("KOIN_CONFIG_CHECK", "true")
arg("KOIN_CONFIG_CHECK", "false")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm disabling this for now because Koin annotations somehow refuses to detect dependencies with named qualifier from the same subproject.

@matejsemancik matejsemancik requested a review from Syntey November 2, 2025 16:11
@matejsemancik matejsemancik marked this pull request as ready for review November 2, 2025 16:11
@github-actions
Copy link

github-actions bot commented Nov 2, 2025

2 Warnings
⚠️ Feature or fix PR title should include JIRA-ID and short description.
⚠️ Feature or fix PR branch name should include JIRA-ID and short description.

Generated by 🚫 Danger

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5674555 and ee2d73a.

📒 Files selected for processing (8)
  • buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt (1 hunks)
  • convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts (4 hunks)
  • gradle.properties (1 hunks)
  • gradle/libs.versions.toml (3 hunks)
  • shared/app/build.gradle.kts (1 hunks)
  • shared/feature/build.gradle.kts (1 hunks)
  • shared/network/graphql/build.gradle.kts (1 hunks)
  • shared/persistence/build.gradle.kts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{kt,kts}

📄 CodeRabbit inference engine (CLAUDE.md)

Max line length: 140 characters

Files:

  • shared/feature/build.gradle.kts
  • shared/persistence/build.gradle.kts
  • buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt
  • shared/app/build.gradle.kts
  • shared/network/graphql/build.gradle.kts
  • convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts
**/*.kt

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.kt: Error handling: Use sealed NetworkError classes and model operations as results (Success/Failure)
Max 25 functions per class
Max 20 functions per file

Files:

  • buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt
🧠 Learnings (1)
📚 Learning: 2025-09-03T08:24:27.077Z
Learnt from: CR
Repo: futuredapp/kmp-futured-template PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T08:24:27.077Z
Learning: Applies to **/*.{android.kt,ios.kt} : Platform-specific code: Place implementations in files suffixed with .android.kt and .ios.kt

Applied to files:

  • shared/feature/build.gradle.kts
  • shared/persistence/build.gradle.kts
  • shared/app/build.gradle.kts
  • gradle/libs.versions.toml
  • shared/network/graphql/build.gradle.kts
  • convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts
🔇 Additional comments (9)
gradle.properties (1)

3-3: LGTM: Clean separation of Kotlin daemon JVM options.

The new kotlin.daemon.jvm.options property properly separates Kotlin-specific JVM settings, and the 1g metaspace allocation aligns with the updated Kotlin 2.2.10 toolchain.

shared/app/build.gradle.kts (1)

25-25: LGTM: Consistent build type configuration.

The addition of androidBuildTypes = ProjectSettings.Android.BuildTypes.all properly enables all Android build types (Debug, Enterprise, Release) for Koin annotation processing in this module, aligning with the new centralized build type configuration.

shared/persistence/build.gradle.kts (1)

15-15: LGTM: Consistent build type configuration.

The build type configuration matches the pattern established in other modules, properly enabling all Android build types for annotation processing.

shared/network/graphql/build.gradle.kts (1)

18-18: LGTM: Consistent build type configuration.

The build type configuration properly enables all Android build types for this module's annotation processing, maintaining consistency across the codebase.

shared/feature/build.gradle.kts (1)

17-17: LGTM: Consistent build type configuration.

The build type configuration is properly applied alongside the existing useKoin and useComponentFactory settings, enabling comprehensive annotation processing for all build variants.

buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt (1)

30-30: LGTM: Clean aggregation of build type constants.

The all property provides a convenient single source of truth for iterating over all build types, eliminating duplication across module configurations.

convention-plugins/src/main/kotlin/conventions-annotations-processor.gradle.kts (3)

13-26: LGTM: Well-documented extension properties.

The new configuration properties are clearly documented and provide a clean API for configuring annotation processing behavior across modules.


36-36: LGTM: KOIN_CONFIG_CHECK disabled as intended.

Setting KOIN_CONFIG_CHECK to false aligns with the past review comment indicating that Koin annotations has issues detecting dependencies with named qualifiers. This is a deliberate configuration choice.


76-82: Task naming convention is correct—no issues found.

KSP creates task names like kspDebugKotlinAndroid and kspReleaseKotlinAndroid for Android build variants, which matches the pattern used in the code: "ksp${it.uppercaseFirstChar()}KotlinAndroid". The mustRunAfter constraint will work as intended; the named tasks will be found and the dependency will be properly wired.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee2d73a and 952470d.

📒 Files selected for processing (2)
  • gradle.properties (1 hunks)
  • gradle/libs.versions.toml (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-03T08:24:27.077Z
Learnt from: CR
Repo: futuredapp/kmp-futured-template PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T08:24:27.077Z
Learning: Applies to **/*.{android.kt,ios.kt} : Platform-specific code: Place implementations in files suffixed with .android.kt and .ios.kt

Applied to files:

  • gradle/libs.versions.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: check-android / Lint & Tests
  • GitHub Check: check-ios / Test
🔇 Additional comments (2)
gradle.properties (1)

2-3: Good fix: syntax error corrected and Kotlin daemon options properly separated.

The previous syntax error (trailing quote) has been resolved, and the kotlin.daemon.jvm.options are now correctly isolated from org.gradle.jvmargs, which is a cleaner configuration approach.

gradle/libs.versions.toml (1)

22-23: Verify Ktorfit 2.6.5 compatibility with Ktor 3.3.3.

The previous review identified that Ktorfit 2.6.4's Ktor version is 3.2.1. The patch-level bump to Ktorfit 2.6.5 may not add support for Ktor 3.3.3 (a minor version ahead). Please verify this pairing is supported, either by testing the build or checking Ktorfit 2.6.5 release notes.

ksp = "2.1.20-1.0.32" # Must be compatible with: `kotlin`
agp = "8.13.1"
kotlin = "2.2.20"
ksp = "2.3.0"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

CRITICAL: KSP version does not meet Koin Annotations 2.3.1 requirement.

Koin Annotations 2.3.1 requires KSP 2.3.2, but Line 4 specifies KSP 2.3.0. This version mismatch will cause compilation failures.

Update Line 4 to match the requirement:

- ksp = "2.3.0"
+ ksp = "2.3.2"

Also applies to: 13-13

🤖 Prompt for AI Agents
In gradle/libs.versions.toml around lines 4 and 13, the KSP version is pinned to
2.3.0 which is incompatible with Koin Annotations 2.3.1; update the ksp entries
on those lines to 2.3.2 so they match Koin's requirement (ensure both
occurrences are changed and any related dependency entries remain consistent).

@davidkocnar
Copy link
Member

Koin Annotations 2.3.2-Beta1 and KSP 2.3.2 did not fix the problem.

Syntey
Syntey previously approved these changes Jan 29, 2026
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

2 Warnings
⚠️ Feature or fix PR title should include JIRA-ID and short description.
⚠️ Feature or fix PR branch name should include JIRA-ID and short description.
1 Message
📖 iosAppTests: Executed 1 test, with 0 failures (0 expected) in 0.001 (0.001) seconds

Generated by 🚫 Danger

@matejsemancik matejsemancik changed the title Kotlin 2.2.10 + other deps Housekeep (dependencies and other improvements) Feb 23, 2026
matejsemancik and others added 2 commits February 23, 2026 14:02
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Enable iOS preview + screen preview example
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (6)
shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt (1)

13-15: Nit: add explicit ): Actions return type for consistency.

All other noOpActions() factories in the codebase (FirstScreen, PickerScreen, TEMPLATEScreen) explicitly annotate the return type as : Actions. Inferring it here is valid but inconsistent.

♻️ Proposed fix
-            fun noOpActions() = object : Actions {
+            fun noOpActions(): Actions = object : Actions {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt`
around lines 13 - 15, Add an explicit return type to the noOpActions factory to
match other factories: change the function declaration for noOpActions in
LoginScreen (the function that returns an object : Actions and currently defined
as fun noOpActions() = ... ) to explicitly declare the return type as : Actions
(i.e., fun noOpActions(): Actions = ...), keeping the same body and object
implementation.
androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt (1)

112-119: Redundant Surface inside Showcase — inconsistent with other previews.

Showcase already wraps content in a Surface(color = MaterialTheme.colorScheme.background). Adding another bare Surface {} inside (which defaults to colorScheme.surface) is inconsistent with _TemplateScreenUi.kt and PickerScreenUi.kt, which both use Showcase { Content(...) } directly. The inner Surface also has no effect since Content renders a Scaffold that owns its own background.

♻️ Proposed fix
 private fun FirstScreenPreview() = Showcase {
-    Surface {
-        Content(
-            viewState = FirstScreenPreviews.viewState(),
-            actions = noOpActions(),
-            modifier = Modifier.fillMaxSize(),
-        )
-    }
+    Content(
+        viewState = FirstScreenPreviews.viewState(),
+        actions = noOpActions(),
+        modifier = Modifier.fillMaxSize(),
+    )
 }

Also remove the now-unused import:

-import androidx.compose.material3.Surface
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt`
around lines 112 - 119, Remove the redundant inner Surface from the
FirstScreenPreview function: instead of wrapping Content in Surface(), call
Showcase { Content(...) } directly (update the FirstScreenPreview function that
currently calls Showcase { Surface { Content(viewState =
FirstScreenPreviews.viewState(), actions = noOpActions(), modifier =
Modifier.fillMaxSize()) } } ). Also remove the now-unused Surface import that
becomes dead after this change so imports match other previews like
_TemplateScreenUi.kt and PickerScreenUi.kt.
androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt (1)

12-19: Consider moving Showcase to a debug source set.

Showcase is only ever called from @Preview-annotated private functions, which are stripped from release builds. The composable itself, however, is compiled into the production APK. Moving it to androidApp/src/debug/kotlin/… would keep it out of release builds and signal its preview-only intent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt`
around lines 12 - 19, The Showcase composable (function Showcase, referencing
MyApplicationTheme and Surface) is preview-only but currently compiled into
production; move the Showcase declaration into the debug source set under the
same package so it is only included in debug/preview builds, update any imports
if needed, and ensure any `@Preview` callers remain in debug or reference the new
debug-only Showcase; keep the function signature and behavior unchanged.
androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt (1)

57-62: Redundant Surface inside Showcase

Showcase already provides a Surface with color = MaterialTheme.colorScheme.background (see androidApp/.../ui/components/Showcase.kt lines 13–15). The extra Surface { } here is a no-op wrapper.

♻️ Proposed fix
 `@Preview`
 `@Composable`
 private fun LoginScreenPreview() = Showcase {
-    Surface {
-        Content(
-            actions = noOpActions(),
-            modifier = Modifier.fillMaxSize(),
-        )
-    }
+    Content(
+        actions = noOpActions(),
+        modifier = Modifier.fillMaxSize(),
+    )
 }

Also remove the now-unused import:

-import androidx.compose.material3.Surface
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt`
around lines 57 - 62, Remove the redundant Surface wrapper inside the Showcase
usage: delete the outer Surface { ... } so that Content(...) is passed directly
to Showcase (keeping actions = noOpActions() and modifier =
Modifier.fillMaxSize()); then remove the now-unused Surface import from
LoginScreenUi.kt. Locate the Showcase usage in LoginScreenUi (where Content is
currently wrapped) and update it to call Content directly, and remove any unused
androidx.compose.material3.Surface import.
iosApp/shared/KMP/Makefile (2)

26-33: checkmake maxbodylength warning: build target body is 7 lines (limit: 5).

The four @echo diagnostics cause this. They can be consolidated into a single @printf call or extracted into a define macro to bring the body under the configured limit.

♻️ Example using `printf` to consolidate echoes
 build:
-	`@echo` "------------------------------------------------"
-	`@echo` "Config: $(KMP_FRAMEWORK_BUILD_TYPE) | Flavor: $(KMP_BUILD_FLAVOR)"
-	`@echo` "Static: $(KMP_IS_STATIC)"
-	`@echo` "Executing: ./gradlew $(GRADLE_TASK) $(GRADLE_ARGS)"
-	`@echo` "------------------------------------------------"
+	`@printf` -- "------------------------------------------------\nConfig: %s | Flavor: %s\nStatic: %s\nExecuting: ./gradlew %s %s\n------------------------------------------------\n" \
+	    "$(KMP_FRAMEWORK_BUILD_TYPE)" "$(KMP_BUILD_FLAVOR)" "$(KMP_IS_STATIC)" "$(GRADLE_TASK)" "$(GRADLE_ARGS)"
 	cd ../../.. && \
 	./gradlew $(GRADLE_TASK) --no-daemon $(GRADLE_ARGS)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@iosApp/shared/KMP/Makefile` around lines 26 - 33, The build target in the
Makefile has too many lines due to four separate `@echo` calls; replace them with
a single consolidated output (e.g., one `@printf` that prints the same header,
config, flavor, static flag, and executing line) or extract them into a Makefile
define/variable and call it once, keeping the rest of the target (cd ../../.. &&
./gradlew $(GRADLE_TASK) --no-daemon $(GRADLE_ARGS)) unchanged; update
references to the same variables (KMP_FRAMEWORK_BUILD_TYPE, KMP_BUILD_FLAVOR,
KMP_IS_STATIC, GRADLE_TASK, GRADLE_ARGS) so the printed message remains
identical.

13-14: Consider adding a KMP_BUILD_FLAVOR guard for consistency.

KMP_FRAMEWORK_BUILD_TYPE is validated with $(error ...) (line 7), but KMP_BUILD_FLAVOR is used without any guard. If unset, Gradle receives -Pbuildkonfig.flavor= with an empty value, which likely produces a confusing downstream failure.

♻️ Proposed guard (after the existing BUILD_MODE block)
 endif
+
+# Validate flavor
+ifndef KMP_BUILD_FLAVOR
+    $(error KMP_BUILD_FLAVOR is not set)
+endif
+
 # Task name: assembleAndCopy[Debug|Release]SwiftPackage
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@iosApp/shared/KMP/Makefile` around lines 13 - 14, Add a guard to fail fast
when KMP_BUILD_FLAVOR is not set: check the KMP_BUILD_FLAVOR variable (similar
to the existing KMP_FRAMEWORK_BUILD_TYPE validation) and invoke $(error ...)
with a clear message if it is empty, then safely construct GRADLE_ARGS :=
-Pbuildkonfig.flavor=$(KMP_BUILD_FLAVOR); place this check after the BUILD_MODE
block so the Makefile will not pass an empty -Pbuildkonfig.flavor to Gradle.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.kt`:
- Around line 6-7: Replace usage of collectAsState with lifecycle-aware
collectAsStateWithLifecycle: change the import from
androidx.compose.runtime.collectAsState to
androidx.lifecycle.compose.collectAsStateWithLifecycle and update any calls in
the TemplateScreenUi (e.g., where viewModel.someFlow is collected with
collectAsState) to use collectAsStateWithLifecycle() instead while keeping the
existing by delegation/getValue usage (getValue) unchanged; ensure all
occurrences (including the one flagged and the similar occurrence at line 29)
are updated so the Flow respects Android lifecycle.

In `@gradle.properties`:
- Around line 2-3: The property key on line 3 is wrong: replace
kotlin.daemon.jvm.options with kotlin.daemon.jvmargs so the Kotlin daemon JVM
arguments are set correctly; update the entry to use
kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g and leave org.gradle.jvmargs
unchanged.
- Line 3: Replace the incorrect gradle.properties key kotlin.daemon.jvm.options
with the correct property kotlin.daemon.jvmargs so the Kotlin Gradle Plugin
applies the JVM argument; update the entry to use kotlin.daemon.jvmargs and keep
the value -XX:MaxMetaspaceSize=1g (ensuring any existing org.gradle.jvmargs
usage isn't duplicated) so the Kotlin daemon receives the MaxMetaspaceSize
setting.

In `@shared/app/build.gradle.kts`:
- Around line 46-49: The iOS target list now only includes iosArm64() and
iosSimulatorArm64(), which removes iosX64() and thus drops Intel Mac simulator
support; add a clear note explaining that iOS development requires an Apple
Silicon Mac (and that iosX64 was intentionally omitted) so contributors know the
requirement. Update the documentation (either add a short comment above the list
that contains iosArm64() and iosSimulatorArm64() in build.gradle.kts and/or add
a line in the repo README) stating the Apple Silicon requirement, the rationale,
and any CI note about self-hosted Apple Silicon runners to guide contributors.

---

Nitpick comments:
In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt`:
- Around line 12-19: The Showcase composable (function Showcase, referencing
MyApplicationTheme and Surface) is preview-only but currently compiled into
production; move the Showcase declaration into the debug source set under the
same package so it is only included in debug/preview builds, update any imports
if needed, and ensure any `@Preview` callers remain in debug or reference the new
debug-only Showcase; keep the function signature and behavior unchanged.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt`:
- Around line 112-119: Remove the redundant inner Surface from the
FirstScreenPreview function: instead of wrapping Content in Surface(), call
Showcase { Content(...) } directly (update the FirstScreenPreview function that
currently calls Showcase { Surface { Content(viewState =
FirstScreenPreviews.viewState(), actions = noOpActions(), modifier =
Modifier.fillMaxSize()) } } ). Also remove the now-unused Surface import that
becomes dead after this change so imports match other previews like
_TemplateScreenUi.kt and PickerScreenUi.kt.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt`:
- Around line 57-62: Remove the redundant Surface wrapper inside the Showcase
usage: delete the outer Surface { ... } so that Content(...) is passed directly
to Showcase (keeping actions = noOpActions() and modifier =
Modifier.fillMaxSize()); then remove the now-unused Surface import from
LoginScreenUi.kt. Locate the Showcase usage in LoginScreenUi (where Content is
currently wrapped) and update it to call Content directly, and remove any unused
androidx.compose.material3.Surface import.

In `@iosApp/shared/KMP/Makefile`:
- Around line 26-33: The build target in the Makefile has too many lines due to
four separate `@echo` calls; replace them with a single consolidated output (e.g.,
one `@printf` that prints the same header, config, flavor, static flag, and
executing line) or extract them into a Makefile define/variable and call it
once, keeping the rest of the target (cd ../../.. && ./gradlew $(GRADLE_TASK)
--no-daemon $(GRADLE_ARGS)) unchanged; update references to the same variables
(KMP_FRAMEWORK_BUILD_TYPE, KMP_BUILD_FLAVOR, KMP_IS_STATIC, GRADLE_TASK,
GRADLE_ARGS) so the printed message remains identical.
- Around line 13-14: Add a guard to fail fast when KMP_BUILD_FLAVOR is not set:
check the KMP_BUILD_FLAVOR variable (similar to the existing
KMP_FRAMEWORK_BUILD_TYPE validation) and invoke $(error ...) with a clear
message if it is empty, then safely construct GRADLE_ARGS :=
-Pbuildkonfig.flavor=$(KMP_BUILD_FLAVOR); place this check after the BUILD_MODE
block so the Makefile will not pass an empty -Pbuildkonfig.flavor to Gradle.

In
`@shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt`:
- Around line 13-15: Add an explicit return type to the noOpActions factory to
match other factories: change the function declaration for noOpActions in
LoginScreen (the function that returns an object : Actions and currently defined
as fun noOpActions() = ... ) to explicitly declare the return type as : Actions
(i.e., fun noOpActions(): Actions = ...), keeping the same body and object
implementation.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ee9152 and d9c5682.

📒 Files selected for processing (19)
  • README.md
  • androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/components/Showcase.kt
  • androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/FirstScreenUi.kt
  • androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/LoginScreenUi.kt
  • androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/PickerScreenUi.kt
  • androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.kt
  • buildSrc/src/main/kotlin/app/futured/kmptemplate/gradle/configuration/ProjectSettings.kt
  • gradle.properties
  • iosApp/Config Files/Beta.xcconfig
  • iosApp/Config Files/Debug.xcconfig
  • iosApp/Config Files/Release.xcconfig
  • iosApp/iosApp/Views/Screen/First/FirstView.swift
  • iosApp/shared/KMP/Makefile
  • shared/app/build.gradle.kts
  • shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/_template/_TemplateScreen.kt
  • shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/firstScreen/FirstScreen.kt
  • shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/firstScreen/FirstScreenPreviews.kt
  • shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/loginScreen/LoginScreen.kt
  • shared/feature/src/commonMain/kotlin/app/futured/kmptemplate/feature/ui/picker/PickerScreen.kt
✅ Files skipped from review due to trivial changes (2)
  • README.md
  • iosApp/Config Files/Beta.xcconfig

Comment on lines +6 to +7
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Template uses collectAsState() — replace with collectAsStateWithLifecycle().

collectAsState() collects unconditionally, ignoring the Android lifecycle. When developers copy this template they will inherit a flow that keeps running (and potentially triggers recompositions) even while the screen is backgrounded/stopped. Every other screen in the project already uses collectAsStateWithLifecycle() from androidx.lifecycle.compose.

🐛 Proposed fix
-import androidx.compose.runtime.collectAsState
-import androidx.compose.runtime.getValue
+import androidx.compose.runtime.getValue
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
-    val viewState by screen.viewState.collectAsState()
+    val viewState by screen.viewState.collectAsStateWithLifecycle()

Also applies to: 29-29

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@androidApp/src/main/kotlin/app/futured/kmptemplate/android/ui/screen/_TemplateScreenUi.kt`
around lines 6 - 7, Replace usage of collectAsState with lifecycle-aware
collectAsStateWithLifecycle: change the import from
androidx.compose.runtime.collectAsState to
androidx.lifecycle.compose.collectAsStateWithLifecycle and update any calls in
the TemplateScreenUi (e.g., where viewModel.someFlow is collected with
collectAsState) to use collectAsStateWithLifecycle() instead while keeping the
existing by delegation/getValue usage (getValue) unchanged; ensure all
occurrences (including the one flagged and the similar occurrence at line 29)
are updated so the Flow respects Android lifecycle.

Comment on lines +2 to +3
org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError
kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

kotlin.daemon.jvm.options Kotlin Gradle Plugin correct property configuration

💡 Result:

To set Kotlin daemon JVM options with the Kotlin Gradle Plugin, you have two different knobs (they behave differently):

1) kotlin.daemon.jvm.options (this is a system property)

You don’t put kotlin.daemon.jvm.options=... directly in gradle.properties. Instead, you pass it as a -D... inside org.gradle.jvmargs, and the value must be comma-separated with no spaces:

# gradle.properties
org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,Xms500m

Rules/quirks:

  • Use commas, no spaces (anything after a space is treated as Gradle’s JVM args, not Kotlin’s).
  • The leading - is only used for certain args (per Kotlin docs).
  • On Gradle 7.0–7.1.1 with JDK 9+ (Kotlin DSL script compilation), this can be ignored; Kotlin recommends upgrading Gradle or using kotlin.daemon.jvmargs instead. [1]

2) kotlin.daemon.jvmargs (this is a Gradle property, usually the preferred approach)

Set it directly in gradle.properties as a normal space-separated JVM arg list:

# gradle.properties
kotlin.daemon.jvmargs=-Xmx1500m -Xms500m

Kotlin notes that if you don’t set -XX:ReservedCodeCacheSize, KGP applies a default (320m). [1]

Precedence (important if you set more than one)

Kotlin daemon JVM args are applied in an override order; kotlin.daemon.jvmargs overrides kotlin.daemon.jvm.options (and both can be overridden again via the kotlin { kotlinDaemonJvmArgs = ... } DSL or per-task config). [1]

Source: Kotlin docs (“Setting Kotlin daemon’s JVM arguments”). [1]


Use kotlin.daemon.jvmargs instead of kotlin.daemon.jvm.options on line 3.

Line 3 incorrectly uses kotlin.daemon.jvm.options as a gradle.properties entry. According to the Kotlin Gradle Plugin documentation, kotlin.daemon.jvm.options is a system property intended to be passed as -Dkotlin.daemon.jvm.options=... within org.gradle.jvmargs, not set directly in gradle.properties. The correct gradle.properties property for configuring Kotlin daemon JVM arguments is kotlin.daemon.jvmargs. Change line 3 to:

kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g

Lines 2 and 26 are correct.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle.properties` around lines 2 - 3, The property key on line 3 is wrong:
replace kotlin.daemon.jvm.options with kotlin.daemon.jvmargs so the Kotlin
daemon JVM arguments are set correctly; update the entry to use
kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g and leave org.gradle.jvmargs
unchanged.

#Gradle
org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dkotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
org.gradle.jvmargs=-Xmx6g -Xms256m -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError
kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if gradle.properties exists and read its contents
find . -name "gradle.properties" -type f

Repository: futuredapp/kmp-futured-template

Length of output: 94


🌐 Web query:

Kotlin Gradle Plugin kotlin.daemon.jvmargs property gradle.properties

💡 Result:

To set Kotlin compiler daemon JVM arguments for the Kotlin Gradle Plugin (KGP) via gradle.properties, add:

# gradle.properties
kotlin.daemon.jvmargs=-Xmx1500m -Xms500m

Notes:

  • This is a Gradle property specifically read by KGP to configure the Kotlin daemon JVM. (kotlinlang.org)
  • If you don’t set -XX:ReservedCodeCacheSize, KGP applies a default of 320m. (kotlinlang.org)
  • There’s also an alternative that routes through org.gradle.jvmargs as a system property (comma-separated, no spaces), which is applied before kotlin.daemon.jvmargs in the override order: (kotlinlang.org)
org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,-Xms500m

Citations:


🌐 Web query:

kotlin.daemon.jvm.options vs kotlin.daemon.jvmargs Kotlin Gradle Plugin

💡 Result:

Both settings configure the Kotlin compiler daemon’s JVM arguments (not the Gradle daemon’s), but they enter the build in different ways and use different syntax/precedence.

kotlin.daemon.jvm.options

  • What it is: a JVM system property that you pass to the Gradle daemon JVM, typically via org.gradle.jvmargs.
  • How to set:
    org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m,Xms500m
  • Syntax quirks: values are comma-separated with no spaces, and - is only allowed before some options (like Xmx, XX:MaxMetaspaceSize, XX:ReservedCodeCacheSize).
  • Known edge case: can be ignored in certain Gradle 7.0–7.1.1 + JDK9+ + Kotlin DSL compilation scenarios; Kotlin docs suggest using kotlin.daemon.jvmargs (or upgrading Gradle) to avoid this. [1]

kotlin.daemon.jvmargs

  • What it is: a Gradle property read by the Kotlin Gradle plugin.
  • How to set:
    kotlin.daemon.jvmargs=-Xmx1500m -Xms500m
  • Syntax: normal JVM-arg format (space-separated).
  • Recommendation: generally the simpler/more reliable way to set Kotlin daemon JVM args. [1]

Precedence (who wins if you set both?)

Kotlin Gradle plugin applies overrides in this order (later wins):
Gradle-daemon inheritance → kotlin.daemon.jvm.optionskotlin.daemon.jvmargskotlin { kotlinDaemonJvmArgs = ... } → per-task settings. [1]

Source
[1] Kotlin docs: “Compilation and caches in the Kotlin Gradle plugin” (Kotlin daemon JVM arguments, precedence, and configuration) (kotlinlang.org)

Citations:


🏁 Script executed:

cat -n ./gradle.properties | head -10

Repository: futuredapp/kmp-futured-template

Length of output: 579


Replace kotlin.daemon.jvm.options with kotlin.daemon.jvmargs — the former is silently ignored in gradle.properties.

kotlin.daemon.jvm.options is a JVM system property meant to be passed via org.gradle.jvmargs (e.g., -Dkotlin.daemon.jvm.options=...), not a standalone gradle.properties key. The Kotlin Gradle Plugin reads kotlin.daemon.jvmargs from gradle.properties. As written, this MaxMetaspaceSize setting for the Kotlin daemon is never applied.

Proposed fix
-kotlin.daemon.jvm.options=-XX:MaxMetaspaceSize=1g
+kotlin.daemon.jvmargs=-XX:MaxMetaspaceSize=1g
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@gradle.properties` at line 3, Replace the incorrect gradle.properties key
kotlin.daemon.jvm.options with the correct property kotlin.daemon.jvmargs so the
Kotlin Gradle Plugin applies the JVM argument; update the entry to use
kotlin.daemon.jvmargs and keep the value -XX:MaxMetaspaceSize=1g (ensuring any
existing org.gradle.jvmargs usage isn't duplicated) so the Kotlin daemon
receives the MaxMetaspaceSize setting.

Comment on lines 46 to 49
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64(),
).forEach {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for iosX64 references in Kotlin/Gradle files
echo "=== Searching for iosX64 in Kotlin/KTS files ==="
rg -n "iosX64" --type=kotlin --type=kts

echo -e "\n=== Searching for iosX64 in YAML files ==="
rg -n "iosX64" --type=yaml

echo -e "\n=== Searching for iosX64 in all files ==="
rg -n "iosX64" --type-list | head -20 || rg -n "iosX64"

echo -e "\n=== Checking for x86_64 or Intel references ==="
rg -n "x86_64|intel|Intel" --type=yaml -g "*{ci,build,github,gitlab}*" | head -20

Repository: futuredapp/kmp-futured-template

Length of output: 694


🏁 Script executed:

#!/bin/bash
# Look for CI/CD configuration files
echo "=== CI Configuration files found ==="
find . -maxdepth 2 -type f \( -name "*.yml" -o -name "*.yaml" -o -name "*.kts" -o -name "*.gradle" \) | grep -i -E "(ci|github|gitlab|build|gradle)" | head -20

echo -e "\n=== Checking for GitHub Actions workflows ==="
find . -path "*/.github/workflows/*" -type f 2>/dev/null | head -20

echo -e "\n=== Checking build.gradle.kts file context ==="
cat -n shared/app/build.gradle.kts | head -60

Repository: futuredapp/kmp-futured-template

Length of output: 3295


🏁 Script executed:

#!/bin/bash
# Check GitHub Actions workflows for runner specifications
echo "=== Contents of on_pull_request.yml ==="
cat -n .github/workflows/on_pull_request.yml

echo -e "\n=== Contents of on_cron.yml ==="
cat -n .github/workflows/on_cron.yml

echo -e "\n=== Contents of on_release.yml ==="
cat -n .github/workflows/on_release.yml

Repository: futuredapp/kmp-futured-template

Length of output: 7337


🏁 Script executed:

#!/bin/bash
# Look for documentation files mentioning platforms
echo "=== Checking for README or CONTRIBUTING files ==="
find . -maxdepth 2 -type f \( -name "README*" -o -name "CONTRIBUTING*" -o -name "SETUP*" \) -o -path "./docs/*" -type f

echo -e "\n=== Searching for platform/Mac/Intel references in documentation ==="
rg -i "intel|x86_64|arm64|apple.silicon|mac.{0,5}setup" --type=markdown

echo -e "\n=== Checking .xcconfig files for simulator arch specs ==="
find . -name "*.xcconfig" -exec echo "--- File: {} ---" \; -exec cat {} \;

Repository: futuredapp/kmp-futured-template

Length of output: 1299


🏁 Script executed:

cat -n ./README.md

Repository: futuredapp/kmp-futured-template

Length of output: 16279


Document Apple Silicon requirement for iOS development.

Removing iosX64() completely drops Intel Mac simulator support. iOS CI already runs on Apple Silicon via self-hosted runners (Futured-controlled), confirming the infrastructure decision. However, this template lacks documentation stating that iOS development requires an Apple Silicon Mac, which is important for contributors forking this template.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@shared/app/build.gradle.kts` around lines 46 - 49, The iOS target list now
only includes iosArm64() and iosSimulatorArm64(), which removes iosX64() and
thus drops Intel Mac simulator support; add a clear note explaining that iOS
development requires an Apple Silicon Mac (and that iosX64 was intentionally
omitted) so contributors know the requirement. Update the documentation (either
add a short comment above the list that contains iosArm64() and
iosSimulatorArm64() in build.gradle.kts and/or add a line in the repo README)
stating the Apple Silicon requirement, the rationale, and any CI note about
self-hosted Apple Silicon runners to guide contributors.

matejsemancik and others added 9 commits February 23, 2026 15:29
Replace findByName guards with lazy dependsOn resolution to fix
implicit task dependency errors that break builds after dependency
bumps. findByName only sees already-realized tasks, causing a race
condition with lazily-registered KSP tasks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

android Android-related issues kmp KMP-related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants