Support a `local` channel for local development
In local development, the Nimbus sidecar isn't available, so we just explicitly load the default values for the `local` channel.
This commit is contained in:
Родитель
56bea1a528
Коммит
0d52cb1510
|
@ -1,6 +1,7 @@
|
|||
about:
|
||||
description: Nimbus Feature Manifest for Monitor Web testing
|
||||
channels:
|
||||
- local
|
||||
- staging
|
||||
- production
|
||||
features:
|
||||
|
@ -12,6 +13,8 @@ features:
|
|||
type: Boolean
|
||||
default: false
|
||||
defaults:
|
||||
- channel: local
|
||||
value: { "enabled": true }
|
||||
- channel: staging
|
||||
value: { "enabled": true }
|
||||
- channel: production
|
||||
|
|
|
@ -7,6 +7,7 @@ import { logger } from "./logging";
|
|||
import {
|
||||
ExperimentData,
|
||||
defaultExperimentData,
|
||||
localExperimentData,
|
||||
} from "../../../telemetry/generated/nimbus/experiments";
|
||||
import { ExperimentationId } from "./getExperimentationId";
|
||||
|
||||
|
@ -25,34 +26,35 @@ export async function getExperiments(params: {
|
|||
locale: string;
|
||||
countryCode: string;
|
||||
}): Promise<ExperimentData> {
|
||||
if (["stage", "production"].includes(process.env.APP_ENV ?? "local")) {
|
||||
const serverUrl = process.env.NIMBUS_SIDECAR_URL;
|
||||
if (!serverUrl) {
|
||||
throw new Error("env var NIMBUS_SIDECAR_URL not set");
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${serverUrl}/v1/features`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
client_id: params.experimentationId,
|
||||
context: {
|
||||
// Nimbus takes a language, rather than a locale, hence the .split:
|
||||
locale: params.locale.split("-")[0],
|
||||
countryCode: params.countryCode,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const experimentData = (await response.json()) as ExperimentData;
|
||||
return experimentData ?? defaultExperimentData;
|
||||
} catch (ex) {
|
||||
logger.error(`Could not connect to Cirrus on ${serverUrl}`, ex);
|
||||
captureException(ex);
|
||||
}
|
||||
if (["local"].includes(process.env.APP_ENV ?? "local")) {
|
||||
return localExperimentData;
|
||||
}
|
||||
const serverUrl = process.env.NIMBUS_SIDECAR_URL;
|
||||
if (!serverUrl) {
|
||||
throw new Error("env var NIMBUS_SIDECAR_URL not set");
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${serverUrl}/v1/features`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
client_id: params.experimentationId,
|
||||
context: {
|
||||
// Nimbus takes a language, rather than a locale, hence the .split:
|
||||
locale: params.locale.split("-")[0],
|
||||
countryCode: params.countryCode,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const experimentData = (await response.json()) as ExperimentData;
|
||||
return experimentData ?? defaultExperimentData;
|
||||
} catch (ex) {
|
||||
logger.error(`Could not connect to Cirrus on ${serverUrl}`, ex);
|
||||
captureException(ex);
|
||||
return defaultExperimentData;
|
||||
}
|
||||
return defaultExperimentData;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ run();
|
|||
* @typedef {"String" | "Boolean" | "Int" | "Text" | "Image" | `Option<${Type}>` | `List<${Type}>` | `Map<${Type}, ${Type}>`} Type
|
||||
*/
|
||||
/**
|
||||
* @typedef {"staging" | "production"} Channel
|
||||
* @typedef {"local" | "staging" | "production"} Channel
|
||||
*/
|
||||
/**
|
||||
* @typedef {Record<
|
||||
|
@ -32,7 +32,7 @@ run();
|
|||
* features: Record<string, {
|
||||
* description: string;
|
||||
* variables: Variables;
|
||||
* defaults: Array<{
|
||||
* defaults?: Array<{
|
||||
* channel: Channel;
|
||||
* values: Record<keyof Variables, unknown>;
|
||||
* }>;
|
||||
|
@ -64,7 +64,9 @@ async function run() {
|
|||
"// AUTOGENERATED `npm run build-nimbus`. DO NOT EDIT. DO NOT COMMIT.\n\n" +
|
||||
getFeaturesTypeDef(nimbusConfig) +
|
||||
"\n" +
|
||||
getFallbackObject(nimbusConfig);
|
||||
getFallbackObject(nimbusConfig) +
|
||||
"\n" +
|
||||
getLocalOverrides(nimbusConfig);
|
||||
await mkdir("src/telemetry/generated/nimbus/", { recursive: true });
|
||||
await writeFile("src/telemetry/generated/nimbus/experiments.ts", typedef);
|
||||
}
|
||||
|
@ -90,6 +92,27 @@ function getFallbackObject(nimbusConfig) {
|
|||
return `export const defaultExperimentData: ExperimentData = {\n${featureFallbackDefs.join("\n")}};\n`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NimbusConfig} nimbusConfig
|
||||
* @returns string
|
||||
*/
|
||||
function getLocalOverrides(nimbusConfig) {
|
||||
const featureLocalOverridesDefs = Object.keys(nimbusConfig.features).map(
|
||||
(featureId) => {
|
||||
const localOverrides = nimbusConfig.features[featureId].defaults?.find(
|
||||
(defaultData) => defaultData.channel === "local",
|
||||
);
|
||||
const overriddenValuesDef =
|
||||
typeof localOverrides === "undefined"
|
||||
? ""
|
||||
: ` ...${JSON.stringify(localOverrides.value, null, 2).replaceAll("\n", "\n ")}\n`;
|
||||
return ` "${featureId}": {\n ...defaultExperimentData["${featureId}"],\n${overriddenValuesDef} },\n`;
|
||||
},
|
||||
);
|
||||
|
||||
return `export const localExperimentData: ExperimentData = {\n${featureLocalOverridesDefs.join("\n")}};\n`;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NimbusConfig} nimbusConfig
|
||||
* @returns string
|
||||
|
|
Загрузка…
Ссылка в новой задаче