Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENG-36 Feature flag pattern. See README.md for usage #2648

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ It is crucial to have `Netlify` functions running locally to work with anything
- Treasury page
- Payments feature

## Environmental feature flags

### Setup

During development, add a flag in .env file. It can be of any data type but usually a boolean:

FEATURE_1=false

In code, use following code for code branching:

if (FeatureFlags.instance?.get('FEATURE_1') === true) {
// executed with FEATURE_1=true,
} else {
// executed with FEATURE_1=false,
}

### Testing

Change the value of the flag by adding params on home page:

https://app.dev.decentdao.org?FEATURE_1=true

From then, the flag holds the value from the URL param until app is refreshed

### Deployment and after

Deployment can ship with the flag turned off in .env file.

Change the value in .env file after the feature is completed and thouroughly tested.

Once code under the feature flag has been proven reliable, remove the feature flag and dead code from code base.

## Subgraph

We're using `Subgraph` to index certain "metadata" events to simplify data fetching from application site.
Expand Down
19 changes: 19 additions & 0 deletions src/helpers/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface IFeatureFlags {
set(key: string, value: any): void; // set from URL params
get(key: string): any;
}

export class FeatureFlags {
static instance?: IFeatureFlags;
}

export class EnvironmentFeatureFlags implements IFeatureFlags {
urlFlags: { [key: string]: any } = {};
set(key: string, value: any): void {
this.urlFlags[key] = value;
}

get(key: string): any {
return this.urlFlags[key] ?? import.meta.env[key];
}
}
5 changes: 4 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import '@fontsource/space-mono';
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import { RouterProvider, useSearchParams } from 'react-router-dom';

Check warning on line 4 in src/main.tsx

View workflow job for this annotation

GitHub Actions / lint

'useSearchParams' is defined but never used
import './assets/css/Markdown.css';
import './assets/css/sentry.css';
import './assets/css/Toast.css';
import './insights';
import { EnvironmentFeatureFlags, FeatureFlags } from './helpers/featureFlags';
import { runMigrations } from './hooks/utils/cache/runMigrations';
import { useNetworkConfigStore } from './providers/NetworkConfig/useNetworkConfigStore';
import Providers from './providers/Providers';
Expand All @@ -25,6 +26,8 @@
async function initializeApp() {
await runMigrations();

FeatureFlags.instance = new EnvironmentFeatureFlags();

const root = document.getElementById('root');
if (root !== null) {
ReactDOM.createRoot(root).render(
Expand Down
7 changes: 7 additions & 0 deletions src/pages/home/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Box, Flex, Hide, Show, Text } from '@chakra-ui/react';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import { DAOSearch } from '../../components/ui/menus/DAOSearch';
import { FeatureFlags } from '../../helpers/featureFlags';
import { useFractal } from '../../providers/App/AppProvider';
import { useDaoInfoStore } from '../../store/daoInfo/useDaoInfoStore';
import { GettingStarted } from './GettingStarted';
Expand All @@ -19,6 +21,11 @@ export default function HomePage() {
}
}, [safe?.address, action]);

const [searchParams] = useSearchParams();
searchParams.forEach((value, key) => {
FeatureFlags.instance?.set(key, value);
});

return (
<Flex
direction="column"
Expand Down
Loading