Skip to content

Поддержка конфигурирования дефолтов флагов в зависимости от типа сборки (build type) #297

Description

@kirich1409

Проблема

Сейчас в 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.

Открытые вопросы для проработки дизайна

  1. Форма DSL. Как описывать пер-сборочные дефолты, не ломая текущий лаконичный синтаксис? Например:

    boolean("new_checkout", default = false) {
        defaultFor("debug", true)   // вариант A — оверрайды поверх базового default
    }
    // или
    boolean("new_checkout") {
        default = false
        debug = true                // вариант B
    }
  2. Понятие «тип сборки». Завязываемся на AGP build types/flavors/variants (только Android) или вводим абстрактный набор «профилей сборки», работающий и для JVM/iOS (KMP)? Featured — KMP-библиотека, поэтому привязка только к AGP нежелательна.

  3. Влияние на кодогенерацию. ConfigParam хранит единственный defaultValue. Нужно решить:

    • выбирать дефолт на этапе сборки (разные сгенерированные ConfigParam для разных вариантов), или
    • генерировать выбор дефолта в рантайме по текущему build type.
  4. Влияние на R8 DCE. Сейчас флаги с default = false дают per-function -assumevalues правила (ProguardRulesGenerator) и DISABLE_<FLAG> для iOS (XcconfigGenerator). Если дефолт зависит от build type, правила -assumevalues и xcconfig должны генерироваться per-variant, иначе DCE станет некорректным. Это ключевой аспект, требующий аккуратного дизайна.

  5. Манифест и агрегатор. featured-manifest.json (SCHEMA_VERSION) и GeneratedFeaturedRegistry.all сейчас несут один дефолт на флаг. Нужно решить, как в них отражать пер-сборочные дефолты (и нужно ли поднимать SCHEMA_VERSION).

  6. 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 (для будущей реализации)

  • Согласован дизайн DSL для пер-сборочных дефолтов.
  • Реализована кодогенерация, корректно выбирающая дефолт по типу сборки.
  • R8 -assumevalues и iOS xcconfig генерируются консистентно по вариантам (DCE остаётся корректным).
  • Обновлены/добавлены тесты плагина и featured-shrinker-tests.
  • Обновлена документация (CLAUDE.md плагина, примеры в :sample).

Issue создан как задача-заготовка; реализация будет выполнена отдельным PR в ветку develop.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions