Artsy releases the app on a 2-week cadence 🔐, submitting the Monday after a sprint starts.
For very small features (like adding a single new label to a view) we simply open a pull request.
For bigger features that will take longer than a sprint, we put development behind a feature flags in order to be able to test our work without making our in-progress work visible to our users. This way we can toggle the flag off and on and thoroughly test the feature before releasing it.
- Feature flags
We want the ability to turn a feature off remotely if something goes wrong.
We do that by adding flag in our remote feature configuration service, Echo
This way we can independently of eigen turn features on and off, which can come in handy in case of bad case scenarios for example.
A feature flag in eigen is a boolean value that decides whether a particular feature should be available in the app.
Whether this value is 'true' or 'false' depends on two things:
- Is the feature ready for release
- Has the feature been added to echo.
To illustrate how these two work together, let's go through an example together.
Let's say you want to add a new feature, called "Marketing Banners".
We'll add a new feature flag called ARShowMarketingBanner
(this naming is a convention we borrow from Objective-C).
First you need to add the new feature block in src/app/store/config/features.ts
AROptionsNewFirstInquiry: {
readyForRelease: true,
echoFlagKey: "AROptionsNewFirstInquiry",
},
+ ARShowMarketingBanner: {
+ readyForRelease: false,
+ description: "Show new marketing banners",
+ showInDevMenu: true,
+ },
AROptionsInquiryCheckout: {
readyForRelease: false,
description: "Enable inquiry checkout",
showInDevMenu: true,
}
The description
property is what makes it possible to override the feature flag from the Dev Menu.
We also need to add a flag in Echo, our remote feature flags configuration service. Here is an example PR for how to do that. The general feature development flow around adding a flag and updating Echo is like so:
- Add flag to eigen,
readyForRelease: false
- Add flag to echo, with
false
- Finish dev
- Change eigen
readyForRelease: true
- When the app version is released, swap echo flag to
true
whenever we want users to get it
After adding the echo key, and the PR is merged, update you local copy of echo by running ./scripts/setup/update-echo
.
With this setup, the echo flag will be the source of truth for whether or not to enable the feature.
you can to call it by using the useFeatureFlag
hook.
+ const showBanner = useFeatureFlag("ARShowMarketingBanner")
return (
<>
<TitleView />
<SummaryView />
+ { showBanner && <MarketingBanner /> }
<>
)
We also have unsafe_getFeatureFlag("ARShowMarketingBanner")
which is not recommended, for feature flags outside of functional react components.
This is marked as unsafe because it will not cause react components to re-render, but it safe to use in non-reactive contexts, like an onPress
handler.
To enable your feature on a physical or virtual device
-
Open the Dev Menu by pressing
command + control + z
on a mac. If this doesn't work:- Log in to the app (eg your artsy email)
- Enable Developer mode by going to Profile > About and tapping "Version" 7 times.
- See a notification "Developer mode enabled"
- Open the Dev Menu
- iOS: Do the shake gesture or press
command + control + z
- Android: Tap the same area of the screen several times
- iOS: Do the shake gesture or press
-
Toggle the feature flag to "Yes".
There is a utility method that can be used by tests that need to override a feature flag.
__globalStoreTestUtils__?.injectFeatureFlags({ ARShowMarketingBanner: true })
You can find documentation about how to do QA on the new shiny feature here 🔐.
There is also the general QA page here 🔐.
Your feature is ready for release 🎉
Let's go to src/app/store/config/features.ts
find our feature and set readyForRelease
to true
.
Consider also removing the entry from the Dev Menu if developers will no longer need to override the flag, by setting showInDevMenu to false.
ARShowMarketingBanner: {
- readyForRelease: false,
+ readyForRelease: true,
description: "Show new marketing banners",
- showInDevMenu: true,
+ showInDevMenu: false,
},
Alternatively, or at some point in the future, you can simply delete the feature flag and all the conditional branches associated with it.
Then when you mark the feature as being ready for release you can link the feature to the echo flag by specifying the key.
ARShowMarketingBanner: {
- readyForRelease: false,
+ readyForRelease: true,
echoFlagKey: "ARShowMarketingBanner"
description: "Show new marketing banners",
},
Here is an example PR for how to do that.
Once the feature flag is no longer needed:
- Removed it from the
src/app/store/config/features.ts
file
AROptionsNewFirstInquiry: {
readyForRelease: true,
echoFlagKey: "AROptionsNewFirstInquiry",
},
- ARShowMarketingBanner: {
- readyForRelease: false,
- description: "Show new marketing banners",
- showInDevMenu: true,
- },
AROptionsInquiryCheckout: {
readyForRelease: false,
description: "Enable inquiry checkout",
showInDevMenu: true,
}
- Remove the
echoFlagKey
from echo: example. It is adviced to give it a few months buffer before doing that, so that all users can get the new version of the app with the flag removed.
Just ask in #practice-mobile slack channel, we are happy to assist!