Skip to content
This repository has been archived by the owner on Sep 17, 2024. It is now read-only.

Commit

Permalink
feat(FF): implements a quick feature flag feature to disable as we wa…
Browse files Browse the repository at this point in the history
…nt flows (and other feature...)

Signed-off-by: reslene <reslene@numary.com>
  • Loading branch information
reslene committed May 4, 2023
1 parent 5bca9a0 commit c8664c6
Show file tree
Hide file tree
Showing 31 changed files with 247 additions and 72 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ OTEL_TRACES_EXPORTER_ZIPKIN_ENDPOINT=http://localhost:9411/api/v2/spans
UNSECURE_COOKIES=1
// from ci
VERSION=develop
FEATURES_DISABLED="workflows,instances,payments" // See Feature Flag section
```

```sh
Expand All @@ -39,6 +40,14 @@ This starts your app in development mode, rebuilding assets on file changes.

If you need to run open-tel use `docker compose up` and change OTEL_TRACES to 1.


## Feature flag
Features can be disabled by setting one or more of the feature string into FEATURES_DISABLED env var. String must be separated by a comma.

List can be found inside `app/src/service.ts` (`enum FEATURES`)

Note that if FEATURES_DISABLED is not given, all features will be enabled.

## Deployment

```sh
Expand Down
8 changes: 7 additions & 1 deletion app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ export const loader: LoaderFunction = async ({ request }) => {
await withSession(request, async () => {
const sessionHolder = decrypt<Authentication>(cookie);
const payload = getJwtPayload(sessionHolder);
const featuresDisabled = get(process, 'env.FEATURES_DISABLED', '').split(
','
);
const user = await getCurrentUser(
openIdConfig,
sessionHolder.access_token
Expand All @@ -108,6 +111,7 @@ export const loader: LoaderFunction = async ({ request }) => {
};

return {
featuresDisabled,
metas: {
origin: REDIRECT_URI,
openIdConfig,
Expand Down Expand Up @@ -277,7 +281,8 @@ const Document = withEmotionCache(
// https://remix.run/api/conventions#default-export
// https://remix.run/api/conventions#route-filenames
export default function App() {
const { metas, currentUser } = useLoaderData();
const { metas, currentUser, featuresDisabled } =
useLoaderData<ServiceContext>() as ServiceContext;
const { t } = useTranslation();
const [loading, _load, stopLoading] = useOpen(true);
const [feedback, setFeedback] = useState({
Expand Down Expand Up @@ -340,6 +345,7 @@ export default function App() {
) : (
<ServiceContext.Provider
value={{
featuresDisabled,
api: new ReactApiClient(),
currentUser,
metas,
Expand Down
3 changes: 3 additions & 0 deletions app/routes/accounts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoun
import AccountList from '~/src/components/Wrappers/Lists/AccountList/AccountList';
import { Filters } from '~/src/components/Wrappers/Table/Filters/filters';
import FiltersBar from '~/src/components/Wrappers/Table/Filters/FiltersBar';
import { FEATURES } from '~/src/contexts/service';
import { TableContext } from '~/src/contexts/table';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor } from '~/src/types/generic';
import { Account } from '~/src/types/ledger';
import { SearchBody, SearchPolicies, SearchTargets } from '~/src/types/search';
Expand Down Expand Up @@ -63,6 +65,7 @@ export function ErrorBoundary({ error }: { error: Error }) {

export default function Index() {
const accounts = useLoaderData<Cursor<Account>>();
useFeatureFlag(FEATURES.ACCOUNTS);

return (
<Page id={accountsConfig.id}>
Expand Down
4 changes: 4 additions & 0 deletions app/routes/apps/$appName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import {
paymentTypeColorMap,
} from '~/src/components/Wrappers/StatusChip/maps';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { useService } from '~/src/hooks/useService';
import i18n from '~/src/translations';
import { Chart, ChartTypes } from '~/src/types/chart';
Expand Down Expand Up @@ -202,6 +204,8 @@ export default function Index() {
}>();
const navigate = useNavigate();
const { api, snackbar } = useService();
useFeatureFlag(FEATURES.APPS);

const provider = lowerCaseAllWordsExceptFirstLetter(connector.provider);
const onDelete = async (name: string) => {
try {
Expand Down
3 changes: 3 additions & 0 deletions app/routes/connectors/apps/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoun
import ShowListAction from '~/src/components/Wrappers/Lists/Actions/ShowListAction';
import ProviderPicture from '~/src/components/Wrappers/ProviderPicture';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Connector } from '~/src/types/connectorsConfig';
import { API_PAYMENT } from '~/src/utils/api';
import { createApiClient } from '~/src/utils/api.server';
Expand Down Expand Up @@ -47,6 +49,7 @@ export default function Index() {
const { t } = useTranslation();
const connectorsData = useLoaderData<Connector[]>();
const navigate = useNavigate();
useFeatureFlag(FEATURES.APPS);

return (
<Box mt={2}>
Expand Down
3 changes: 3 additions & 0 deletions app/routes/connectors/oauth-clients/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { OAUTH_CLIENT_ROUTE } from '~/src/components/Layout/routes';
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import ShowListAction from '~/src/components/Wrappers/Lists/Actions/ShowListAction';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { OAuthClient } from '~/src/types/oauthClient';
import { API_AUTH } from '~/src/utils/api';
import { createApiClient } from '~/src/utils/api.server';
Expand Down Expand Up @@ -53,6 +55,7 @@ export const loader: LoaderFunction = async ({ request }) => {
export default function Index() {
const { t } = useTranslation();
const oAuthClients = useLoaderData() as OAuthClient[];
useFeatureFlag(FEATURES.O_AUTH_CLIENTS);

return (
<Box mt={2}>
Expand Down
3 changes: 3 additions & 0 deletions app/routes/connectors/webhooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoun
import ShowListAction from '~/src/components/Wrappers/Lists/Actions/ShowListAction';
import Table from '~/src/components/Wrappers/Table';
import WebhookStatus from '~/src/components/Wrappers/WebhookStatus';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor } from '~/src/types/generic';
import { Webhook } from '~/src/types/webhook';
import { API_WEBHOOK } from '~/src/utils/api';
Expand Down Expand Up @@ -54,6 +56,7 @@ export default function Index() {
const { t } = useTranslation();
const cursor = useLoaderData() as unknown as Cursor<Webhook>;
const [webhooks, setWebhooks] = useState<Webhook[]>(cursor.data);
useFeatureFlag(FEATURES.WEBHOOKS);

return (
<Box mt={2}>
Expand Down
1 change: 1 addition & 0 deletions app/routes/flows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function Index() {
const navigate = useNavigate();
const location = useLocation();
const handleActive = (path: string) => location.pathname.includes(path);

const config = [
{
active: handleActive('workflows'),
Expand Down
15 changes: 15 additions & 0 deletions app/routes/flows/instances/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import { Session } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import { LoaderFunction } from '@remix-run/server-runtime';

import { instances as instancesConfig } from '~/src/components/Layout/routes';
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import InstanceList from '~/src/components/Wrappers/Lists/InstanceList';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { OrchestrationInstance } from '~/src/types/orchestration';
import { API_ORCHESTRATION } from '~/src/utils/api';
import { createApiClient } from '~/src/utils/api.server';
Expand Down Expand Up @@ -36,10 +40,21 @@ export const loader: LoaderFunction = async ({ request }) => {
return handleResponse(await withSession(request, handleData));
};

export function ErrorBoundary({ error }: { error: Error }) {
return (
<ComponentErrorBoundary
id={instancesConfig.id}
title="pages.instances.title"
error={error}
/>
);
}

export default function Index() {
const instances = useLoaderData<
OrchestrationInstance[]
>() as unknown as OrchestrationInstance[];
useFeatureFlag(FEATURES.INSTANCES);

return (
<Box mt={2}>
Expand Down
19 changes: 18 additions & 1 deletion app/routes/flows/workflows/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ import { useTranslation } from 'react-i18next';

import { Chip, Date, Row } from '@numaryhq/storybook';

import { WORKFLOW_ROUTE } from '~/src/components/Layout/routes';
import {
WORKFLOW_ROUTE,
workflows as workflowsConfig,
} from '~/src/components/Layout/routes';
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import ShowListAction from '~/src/components/Wrappers/Lists/Actions/ShowListAction';
import { orchestrationStagesIconMap } from '~/src/components/Wrappers/StatusChip/maps';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { OrchestrationWorkflow } from '~/src/types/orchestration';
import { API_ORCHESTRATION } from '~/src/utils/api';
import { createApiClient } from '~/src/utils/api.server';
Expand All @@ -25,6 +31,16 @@ export const meta: MetaFunction = () => ({
description: 'Workflow list',
});

export function ErrorBoundary({ error }: { error: Error }) {
return (
<ComponentErrorBoundary
id={workflowsConfig.id}
title="pages.workflows.title"
error={error}
/>
);
}

export const loader: LoaderFunction = async ({ request }) => {
async function handleData(session: Session) {
const workflows = await (
Expand All @@ -47,6 +63,7 @@ export const loader: LoaderFunction = async ({ request }) => {
export default function Index() {
const { t } = useTranslation();
const workflows = useLoaderData<OrchestrationWorkflow<any>[]>();
useFeatureFlag(FEATURES.WORKFLOWS);

return (
<Box mt={2}>
Expand Down
4 changes: 4 additions & 0 deletions app/routes/instances/$instanceId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {
orchestrationInstanceStatusIconMap,
} from '~/src/components/Wrappers/StatusChip/maps';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import {
FlowInstance,
OrchestrationInstanceStatuses,
Expand Down Expand Up @@ -126,6 +128,8 @@ const nodeTypes = {

export default function Index() {
const { t } = useTranslation();
useFeatureFlag(FEATURES.INSTANCES);

const rawInstance = useLoaderData<FlowInstance>() as unknown as FlowInstance;
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [next, setNext] = useState(5);
Expand Down
3 changes: 3 additions & 0 deletions app/routes/ledgers/$ledgerId/accounts/$accountId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import IconTitlePage from '~/src/components/Wrappers/IconTitlePage';
import TransactionList from '~/src/components/Wrappers/Lists/TransactionList';
import Metadata from '~/src/components/Wrappers/Metadata';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Chart } from '~/src/types/chart';
import { Cursor } from '~/src/types/generic';
import {
Expand Down Expand Up @@ -150,6 +152,7 @@ export default function Index() {
const fetcher = useFetcher();
const account = fetcher.data?.account || loaderData.account;
const { palette } = useTheme();
useFeatureFlag(FEATURES.ACCOUNTS);

const sync = () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Expand Down
3 changes: 3 additions & 0 deletions app/routes/ledgers/$ledgerId/logs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { ledgers } from '~/src/components/Layout/routes';
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import IconTitlePage from '~/src/components/Wrappers/IconTitlePage';
import LedgerLogList from '~/src/components/Wrappers/Lists/LedgerLogList';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor } from '~/src/types/generic';
import { LedgerLog, Transaction } from '~/src/types/ledger';
import { API_LEDGER } from '~/src/utils/api';
Expand Down Expand Up @@ -65,6 +67,7 @@ export default function Index() {
const { ledgerId: id } = useParams<{
ledgerId: string;
}>();
useFeatureFlag(FEATURES.LEDGERS);

return (
<Page
Expand Down
3 changes: 3 additions & 0 deletions app/routes/ledgers/$ledgerId/transactions/$transactionId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import IconTitlePage from '~/src/components/Wrappers/IconTitlePage';
import PaymentList from '~/src/components/Wrappers/Lists/PaymentList';
import TransactionList from '~/src/components/Wrappers/Lists/TransactionList/TransactionList';
import Metadata from '~/src/components/Wrappers/Metadata';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor, ObjectOf } from '~/src/types/generic';
import {
LedgerResources,
Expand Down Expand Up @@ -116,6 +118,7 @@ export default function Index() {
const { t } = useTranslation();
const fetcher = useFetcher();
const transaction = fetcher.data || loaderData;
useFeatureFlag(FEATURES.TRANSACTIONS);

const sync = () => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
Expand Down
3 changes: 3 additions & 0 deletions app/routes/ledgers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import ShowListAction from '~/src/components/Wrappers/Lists/Actions/ShowListAction';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { API_LEDGER } from '~/src/utils/api';
import { createApiClient } from '~/src/utils/api.server';
import { handleResponse, withSession } from '~/src/utils/auth.server';
Expand Down Expand Up @@ -55,6 +57,7 @@ export const loader: LoaderFunction = async ({ request }) => {
export default function Index() {
const { t } = useTranslation();
const ledgers = useLoaderData<string[]>();
useFeatureFlag(FEATURES.LEDGERS);

return (
<Page id={ledgersConfig.id}>
Expand Down
3 changes: 3 additions & 0 deletions app/routes/oauth-clients/$oAuthClientId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoun
import IconTitlePage from '~/src/components/Wrappers/IconTitlePage';
import Modal from '~/src/components/Wrappers/Modal';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { useService } from '~/src/hooks/useService';
import { OAuthClient, OAuthSecret } from '~/src/types/oauthClient';
import { API_AUTH } from '~/src/utils/api';
Expand Down Expand Up @@ -87,6 +89,7 @@ export default function Index() {
);
const navigate = useNavigate();
const { typography } = useTheme();
useFeatureFlag(FEATURES.O_AUTH_CLIENTS);

const renderUris = (key: string, color?: ColorVariants) => {
const uris = get(oAuthClient, key, []) || [];
Expand Down
3 changes: 3 additions & 0 deletions app/routes/oauth-clients/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { LoadingButton, Row, TextArea, TextField } from '@numaryhq/storybook';
import { getRoute, OAUTH_CLIENT_ROUTE } from '~/src/components/Layout/routes';
import Modal from '~/src/components/Wrappers/Modal';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { useService } from '~/src/hooks/useService';
import i18n from '~/src/translations';
import { OAuthClient, OAuthSecret } from '~/src/types/oauthClient';
Expand Down Expand Up @@ -95,6 +97,7 @@ export default function Index() {
resolver: yupResolver(schema),
mode: 'onTouched',
});
useFeatureFlag(FEATURES.O_AUTH_CLIENTS);

const onSave = async () => {
const validated = await trigger('name');
Expand Down
1 change: 1 addition & 0 deletions app/routes/overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const meta: MetaFunction = () => ({
export function ErrorBoundary() {
return <Overview />;
}

const getLedgersStats = async (ledgersList: string[], api: ApiClient) => {
const ledgers = [] as any;
const firstThreeLedgers = take(ledgersList, 3);
Expand Down
3 changes: 3 additions & 0 deletions app/routes/payments/$paymentId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
paymentTypeIconMap,
} from '~/src/components/Wrappers/StatusChip/maps';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor } from '~/src/types/generic';
import { Transaction } from '~/src/types/ledger';
import { Payment, PaymentDetail } from '~/src/types/payment';
Expand Down Expand Up @@ -92,6 +94,7 @@ export default function PaymentDetails() {
const { payment, transactions } =
useLoaderData<PaymentDetailData>() as unknown as PaymentDetailData;
const { t } = useTranslation();
useFeatureFlag(FEATURES.PAYMENTS);

const renderTableItem = (
key: string,
Expand Down
3 changes: 3 additions & 0 deletions app/routes/payments/accounts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { paymentsAccounts as paymentsAccountsConfig } from '~/src/components/Lay
import ComponentErrorBoundary from '~/src/components/Wrappers/ComponentErrorBoundary';
import ProviderPicture from '~/src/components/Wrappers/ProviderPicture';
import Table from '~/src/components/Wrappers/Table';
import { FEATURES } from '~/src/contexts/service';
import { useFeatureFlag } from '~/src/hooks/useFeatureFlag';
import { Cursor } from '~/src/types/generic';
import { Account } from '~/src/types/payment';
import { API_PAYMENT } from '~/src/utils/api';
Expand Down Expand Up @@ -46,6 +48,7 @@ export const loader: LoaderFunction = async ({ request }) => {
export default function Index() {
const accounts = useLoaderData<Account[]>();
const { t } = useTranslation();
useFeatureFlag(FEATURES.PAYMENTS_ACCOUNT);

return (
<Page id={paymentsAccountsConfig.id}>
Expand Down
Loading

0 comments on commit c8664c6

Please sign in to comment.