fix(ci): fix firebase exception wrapping, missing ADR doc, and gitignore#149
fix(ci): fix firebase exception wrapping, missing ADR doc, and gitignore#149kirich1409 wants to merge 2 commits intomainfrom
Conversation
- FirebaseConfigValueProvider.fetch() was re-throwing RuntimeException directly instead of wrapping it in FetchException; only CancellationException should propagate unwrapped (coroutine cancellation semantics) - Create docs/adr/001-configvalues-multi-module.md referenced in mkdocs.yml nav but missing from the repo, causing Build Docs to abort in strict mode Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove /docs/adr/ from .gitignore so ADR files are versioned. Add docs/adr/001-configvalues-multi-module.md which was referenced in mkdocs.yml nav but missing, causing Build Docs to abort in strict mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Review Summary by QodoFix Firebase exception wrapping and add missing ADR documentation
WalkthroughsDescription• Fix Firebase exception handling to wrap RuntimeException in FetchException - Only CancellationException should propagate unwrapped for coroutine semantics • Add missing ADR 001 documentation file referenced in mkdocs.yml • Remove /docs/adr/ from .gitignore to enable version control of ADR files Diagramflowchart LR
A["FirebaseConfigValueProvider.fetch()"] -->|"catch CancellationException"| B["Propagate unwrapped"]
A -->|"catch other Exception"| C["Wrap in FetchException"]
D[".gitignore"] -->|"remove /docs/adr/"| E["Enable ADR versioning"]
F["mkdocs.yml reference"] -->|"add missing file"| G["docs/adr/001-configvalues-multi-module.md"]
File Changes1. providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewⓘ The new review experience is currently in Beta. Learn more |
There was a problem hiding this comment.
Pull request overview
Fixes CI failures by correcting Firebase Remote Config exception wrapping, restoring missing MkDocs ADR content, and ensuring docs ADRs aren’t ignored by git.
Changes:
- Update
FirebaseConfigValueProvider.fetch()to rethrow coroutine cancellation while wrapping other failures inFetchException. - Add the missing ADR doc referenced by
mkdocs.yml. - Stop ignoring
/docs/adr/so ADR docs are included in the repo and docs build.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| providers/firebase/src/main/kotlin/dev/androidbroadcast/featured/firebase/FirebaseConfigValueProvider.kt | Adjust exception handling so cancellation propagates and all other failures are wrapped consistently. |
| docs/adr/001-configvalues-multi-module.md | Adds ADR 001 content to satisfy MkDocs nav and document multi-module setup. |
| .gitignore | Removes rule that was excluding ADR docs from version control. |
| In multi-module Android/KMP projects, each feature module may declare its own `ConfigParam` flags. The question is how to compose these into a single `ConfigValues` instance that is shared across the app. | ||
|
|
||
| ## Decision | ||
|
|
||
| Each module declares its flags as top-level `ConfigParam` constants. A single `ConfigValues` instance is created at the app level (e.g., in the DI graph) by passing all params through the same providers. | ||
|
|
||
| The Gradle plugin generates a `FlagRegistrar` per module. The app module aggregates them via the generated `GeneratedFlagRegistry`, which collects every module's registrar at compile time. | ||
|
|
||
| Modules never create their own `ConfigValues`; they only declare params and read from the shared instance injected from the app layer. | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Flag namespacing is flat — param names must be unique across all modules. | ||
| - There is one set of local/remote providers for the whole app; per-module providers are not supported. | ||
| - The Gradle plugin enforces uniqueness and generates the aggregation boilerplate automatically. |
There was a problem hiding this comment.
The ADR’s “Decision” section describes flags as top-level ConfigParam constants and references an app-level GeneratedFlagRegistry. In this repo, flags are typically declared via the featured { } Gradle DSL and the plugin generates Generated{Local,Remote}Flags plus a per-module GeneratedFlagRegistrar; there doesn’t appear to be any GeneratedFlagRegistry type in the codebase. Please update the ADR to reflect the actual generated artifacts and how multi-module apps should wire things together (and avoid referencing non-existent symbols).
| In multi-module Android/KMP projects, each feature module may declare its own `ConfigParam` flags. The question is how to compose these into a single `ConfigValues` instance that is shared across the app. | |
| ## Decision | |
| Each module declares its flags as top-level `ConfigParam` constants. A single `ConfigValues` instance is created at the app level (e.g., in the DI graph) by passing all params through the same providers. | |
| The Gradle plugin generates a `FlagRegistrar` per module. The app module aggregates them via the generated `GeneratedFlagRegistry`, which collects every module's registrar at compile time. | |
| Modules never create their own `ConfigValues`; they only declare params and read from the shared instance injected from the app layer. | |
| ## Consequences | |
| - Flag namespacing is flat — param names must be unique across all modules. | |
| - There is one set of local/remote providers for the whole app; per-module providers are not supported. | |
| - The Gradle plugin enforces uniqueness and generates the aggregation boilerplate automatically. | |
| In multi-module Android/KMP projects, each feature module may declare its own flags via the `featured { }` Gradle DSL. The question is how to compose these generated flags into a single `ConfigValues` instance that is shared across the app. | |
| ## Decision | |
| Each module declares its flags in the `featured { }` Gradle DSL. The Gradle plugin generates module-scoped accessors such as `GeneratedLocalFlags` and `GeneratedRemoteFlags`, along with a per-module `GeneratedFlagRegistrar`. | |
| A single `ConfigValues` instance is created at the app level (for example, in the DI graph) and is wired using the set of `GeneratedFlagRegistrar` instances from the modules that participate in the app. There is no app-level generated `GeneratedFlagRegistry`; multi-module apps must explicitly include each module's generated registrar in their app wiring. | |
| Modules never create their own `ConfigValues`; they declare flags through the plugin-generated model and read from the shared instance injected from the app layer. | |
| ## Consequences | |
| - Flag namespacing is flat — flag names must be unique across all modules. | |
| - There is one set of local/remote providers for the whole app; per-module providers are not supported. | |
| - The Gradle plugin generates `GeneratedLocalFlags`, `GeneratedRemoteFlags`, and a `GeneratedFlagRegistrar` for each module, while the app is responsible for wiring the relevant registrars together. |
|
|
||
| - Flag namespacing is flat — param names must be unique across all modules. | ||
| - There is one set of local/remote providers for the whole app; per-module providers are not supported. | ||
| - The Gradle plugin enforces uniqueness and generates the aggregation boilerplate automatically. |
There was a problem hiding this comment.
The consequences list says “The Gradle plugin enforces uniqueness” and “generates the aggregation boilerplate automatically”. From the current plugin implementation, resolveFeatureFlags just serializes each module’s flags and scanAllLocalFlags only depends on per-module tasks; there’s no cross-module duplicate-key validation or generated app-level aggregator. Please reword these bullets to match actual behavior (or add explicit validation/generation if that’s intended).
| - The Gradle plugin enforces uniqueness and generates the aggregation boilerplate automatically. | |
| - The Gradle plugin currently serializes each module's declared flags, but it does not enforce cross-module uniqueness or generate an app-level aggregation boilerplate automatically. |
| try { | ||
| task.await() | ||
| } catch (e: RuntimeException) { | ||
| } catch (e: CancellationException) { | ||
| throw e | ||
| } catch (e: Exception) { | ||
| throw FetchException("Firebase Remote Config fetch failed", e) |
There was a problem hiding this comment.
fetch() now treats CancellationException specially (rethrowing it), but the firebase provider tests only assert that failures are wrapped in FetchException. Please add a unit test covering the cancellation path (e.g., cancelled Task or coroutine cancellation) to ensure cancellation is not accidentally wrapped in FetchException in the future.
Summary
Three CI failures blocking all open PRs (#143, #144, #145):
Tests & Coverage —
FirebaseConfigValueProvider.fetch()was catchingRuntimeExceptionand re-throwing it directly, soRuntimeException("Network unavailable")never got wrapped inFetchException. OnlyCancellationExceptionshould propagate unwrapped (coroutine cancellation semantics).Build Docs —
docs/adr/001-configvalues-multi-module.mdwas referenced inmkdocs.ymlnav but both missing from repo AND listed in.gitignore. Removed the ignore rule and added the ADR file.Analyze Kotlin (CodeQL) — secondary failure caused by the build failures above; should resolve automatically.
Test plan
Tests & CoveragepassesBuild DocspassesAnalyze Kotlinpasses🤖 Generated with Claude Code