Conversation
Integrate kmp-product-flavors (v1.0.0) for cross-platform flavor support that aligns with existing Android application flavors.
## Changes
- Add kmp-product-flavors v1.0.0 to version catalog
- Create KMPFlavorsConventionPlugin for easy integration
- Add KmpFlavors.kt with centralized flavor configuration
- Configure demo/prod flavors matching Android application
- Add mavenLocal() for local development support
## Features
- Cross-platform flavor support (Android, iOS, Desktop, Web)
- BuildConfig generation with flavor-specific constants
- Automatic source set wiring for all platforms
- Aligns with existing Android contentType dimension (demo/prod)
## Usage
Apply to any KMP module:
```kotlin
plugins {
id("org.convention.kmp.flavors")
}
```
Build with specific flavor:
```bash
./gradlew build -PkmpFlavor=prod
```
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply kmp.flavors in KMPLibraryConventionPlugin (all KMP modules get flavors) - Apply kmp.flavors in KMPCoreBaseLibraryConventionPlugin - Add kmp-flavors-convention to version catalog for direct usage - Remove mavenLocal (not needed for production - plugin on Maven Central) All KMP library modules now automatically get cross-platform flavor support (demo/prod) that aligns with Android application flavors. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis change introduces Kotlin Multiplatform (KMP) Product Flavors support by registering a new convention plugin, creating a centralized flavor configuration module, and integrating it into existing KMP library plugins to enable cross-platform flavor dimensions with DEMO and PROD variants. Changes
Sequence DiagramsequenceDiagram
participant Gradle as Gradle Build<br/>Initialization
participant KMPLib as KMPLibraryConvention<br/>Plugin
participant KMPFlav as KMPFlavorsConvention<br/>Plugin
participant KmpConfig as KmpFlavors<br/>Configuration
participant Project as Project
Gradle->>KMPLib: Apply plugin
KMPLib->>KMPFlav: Apply org.convention.kmp.flavors
KMPFlav->>KMPFlav: Instantiate plugin
KMPFlav->>KmpConfig: Call configureKmpFlavors()
KmpConfig->>KmpConfig: Extract defaultDimensions
KmpConfig->>KmpConfig: Extract defaultFlavors (DEMO, PROD)
KmpConfig->>KmpConfig: Add standard BuildConfig fields<br/>(BASE_URL, ANALYTICS_ENABLED)
KmpConfig->>Project: Configure flavor extension<br/>with dimensions & flavors
Project-->>Gradle: Flavors configured & BuildConfig ready
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
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. Comment |
Version Update RequiredPlease update the kmp-product-flavors version to File: - kmpProductFlavors = "1.0.0"
+ kmpProductFlavors = "1.0.1"v1.0.1 Fixes
The v1.0.1 release is now publishing to Maven Central and Gradle Plugin Portal. |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (5)
gradle/libs.versions.toml (1)
57-57: Version entry placed under the wrong section.
kmpProductFlavorsis listed under the "Static Analysis & Code Formatting" section, but it's a build/flavor plugin, not a static analysis or formatting tool. Consider moving it to a more appropriate section (e.g., near "KMP & CMP" entries or a new dedicated section) for maintainability.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@gradle/libs.versions.toml` at line 57, The version entry "kmpProductFlavors" is placed under the "Static Analysis & Code Formatting" section but belongs with build/flavor tooling; move the kmpProductFlavors = "1.0.0" line out of that section and place it near the "KMP & CMP" entries (or create a new "KMP / Build Flavors" section) so it groups logically with other KMP/build plugin versions and retains alphabetical/organizational ordering.build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt (3)
139-174: Potential shadowing:flavorsparameter vsflavorsextension method.On line 160,
this.flavors { ... }calls the extension'sflavorsconfiguration block, while the parameterflavors: List<FlavorConfigData>on line 142 is also namedflavors. Inside the lambda on line 161,flavorsresolves to the parameter due to scoping, which happens to be correct here. However, this is fragile and could confuse future maintainers.Rename parameter to avoid ambiguity
fun configureKmpFlavors( extension: KmpFlavorExtension, dimensions: List<DimensionConfig>, - flavors: List<FlavorConfigData>, + flavorConfigs: List<FlavorConfigData>, generateBuildConfig: Boolean = true, buildConfigPackage: String? = null, ) { extension.apply { ... this.flavors { - flavors.forEach { flavorData -> + flavorConfigs.forEach { flavorData ->🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt` around lines 139 - 174, Rename the function parameter flavors: List<FlavorConfigData> to a non-shadowing name (e.g., flavorConfigs) in configureKmpFlavors so it doesn’t conflict with the KmpFlavorExtension.flavors { ... } configuration block; update all uses inside the function (change flavors.forEach { ... } to flavorConfigs.forEach { ... } and any other references to the parameter) so the call to this.flavors { register(...) } clearly refers to the extension method and the loop iterates the renamed parameter.
94-97: Hardcoded API base URLs in build-logic.
getBaseUrlhardcodeshttps://demo-api.mifos.organdhttps://api.mifos.org. These are fine for this specific template, but they'll be baked into the generatedBuildConfigfor every module that applies the flavors plugin. If this template is forked, users may overlook updating these values.Consider adding a comment or documenting that downstream projects should customize these URLs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt` around lines 94 - 97, The getBaseUrl(flavor: Flavor) function currently returns hardcoded URLs for Flavor.DEMO and Flavor.PROD; add a brief TODO comment above getBaseUrl calling out that these values are template defaults that must be customized by downstream projects (or provide instructions to override), and change implementation to prefer configurable values (e.g., read from project properties or environment) with the existing hardcoded URLs as fallbacks; reference the getBaseUrl function and the Flavor.DEMO / Flavor.PROD branches so reviewers can locate and verify the TODO and the new config-first fallback behavior.
64-69: ReplaceEnum.values()withEnum.entriesfor Kotlin 1.9+ compatibility.
Dimension.values()(line 64),Flavor.values()(line 75), andFlavor.values()again (line 183) use the syntheticvalues()method. Since Kotlin 1.9,entriesis the recommended modern replacement, offering better performance and consistency across platforms. This project targets Kotlin 2.2.21.Replace values() with entries
val defaultDimensions: List<DimensionConfig> - get() = Dimension.values().map { dimension -> + get() = Dimension.entries.map { dimension ->val defaultFlavors: List<FlavorConfigData> - get() = Flavor.values().map { flavor -> + get() = Flavor.entries.map { flavor ->- val flavor = KmpFlavors.Flavor.values().find { it.flavorName == flavorData.name } + val flavor = KmpFlavors.Flavor.entries.find { it.flavorName == flavorData.name }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt` around lines 64 - 69, Replace all uses of the synthetic Enum.values() with the Kotlin 1.9+ entries property: change Dimension.values() to Dimension.entries and both Flavor.values() occurrences to Flavor.entries. Locate the mapping logic that builds DimensionConfig (where you currently call Dimension.values()) and the places that iterate over Flavor (including the mapping creating flavor configs and the later occurrence around line 183) and swap .values() for .entries so the code iterates over the enum entries collection compatible with Kotlin 2.2.21.build-logic/convention/build.gradle.kts (1)
35-36:implementationscope is correct for class-based plugin application, but considercompileOnlyfor consistency.Other Gradle plugin dependencies in this block use
compileOnly(e.g.,libs.android.gradlePlugin,libs.kotlin.gradlePlugin). This one usesimplementationbecauseKMPFlavorsConventionPluginappliesKmpFlavorPluginby class reference (pluginManager.apply(KmpFlavorPlugin::class.java)), which requires the class to be on the runtime classpath.If you'd prefer consistency, you could switch to applying the plugin by its string ID instead (which would allow
compileOnly), assuming the plugin ID is declared in the consuming project's classpath. However, the current approach is functionally correct.Alternative: apply by plugin ID with compileOnly
In
build.gradle.kts:- implementation(libs.kmpProductFlavors.gradlePlugin) + compileOnly(libs.kmpProductFlavors.gradlePlugin)In
KMPFlavorsConventionPlugin.kt:- pluginManager.apply(KmpFlavorPlugin::class.java) + pluginManager.apply("io.github.mobilebytelabs.kmpflavors") // or whatever the plugin ID isThis would require consuming modules to have the plugin on their classpath (e.g., via
settings.gradle.ktsplugin management).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build-logic/convention/build.gradle.kts` around lines 35 - 36, The current dependency uses implementation(libs.kmpProductFlavors.gradlePlugin) because KMPFlavorsConventionPlugin applies the plugin by class reference via pluginManager.apply(KmpFlavorPlugin::class.java), which requires the plugin on the runtime classpath; to make this consistent with other plugin deps use compileOnly you have two options: either keep the class-based application and leave implementation as-is, or change KMPFlavorsConventionPlugin to apply the plugin by its string ID (pluginManager.apply("com.example.kmpflavor") / apply(plugin = "com.example.kmpflavor") pattern) so you can switch the dependency to compileOnly(libs.kmpProductFlavors.gradlePlugin); update the code around KMPFlavorsConventionPlugin and the plugin application call (KmpFlavorPlugin::class.java) accordingly and ensure the plugin ID is provided on the consuming projects' classpath (pluginManagement).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@build-logic/convention/src/main/kotlin/KMPFlavorsConventionPlugin.kt`:
- Around line 49-67: inferBuildConfigPackage currently builds package segments
from project.name and project.path without sanitizing invalid Java/Kotlin
identifiers and uses a hardcoded "org.mifos" prefix; update
inferBuildConfigPackage to (1) read a configurable base package first (e.g.,
from a project property like "buildConfigPackageBase" or fallback to
project.group if set), (2) sanitize every segment derived from project.name and
pathParts by replacing non-alphanumeric/underscore characters with underscores,
lowercasing, and if a segment starts with a digit prefixing it with an
underscore so it becomes a valid identifier, and (3) join the sanitized segments
with dots and prepend the configurable base (instead of the hardcoded
"org.mifos") before returning the package string; refer to
inferBuildConfigPackage, project.name, pathParts, and the "org.mifos" prefix
when locating places to change.
In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt`:
- Line 66: The dimension name transform in KmpFlavors (the expression that
builds the flavor dimension name from dimension.name) lowercases and strips
underscores producing "contenttype" which mismatches Android's
FlavorDimension.contentType (camelCase); update the transformation used where
name = dimension.name.lowercase().replace("_", "") (and the analogous occurrence
later in the same file) to produce camelCase (e.g., convert tokens split by '_'
to lower-firstToken + capitalized subsequent tokens) so CONTENT_TYPE becomes
contentType and matches AppFlavor/FlavorDimension.
In `@gradle/libs.versions.toml`:
- Line 255: The dependency entry kmpProductFlavors-gradlePlugin = { group =
"io.github.mobilebytelabs.kmpflavors", name = "flavor-plugin", version.ref =
"kmpProductFlavors" } references an artifact that isn't on Maven Central; verify
the coordinates (group/name/version referenced by kmpProductFlavors) and either
correct them or add the repository that hosts the artifact to the Gradle
repositories (e.g., maven { url "..." } or a private repo with credentials) so
Gradle can resolve it; if this is an internal artifact ensure the appropriate
credentials and repository are configured in the project’s build/repository
configuration or replace version.ref with a published version available on the
configured repositories.
---
Nitpick comments:
In `@build-logic/convention/build.gradle.kts`:
- Around line 35-36: The current dependency uses
implementation(libs.kmpProductFlavors.gradlePlugin) because
KMPFlavorsConventionPlugin applies the plugin by class reference via
pluginManager.apply(KmpFlavorPlugin::class.java), which requires the plugin on
the runtime classpath; to make this consistent with other plugin deps use
compileOnly you have two options: either keep the class-based application and
leave implementation as-is, or change KMPFlavorsConventionPlugin to apply the
plugin by its string ID (pluginManager.apply("com.example.kmpflavor") /
apply(plugin = "com.example.kmpflavor") pattern) so you can switch the
dependency to compileOnly(libs.kmpProductFlavors.gradlePlugin); update the code
around KMPFlavorsConventionPlugin and the plugin application call
(KmpFlavorPlugin::class.java) accordingly and ensure the plugin ID is provided
on the consuming projects' classpath (pluginManagement).
In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt`:
- Around line 139-174: Rename the function parameter flavors:
List<FlavorConfigData> to a non-shadowing name (e.g., flavorConfigs) in
configureKmpFlavors so it doesn’t conflict with the KmpFlavorExtension.flavors {
... } configuration block; update all uses inside the function (change
flavors.forEach { ... } to flavorConfigs.forEach { ... } and any other
references to the parameter) so the call to this.flavors { register(...) }
clearly refers to the extension method and the loop iterates the renamed
parameter.
- Around line 94-97: The getBaseUrl(flavor: Flavor) function currently returns
hardcoded URLs for Flavor.DEMO and Flavor.PROD; add a brief TODO comment above
getBaseUrl calling out that these values are template defaults that must be
customized by downstream projects (or provide instructions to override), and
change implementation to prefer configurable values (e.g., read from project
properties or environment) with the existing hardcoded URLs as fallbacks;
reference the getBaseUrl function and the Flavor.DEMO / Flavor.PROD branches so
reviewers can locate and verify the TODO and the new config-first fallback
behavior.
- Around line 64-69: Replace all uses of the synthetic Enum.values() with the
Kotlin 1.9+ entries property: change Dimension.values() to Dimension.entries and
both Flavor.values() occurrences to Flavor.entries. Locate the mapping logic
that builds DimensionConfig (where you currently call Dimension.values()) and
the places that iterate over Flavor (including the mapping creating flavor
configs and the later occurrence around line 183) and swap .values() for
.entries so the code iterates over the enum entries collection compatible with
Kotlin 2.2.21.
In `@gradle/libs.versions.toml`:
- Line 57: The version entry "kmpProductFlavors" is placed under the "Static
Analysis & Code Formatting" section but belongs with build/flavor tooling; move
the kmpProductFlavors = "1.0.0" line out of that section and place it near the
"KMP & CMP" entries (or create a new "KMP / Build Flavors" section) so it groups
logically with other KMP/build plugin versions and retains
alphabetical/organizational ordering.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
build-logic/convention/build.gradle.ktsbuild-logic/convention/src/main/kotlin/KMPCoreBaseLibraryConventionPlugin.ktbuild-logic/convention/src/main/kotlin/KMPFlavorsConventionPlugin.ktbuild-logic/convention/src/main/kotlin/KMPLibraryConventionPlugin.ktbuild-logic/convention/src/main/kotlin/org/convention/KmpFlavors.ktgradle/libs.versions.toml
| private fun inferBuildConfigPackage(project: Project): String { | ||
| // Try to use the project's group if available | ||
| val group = project.group.toString() | ||
| if (group.isNotEmpty() && group != "unspecified") { | ||
| return "$group.${project.name.replace("-", ".")}" | ||
| } | ||
|
|
||
| // Fall back to path-based package name | ||
| val pathParts = project.path | ||
| .removePrefix(":") | ||
| .split(":") | ||
| .filter { it.isNotEmpty() } | ||
|
|
||
| return if (pathParts.isNotEmpty()) { | ||
| "org.mifos.${pathParts.joinToString(".") { it.replace("-", ".") }}" | ||
| } else { | ||
| "org.mifos.${project.name.replace("-", ".")}" | ||
| } | ||
| } |
There was a problem hiding this comment.
Package name inference may produce invalid Kotlin/Java packages.
A few concerns with inferBuildConfigPackage:
-
Line 53:
project.name.replace("-", ".")doesn't sanitize characters that are invalid in Java/Kotlin package identifiers (e.g., names starting with a digit, or containing other special characters). A module named3d-rendererwould produce a segment starting with3d. -
Line 63: Same issue with
pathParts.joinToString(".")— path segments could begin with digits or contain other invalid chars. -
Lines 63, 65: The
"org.mifos."prefix is hardcoded. Since this is a project template intended for forking, downstream users will inheritorg.mifosBuildConfig packages unless they set an explicit group. Consider deriving this from a configurable property or at minimum documenting that users should setproject.group.
Suggested defensive sanitization
+ /**
+ * Sanitizes a string segment to be a valid Java/Kotlin package identifier.
+ */
+ private fun sanitizePackageSegment(segment: String): String =
+ segment.replace("-", ".")
+ .split(".")
+ .joinToString(".") { part ->
+ if (part.firstOrNull()?.isDigit() == true) "_$part" else part
+ }
+
private fun inferBuildConfigPackage(project: Project): String {
val group = project.group.toString()
if (group.isNotEmpty() && group != "unspecified") {
- return "$group.${project.name.replace("-", ".")}"
+ return "$group.${sanitizePackageSegment(project.name)}"
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@build-logic/convention/src/main/kotlin/KMPFlavorsConventionPlugin.kt` around
lines 49 - 67, inferBuildConfigPackage currently builds package segments from
project.name and project.path without sanitizing invalid Java/Kotlin identifiers
and uses a hardcoded "org.mifos" prefix; update inferBuildConfigPackage to (1)
read a configurable base package first (e.g., from a project property like
"buildConfigPackageBase" or fallback to project.group if set), (2) sanitize
every segment derived from project.name and pathParts by replacing
non-alphanumeric/underscore characters with underscores, lowercasing, and if a
segment starts with a digit prefixing it with an underscore so it becomes a
valid identifier, and (3) join the sanitized segments with dots and prepend the
configurable base (instead of the hardcoded "org.mifos") before returning the
package string; refer to inferBuildConfigPackage, project.name, pathParts, and
the "org.mifos" prefix when locating places to change.
| val defaultDimensions: List<DimensionConfig> | ||
| get() = Dimension.values().map { dimension -> | ||
| DimensionConfig( | ||
| name = dimension.name.lowercase().replace("_", ""), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, find and read the KmpFlavors.kt file
find . -name "KmpFlavors.kt" -type fRepository: openMF/kmp-project-template
Length of output: 140
🏁 Script executed:
#!/bin/bash
# Read the KmpFlavors.kt file to see lines around 66 and 78
cat -n ./build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.ktRepository: openMF/kmp-project-template
Length of output: 7080
🏁 Script executed:
#!/bin/bash
# Search for contentType, contenttype, CONTENT_TYPE usage in the codebase
rg -i "contenttype|content_type" --type=kt -C 3Repository: openMF/kmp-project-template
Length of output: 97
🏁 Script executed:
#!/bin/bash
# Search for contentType, contenttype, CONTENT_TYPE usage in the codebase
rg -i "contenttype|content_type" -C 3Repository: openMF/kmp-project-template
Length of output: 5960
🏁 Script executed:
#!/bin/bash
# Let's look at the AppFlavor.kt file more closely to understand the dimension naming
cat -n ./build-logic/convention/src/main/kotlin/org/convention/AppFlavor.ktRepository: openMF/kmp-project-template
Length of output: 2182
🏁 Script executed:
#!/bin/bash
# Check if there's any test or usage that validates the dimension names match
rg "contentType\|contenttype" --type-list | head -20
find . -name "*.gradle.kts" -o -name "build.gradle" | xargs grep -l "contentType\|contenttype\|kmp.*flavor" 2>/dev/null | head -10Repository: openMF/kmp-project-template
Length of output: 519
🏁 Script executed:
#!/bin/bash
# Check the build.gradle.kts file for kmp-product-flavors configuration
cat -n ./build-logic/convention/build.gradle.kts | head -80Repository: openMF/kmp-project-template
Length of output: 3032
🏁 Script executed:
#!/bin/bash
# Search for how kmp-product-flavors is actually used and if there's any configuration or test
find . -type f \( -name "*.kt" -o -name "*.kts" \) | xargs grep -l "kmpProductFlavors\|KmpFlavorExtension\|configureKmpFlavors" 2>/dev/nullRepository: openMF/kmp-project-template
Length of output: 253
🏁 Script executed:
#!/bin/bash
# Read the KMPFlavorsConventionPlugin.kt to see how it's being used
cat -n ./build-logic/convention/src/main/kotlin/KMPFlavorsConventionPlugin.ktRepository: openMF/kmp-project-template
Length of output: 2902
🏁 Script executed:
#!/bin/bash
# Search for any test files that might validate dimension names
find . -type f -name "*Test*.kt" -o -name "*test*.kts" | xargs grep -l "contenttype\|contentType\|dimension" 2>/dev/null | head -5Repository: openMF/kmp-project-template
Length of output: 53
🏁 Script executed:
#!/bin/bash
# Search for any gradle configuration files that might show how dimension names are used
find . -type f -name "*.gradle.kts" | xargs grep -A5 -B5 "dimension\|flavorDimension" 2>/dev/null | head -50Repository: openMF/kmp-project-template
Length of output: 53
Dimension name transform produces "contenttype" instead of "contentType" — this mismatches Android configuration.
Android's FlavorDimension.contentType (line 33 of AppFlavor.kt) registers the dimension as "contentType" (camelCase). However, lines 66 and 78 of KmpFlavors.kt transform CONTENT_TYPE to "contenttype" (all lowercase), causing a mismatch.
The transform should convert CONTENT_TYPE to contentType to align with Android's expected dimension name:
Suggested fix for camelCase conversion
- name = dimension.name.lowercase().replace("_", ""),
+ name = dimension.name.lowercase()
+ .replace(Regex("_([a-z])")) { it.groupValues[1].uppercase() },Apply the same to line 78.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| name = dimension.name.lowercase().replace("_", ""), | |
| name = dimension.name.lowercase() | |
| .replace(Regex("_([a-z])")) { it.groupValues[1].uppercase() }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@build-logic/convention/src/main/kotlin/org/convention/KmpFlavors.kt` at line
66, The dimension name transform in KmpFlavors (the expression that builds the
flavor dimension name from dimension.name) lowercases and strips underscores
producing "contenttype" which mismatches Android's FlavorDimension.contentType
(camelCase); update the transformation used where name =
dimension.name.lowercase().replace("_", "") (and the analogous occurrence later
in the same file) to produce camelCase (e.g., convert tokens split by '_' to
lower-firstToken + capitalized subsequent tokens) so CONTENT_TYPE becomes
contentType and matches AppFlavor/FlavorDimension.
| kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } | ||
|
|
||
| ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } | ||
| kmpProductFlavors-gradlePlugin = { group = "io.github.mobilebytelabs.kmpflavors", name = "flavor-plugin", version.ref = "kmpProductFlavors" } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the artifact exists on Maven Central
echo "Checking Maven Central for io.github.mobilebytelabs.kmpflavors:flavor-plugin:1.0.0"
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "https://repo1.maven.org/maven2/io/github/mobilebytelabs/kmpflavors/flavor-plugin/1.0.0/flavor-plugin-1.0.0.pom")
echo "HTTP Response Code: $HTTP_CODE"
if [ "$HTTP_CODE" == "200" ]; then
echo "✓ Artifact is available on Maven Central"
elif [ "$HTTP_CODE" == "404" ]; then
echo "✗ Artifact NOT found on Maven Central (404)"
else
echo "? Unexpected response code: $HTTP_CODE"
fiRepository: openMF/kmp-project-template
Length of output: 221
The artifact io.github.mobilebytelabs.kmpflavors:flavor-plugin:1.0.0 is not available on Maven Central. The dependency cannot be resolved with this configuration and the build will fail.
Confirm the artifact group ID, name, and version are correct. If the artifact is published to an alternative repository, add that repository to the project's Gradle configuration. If this is a custom or private artifact, ensure the appropriate repository and credentials are configured.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@gradle/libs.versions.toml` at line 255, The dependency entry
kmpProductFlavors-gradlePlugin = { group =
"io.github.mobilebytelabs.kmpflavors", name = "flavor-plugin", version.ref =
"kmpProductFlavors" } references an artifact that isn't on Maven Central; verify
the coordinates (group/name/version referenced by kmpProductFlavors) and either
correct them or add the repository that hosts the artifact to the Gradle
repositories (e.g., maven { url "..." } or a private repo with credentials) so
Gradle can resolve it; if this is an internal artifact ensure the appropriate
credentials and repository are configured in the project’s build/repository
configuration or replace version.ref with a published version available on the
configured repositories.
|
Superseded by #132 which uses kmp-product-flavors v1.0.1 with source set dependency fixes. |
Summary
Integrate kmp-product-flavors (v1.0.0) for cross-platform flavor support that aligns with existing Android application flavors.
What's Changed
Convention Plugin Integration
org.convention.kmp.flavorsautomaticallyorg.convention.kmp.flavorsautomaticallyNew Files
KMPFlavorsConventionPlugin.kt- Convention plugin wrapping kmp-product-flavorsorg/convention/KmpFlavors.kt- Centralized flavor configurationVersion Catalog
kmpProductFlavors = "1.0.0"versionkmpProductFlavors-gradlePluginlibrarykmp-flavors-conventionplugin aliasHow It Works
Since KMP flavors is applied in
KMPLibraryConventionPluginandKMPCoreBaseLibraryConventionPlugin, ALL existing KMP modules automatically get:Cross-platform BuildConfig - Access flavor info from shared code:
Flavor-specific source sets -
commonDemo,commonProd,iosDemo, etc.Aligned with Android - Same demo/prod flavors as Android application
Build Commands
Test Plan
./gradlew build./gradlew build -PkmpFlavor=prod./gradlew listFlavorsshows demo/prod variants🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
New Features
Build Configuration