diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f7a61e5..a5714cc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -46,7 +46,9 @@ jobs: ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.GPG_KEY_ID }} ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.GPG_KEY_PASSWORD }} ORG_GRADLE_PROJECT_VERSION_NAME: ${{ steps.version.outputs.VERSION_NAME }} - run: ./gradlew --no-daemon publishAllPublicationsToMavenCentralRepository + # publishToMavenCentral = manual promotion (no auto-release); --no-configuration-cache for + # release-pipeline debuggability (runs once per tag, CC savings are zero). + run: ./gradlew --no-daemon publishToMavenCentral --no-configuration-cache publish-xcframework: name: Publish XCFramework to GitHub Release diff --git a/CHANGELOG.md b/CHANGELOG.md index 395ca24..f8aea62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,38 +7,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.0-Beta1] - 2026-05-17 + ### Added -- Configuration Cache support (Gradle 9+, AGP 9+) for `featured-gradle-plugin` -- `NSUserDefaultsConfigValueProvider` for iOS/macOS local storage (#104) +#### Core library + +- Core KMP library: `ConfigParam`, `ConfigValue`, `ConfigValues` with reactive `Flow` API +- Explicit initialization mechanism for `ConfigValues` (#98) - `clear()` method on `LocalConfigValueProvider` interface (#101) - Graceful error handling when a provider fails (#100) - Multivariate flag support — `enum` and sealed class `ConfigParam` types (#99) -- Explicit initialization mechanism for `ConfigValues` (#98) +- SKIE 0.10.10 bridge for Swift interop (coroutines, sealed classes, default arguments) +- Combine `Publisher` support in `FeatureFlags.swift` (#88) +- XCFramework published as Swift Package Manager artifact (#91) + +#### Providers + +- `InMemoryConfigValueProvider` — built-in in-memory local provider +- `SharedPreferencesConfigValueProvider` — local storage via SharedPreferences +- `DataStoreConfigValueProvider` — local storage via Jetpack DataStore +- `JavaPreferencesConfigValueProvider` — default JVM local provider (#167, #178) +- `NSUserDefaultsConfigValueProvider` for iOS/macOS local storage (#104) +- `FirebaseConfigValueProvider` — remote config via Firebase Remote Config + +#### Gradle plugin and code generation + +- `featured-gradle-plugin` module — code generation for Kotlin, iOS, and ProGuard (#72, #76, #80, #83, #86) +- Declare flags via Gradle DSL; auto-generate typed extensions and per-function R8 rules +- Enum-typed flags in Gradle DSL (#162) +- Auto-generated `FlagRegistry` initializers per module (#110) +- Auto-wired ProGuard rules into Android builds via AGP Variant API +- Configuration Cache support (Gradle 9+, AGP 9+) (#164) +- E2E integration test for `featured-gradle-plugin` +- `featured-shrinker-tests` — R8 dead-code-elimination verification module (#165) + +#### Static analysis + +- `featured-lint-rules` Android Lint module with `HardcodedFlagValue`, `UncheckedFlagAccess`, `ExpiredFeatureFlag`, and `InvalidFlagReference` detectors (#141, #176, #181) +- Detekt rules: `@BehindFlag` / `@AssumesFlag` annotations and `InvalidFlagReference` / `UncheckedFlagAccess` rules (#142) + +#### Compose and tooling + +- `featured-compose` module — `LocalConfigValues` CompositionLocal and `collectAsState` (#73, #78) +- `featured-debug-ui` module — Compose Multiplatform flag override UI (#79) +- `featured-registry` module — declarative flag scanning across modules (#74) - `featured-testing` module with `FakeConfigValues` and test DSL (#97) -- MkDocs Material documentation website (#96) + +#### Packaging and docs + - Bill of Materials (`featured-bom`) module (#82) - Maven Central publishing for all modules (#81) -- `featured-debug-ui` module — Compose Multiplatform flag override UI (#79, #648f38e) -- `featured-gradle-plugin` module — code generation for Kotlin, iOS, and ProGuard (#72, #76, #80, #83, #86) -- `featured-registry` module — declarative flag scanning across modules (#74) -- `featured-compose` module — `LocalConfigValues` CompositionLocal and `collectAsState` (#73, #78) -- XCFramework published as Swift Package Manager artifact (#91) -- Combine `Publisher` support in `FeatureFlags.swift` (#88) - Dokka API reference generation (#92) -- `FirebaseConfigValueProvider` — remote config via Firebase Remote Config -- `DataStoreConfigValueProvider` — local storage via Jetpack DataStore -- `SharedPreferencesConfigValueProvider` — local storage via SharedPreferences -- `InMemoryConfigValueProvider` — built-in in-memory local provider -- Core KMP library: `ConfigParam`, `ConfigValue`, `ConfigValues` with reactive `Flow` API -- SKIE 0.10.5 bridge for Swift interop (coroutines, sealed classes, default arguments) -- Binary Compatibility Validator (BCV) API dump for all modules (#95) +- MkDocs Material documentation website (#96) - DI pattern documentation for multi-module `ConfigValues` usage (#93) +- `SECURITY.md` with vulnerability disclosure policy (#173) +- GitHub issue templates and pull-request template (#175) + +### Changed + +- Migrated to AGP 9.1.0 + Gradle 9.4.1 with full KMP plugin support (#135) +- Moved all provider modules under `providers/` directory (#128) + +### Removed + +- `binary-compatibility-validator` (BCV) plugin from all modules (#150) +- `@LocalFlag` / `@RemoteFlag` annotations from public API ### Fixed -- `ConfigValues.observe()` not reacting to remote provider changes (#c0e0557) -- Xcode build: JAVA_HOME, FRAMEWORK_SEARCH_PATHS, and Swift module import (#1c488ca) +- Swift API: `ConfigParam.description` is now exposed as `.summary` (via `@ObjCName`), avoiding the SKIE-generated `description_` workaround for the `NSObject.description()` collision +- `ConfigValues.observe()` not reacting to remote provider changes +- Xcode build: `JAVA_HOME`, `FRAMEWORK_SEARCH_PATHS`, and Swift module import - `@MainActor` and `Sendable` conformance in `FeatureFlags.swift` (#85) +- `FirebaseConfigValueProvider.fetch()` now wraps `RuntimeException` in `FetchException` (#151) +- License mismatch: use MIT in all POM declarations (#174) +- Stale artifact IDs in quick-start docs (#179) -[Unreleased]: https://github.com/androidbroadcast/Featured/compare/HEAD...HEAD +[Unreleased]: https://github.com/androidbroadcast/Featured/compare/v1.0.0-Beta1...HEAD +[1.0.0-Beta1]: https://github.com/androidbroadcast/Featured/releases/tag/v1.0.0-Beta1 diff --git a/core/src/commonMain/kotlin/dev/androidbroadcast/featured/ConfigParam.kt b/core/src/commonMain/kotlin/dev/androidbroadcast/featured/ConfigParam.kt index 10d709e..6a465af 100644 --- a/core/src/commonMain/kotlin/dev/androidbroadcast/featured/ConfigParam.kt +++ b/core/src/commonMain/kotlin/dev/androidbroadcast/featured/ConfigParam.kt @@ -1,7 +1,9 @@ @file:Suppress("unused") +@file:OptIn(kotlin.experimental.ExperimentalObjCName::class) package dev.androidbroadcast.featured +import kotlin.native.ObjCName import kotlin.reflect.KClass /** @@ -44,6 +46,7 @@ public class ConfigParam * An optional description for the configuration parameter. * This can be used to provide additional context or information about the parameter. */ + @property:ObjCName("summary") public val description: String? = null, /** * Category or group name for organizing related parameters. diff --git a/featured-bom/build.gradle.kts b/featured-bom/build.gradle.kts index c6a4e69..9bd2fff 100644 --- a/featured-bom/build.gradle.kts +++ b/featured-bom/build.gradle.kts @@ -20,7 +20,9 @@ dependencies { api(project(":featured-compose")) api(project(":featured-registry")) api(project(":featured-debug-ui")) + api(project(":featured-testing")) api(project(":featured-gradle-plugin")) + api(project(":featured-lint-rules")) api(project(":featured-platform")) api(project(":featured-detekt-rules")) diff --git a/gradle.properties b/gradle.properties index 7ddc139..c4166f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -36,7 +36,7 @@ android.r8.strictInputValidation=true android.proguard.failOnMissingFiles=true # Publishing -VERSION_NAME=0.1.0-SNAPSHOT +VERSION_NAME=1.0.0-Beta1 # Dokka org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled