Skip to content

fix(remote-config, ios): ensure fetchActivate() match fetch() + activate() behavior#9095

Draft
russellwheatley wants to merge 2 commits into
mainfrom
remote-config-7779
Draft

fix(remote-config, ios): ensure fetchActivate() match fetch() + activate() behavior#9095
russellwheatley wants to merge 2 commits into
mainfrom
remote-config-7779

Conversation

@russellwheatley

@russellwheatley russellwheatley commented Jul 9, 2026

Copy link
Copy Markdown
Member

Description

On iOS, remoteConfig().fetchAndActivate() always resolved true, even when nothing new was fetched/activated. This is inconsistent with a separate fetch() + activate() call, and inconsistent with Android's fetchAndActivate(), which correctly resolves false when there's nothing new.

Root cause: the iOS implementation used the Firebase iOS SDK's -[FIRRemoteConfig fetchAndActivateWithCompletionHandler:] and mapped its FIRRemoteConfigFetchAndActivateStatus result to a boolean (SuccessFetchedFromRemotetrue, else → false). That status only reflects whether the fetch succeeded — it ignores the changed BOOL returned by the SDK's own activateWithCompletion:, which is the actual "did activation change anything" signal. Since activateWithCompletion: essentially never errors in modern SDK versions, the status was almost always SuccessFetchedFromRemote, so RNFB always resolved true.

Fix: fetchAndActivate: in RNFBConfigModule.mm now performs the fetch + activate itself (mirroring what the SDK does internally) and resolves with the changed BOOL from activateWithCompletion:, using the same "already activated" error-handling special case already present in RNFB's own activate: method. This matches Android's semantics and iOS's own activate() semantics.

Related issues

fixes #7779

Release Summary

fix(remote-config, ios): fetchAndActivate() now correctly resolves false when there is nothing new to activate, matching Android and matching fetch() + activate().

Test Plan

Added 3 new e2e tests to packages/remote-config/e2e/config.e2e.js (in the existing fetchAndActivate() describe block), designed as regression tests that would have failed against the old iOS behavior:

  1. returns false when there is nothing new to activate — calls fetchAndActivate() twice in a row with no server-side template change; second call must resolve false.
  2. is consistent with fetch() followed by activate() — asserts fetchAndActivate() agrees with a separate fetchConfig() + activate() call when nothing changed.
  3. returns true only once new remote values have actually been fetched and activated — publishes a new remote config parameter via the existing cloud-function test helper (FirebaseHelpers.updateRemoteConfigTemplate / testFunctionRemoteConfigUpdateV2), then polls fetchAndActivate() for up to 60s (template publish → fetch-backend propagation isn't instant) asserting it eventually returns true and the new value is visible via getValue(). Cleans up the published parameter afterwards.

Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
    • Yes
  • My change supports the following platforms;
    • Android (unchanged, regression-tested for parity)
    • iOS
    • Other (macOS, web — validates test logic against firebase-js-sdk)
  • My change includes tests;
    • e2e tests added or updated in packages/**/e2e
    • jest tests added or updated in packages/**/__tests__
  • I have updated TypeScript types that are affected by my change. (n/a — no public API/type change)
  • This is a breaking change;
    • Yes
    • No

Think react-native-firebase is great? Please consider supporting the project with any of the below:

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an inconsistency in the fetchAndActivate() method for Firebase Remote Config on iOS. Previously, the method would always resolve as true if the fetch operation succeeded, regardless of whether new configuration values were actually applied. The changes ensure that fetchAndActivate() now accurately reports whether new Remote Config values were activated, bringing its behavior in line with Android and the explicit fetch() followed by activate() workflow. This provides a more reliable and predictable API for developers.

Highlights

  • iOS fetchAndActivate() Behavior Fix: Resolved an issue on iOS where fetchAndActivate() incorrectly returned true even when no new Remote Config values were actually activated. The method now accurately reflects whether new values were applied, aligning its behavior with Android and the fetch() + activate() pattern.
  • Improved fetchAndActivate() Implementation: The iOS implementation of fetchAndActivate() was refactored to explicitly perform a fetch operation followed by an activate operation. This change allows for precise control over the return value, ensuring it reports true only when configuration values have genuinely changed and been activated.
  • Enhanced End-to-End Testing: Added comprehensive end-to-end tests to validate the corrected fetchAndActivate() behavior. These tests cover scenarios where no new values are activated (expecting false), consistency with separate fetch() and activate() calls, and proper true return when new values are indeed fetched and activated.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue on iOS where fetchAndActivate() incorrectly resolved to true even when no new remote config values were activated. The iOS implementation has been refactored to perform a fetch followed by an explicit activation, ensuring its behavior matches Android and the separate fetch() and activate() calls. Additionally, comprehensive end-to-end regression tests have been added to verify this behavior. The feedback recommends simplifying redundant RCTConvert calls in the Objective-C++ code to improve readability.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/remote-config/ios/RNFBConfig/RNFBConfigModule.mm Outdated
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 34.37500% with 21 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.65%. Comparing base (3933b45) to head (b5c6b70).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #9095      +/-   ##
============================================
+ Coverage     58.61%   58.65%   +0.04%     
- Complexity     1616     1617       +1     
============================================
  Files           503      503              
  Lines         39178    39196      +18     
  Branches       5807     5779      -28     
============================================
+ Hits          22962    22987      +25     
  Misses        14811    14811              
+ Partials       1405     1398       -7     
Flag Coverage Δ
android-native 53.57% <ø> (+0.01%) ⬆️
e2e-ts-android 50.00% <ø> (+0.03%) ⬆️
e2e-ts-ios 53.93% <34.38%> (+0.04%) ⬆️
e2e-ts-macos 41.51% <ø> (+0.03%) ⬆️
ios-native 53.93% <34.38%> (+0.04%) ⬆️
jest 49.58% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread packages/remote-config/ios/RNFBConfig/RNFBConfigModule.mm Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[🐛] 🔥 remote config method fetchAndActivate() inconsistent with method fetch() and then activate() on iOS only

2 participants