Skip to content

Commit

Permalink
🪟 🔧 Allow overwriting experiments and features during development (#2…
Browse files Browse the repository at this point in the history
…0843)

* Allow overwriting experiments via special file

* Allow feature overwriting via .features.dev

* Adjust to discussion
  • Loading branch information
Tim Roes authored Jan 17, 2023
1 parent 3c39e0c commit f104508
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
14 changes: 9 additions & 5 deletions airbyte-webapp/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

*.iml
/.idea

.npmrc
# Environment overwrites
.env.development
.env.production
.env.local
.env.development.local
.env.test.local
.env.production.local

# Local overwrites
.experiments.json

storybook-static/

Expand Down
4 changes: 2 additions & 2 deletions airbyte-webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"scripts": {
"prepare": "cd .. && husky install airbyte-webapp/.husky",
"prestart": "npm run generate-client",
"start": "craco start",
"start": "node -r ./scripts/dev-overwrites.js ./node_modules/.bin/craco start",
"prestart:cloud": "npm run generate-client",
"start:cloud": "AB_ENV=${AB_ENV-frontend-dev} node -r ./scripts/environment.js ./node_modules/.bin/craco start",
"start:cloud": "AB_ENV=${AB_ENV-frontend-dev} node -r ./scripts/environment.js -r ./scripts/dev-overwrites.js ./node_modules/.bin/craco start",
"prebuild": "npm run generate-client",
"build": "BUILD_PATH='./build/app' craco build",
"pretest": "npm run generate-client",
Expand Down
14 changes: 14 additions & 0 deletions airbyte-webapp/scripts/dev-overwrites.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const fs = require("fs");
const path = require("path");

const EXPERIMENTS_FILE = path.resolve(__dirname, "../.experiments.json");

if (fs.existsSync(EXPERIMENTS_FILE)) {
console.log("\nOverwriting experiments from .experiments.json ...");
const overwrites = require(EXPERIMENTS_FILE);

if (Object.keys(overwrites).length) {
console.log(`Overwriting experiments with the following values:\n\n${JSON.stringify(overwrites, null, 2)}`);
process.env.REACT_APP_EXPERIMENT_OVERWRITES = JSON.stringify(overwrites);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { createContext, useContext, useMemo } from "react";
import { useObservable } from "react-use";
import { EMPTY, Observable } from "rxjs";

const devOverwrites = process.env.REACT_APP_EXPERIMENT_OVERWRITES
? (JSON.parse(process.env.REACT_APP_EXPERIMENT_OVERWRITES) as Record<string, unknown>)
: {};

const experimentContext = createContext<ExperimentService | null>(null);

/**
Expand All @@ -15,7 +19,7 @@ export interface ExperimentService {
getExperimentChanges$<K extends keyof Experiments>(key: K): Observable<Experiments[K]>;
}

export function useExperiment<K extends keyof Experiments>(key: K, defaultValue: Experiments[K]): Experiments[K] {
function useExperimentHook<K extends keyof Experiments>(key: K, defaultValue: Experiments[K]): Experiments[K] {
const experimentService = useContext(experimentContext);
// Get the observable for the changes of the experiment or an empty (never emitting) observable in case the
// experiment service doesn't exist (e.g. we're running in OSS or it failed to initialize)
Expand All @@ -25,4 +29,17 @@ export function useExperiment<K extends keyof Experiments>(key: K, defaultValue:
return useObservable(onChanges$, experimentService?.getExperiment(key, defaultValue) ?? defaultValue);
}

function useExperimentWithOverwrites<K extends keyof Experiments>(
key: K,
defaultValue: Experiments[K]
): Experiments[K] {
// Load the regular experiments value via the prod hook
const value = useExperimentHook(key, defaultValue);
// Use the overwrite value if it's available, otherwise the proper value
return key in devOverwrites ? (devOverwrites[key] as Experiments[K]) : value;
}

// Allow overwriting values via the .experiments.dev file (and thus the REACT_APP_EXPERIMENT_OVERWRITES env variable) only during development
export const useExperiment = process.env.NODE_ENV === "development" ? useExperimentWithOverwrites : useExperimentHook;

export const ExperimentProvider = experimentContext.Provider;

0 comments on commit f104508

Please sign in to comment.