Проблема
Сейчас в DSL featured { localFlags { … } } для каждого флага задаётся ровно одно значение по умолчанию (FlagSpec.defaultValue, см. featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FlagContainer.kt и FlagSpec.kt):
featured {
localFlags {
boolean("dark_mode", default = false)
int("max_retries", default = 3)
enum("checkout_variant", typeFqn = "com.example.CheckoutVariant", default = "LEGACY")
}
}
Этот дефолт одинаков для всех сборок. На практике часто нужно, чтобы значение по умолчанию отличалось в зависимости от типа сборки (debug / release, либо произвольные build types / flavors / variants): например, экспериментальную фичу включать по умолчанию только в debug, а в release оставлять выключенной.
Цель
Дать возможность задавать значение по умолчанию флага в зависимости от типа сборки.
⚠️ Это задача-заготовка на будущее. Реализацию сейчас делать не нужно — нужно зафиксировать требование, продумать дизайн API и оценить влияние на кодогенерацию и DCE.
Открытые вопросы для проработки дизайна
-
Форма DSL. Как описывать пер-сборочные дефолты, не ломая текущий лаконичный синтаксис? Например:
boolean("new_checkout", default = false) {
defaultFor("debug", true) // вариант A — оверрайды поверх базового default
}
// или
boolean("new_checkout") {
default = false
debug = true // вариант B
}
-
Понятие «тип сборки». Завязываемся на AGP build types/flavors/variants (только Android) или вводим абстрактный набор «профилей сборки», работающий и для JVM/iOS (KMP)? Featured — KMP-библиотека, поэтому привязка только к AGP нежелательна.
-
Влияние на кодогенерацию. ConfigParam хранит единственный defaultValue. Нужно решить:
- выбирать дефолт на этапе сборки (разные сгенерированные
ConfigParam для разных вариантов), или
- генерировать выбор дефолта в рантайме по текущему build type.
-
Влияние на R8 DCE. Сейчас флаги с default = false дают per-function -assumevalues правила (ProguardRulesGenerator) и DISABLE_<FLAG> для iOS (XcconfigGenerator). Если дефолт зависит от build type, правила -assumevalues и xcconfig должны генерироваться per-variant, иначе DCE станет некорректным. Это ключевой аспект, требующий аккуратного дизайна.
-
Манифест и агрегатор. featured-manifest.json (SCHEMA_VERSION) и GeneratedFeaturedRegistry.all сейчас несут один дефолт на флаг. Нужно решить, как в них отражать пер-сборочные дефолты (и нужно ли поднимать SCHEMA_VERSION).
-
Debug UI. FeatureFlagsDebugScreen показывает текущие значения — учесть, какой именно дефолт показывать.
Затронутые места (ориентир)
featured-gradle-plugin/.../FlagSpec.kt, FlagContainer.kt, FeaturedExtension.kt — DSL.
ConfigParamGenerator.kt, ProguardRulesGenerator.kt, XcconfigGenerator.kt, IosConstValGenerator.kt — кодогенерация и DCE.
manifest/ (GenerateFeaturedManifestTask.kt, SCHEMA_VERSION) и агрегатор (GeneratedFeaturedRegistry.all).
Definition of Done (для будущей реализации)
Issue создан как задача-заготовка; реализация будет выполнена отдельным PR в ветку develop.
Проблема
Сейчас в DSL
featured { localFlags { … } }для каждого флага задаётся ровно одно значение по умолчанию (FlagSpec.defaultValue, см.featured-gradle-plugin/src/main/kotlin/dev/androidbroadcast/featured/gradle/FlagContainer.ktиFlagSpec.kt):featured { localFlags { boolean("dark_mode", default = false) int("max_retries", default = 3) enum("checkout_variant", typeFqn = "com.example.CheckoutVariant", default = "LEGACY") } }Этот дефолт одинаков для всех сборок. На практике часто нужно, чтобы значение по умолчанию отличалось в зависимости от типа сборки (
debug/release, либо произвольные build types / flavors / variants): например, экспериментальную фичу включать по умолчанию только вdebug, а вreleaseоставлять выключенной.Цель
Дать возможность задавать значение по умолчанию флага в зависимости от типа сборки.
Открытые вопросы для проработки дизайна
Форма DSL. Как описывать пер-сборочные дефолты, не ломая текущий лаконичный синтаксис? Например:
Понятие «тип сборки». Завязываемся на AGP build types/flavors/variants (только Android) или вводим абстрактный набор «профилей сборки», работающий и для JVM/iOS (KMP)? Featured — KMP-библиотека, поэтому привязка только к AGP нежелательна.
Влияние на кодогенерацию.
ConfigParamхранит единственныйdefaultValue. Нужно решить:ConfigParamдля разных вариантов), илиВлияние на R8 DCE. Сейчас флаги с
default = falseдают per-function-assumevaluesправила (ProguardRulesGenerator) иDISABLE_<FLAG>для iOS (XcconfigGenerator). Если дефолт зависит от build type, правила-assumevaluesи xcconfig должны генерироваться per-variant, иначе DCE станет некорректным. Это ключевой аспект, требующий аккуратного дизайна.Манифест и агрегатор.
featured-manifest.json(SCHEMA_VERSION) иGeneratedFeaturedRegistry.allсейчас несут один дефолт на флаг. Нужно решить, как в них отражать пер-сборочные дефолты (и нужно ли подниматьSCHEMA_VERSION).Debug UI.
FeatureFlagsDebugScreenпоказывает текущие значения — учесть, какой именно дефолт показывать.Затронутые места (ориентир)
featured-gradle-plugin/.../FlagSpec.kt,FlagContainer.kt,FeaturedExtension.kt— DSL.ConfigParamGenerator.kt,ProguardRulesGenerator.kt,XcconfigGenerator.kt,IosConstValGenerator.kt— кодогенерация и DCE.manifest/(GenerateFeaturedManifestTask.kt,SCHEMA_VERSION) и агрегатор (GeneratedFeaturedRegistry.all).Definition of Done (для будущей реализации)
-assumevaluesи iOS xcconfig генерируются консистентно по вариантам (DCE остаётся корректным).featured-shrinker-tests.:sample).Issue создан как задача-заготовка; реализация будет выполнена отдельным PR в ветку
develop.