mirror of https://github.com/coder/coder.git
feat: add warning about use of old/removed/invalid experiments (#12962)
This commit is contained in:
parent
cb8c576c93
commit
b85d5d8491
|
@ -3,7 +3,7 @@ import { Helmet } from "react-helmet-async";
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { deploymentDAUs } from "api/queries/deployment";
|
import { deploymentDAUs } from "api/queries/deployment";
|
||||||
import { entitlements } from "api/queries/entitlements";
|
import { entitlements } from "api/queries/entitlements";
|
||||||
import { availableExperiments } from "api/queries/experiments";
|
import { availableExperiments, experiments } from "api/queries/experiments";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { useDeploySettings } from "../DeploySettingsLayout";
|
import { useDeploySettings } from "../DeploySettingsLayout";
|
||||||
import { GeneralSettingsPageView } from "./GeneralSettingsPageView";
|
import { GeneralSettingsPageView } from "./GeneralSettingsPageView";
|
||||||
|
@ -12,7 +12,14 @@ const GeneralSettingsPage: FC = () => {
|
||||||
const { deploymentValues } = useDeploySettings();
|
const { deploymentValues } = useDeploySettings();
|
||||||
const deploymentDAUsQuery = useQuery(deploymentDAUs());
|
const deploymentDAUsQuery = useQuery(deploymentDAUs());
|
||||||
const entitlementsQuery = useQuery(entitlements());
|
const entitlementsQuery = useQuery(entitlements());
|
||||||
const experimentsQuery = useQuery(availableExperiments());
|
const enabledExperimentsQuery = useQuery(experiments());
|
||||||
|
const safeExperimentsQuery = useQuery(availableExperiments());
|
||||||
|
|
||||||
|
const safeExperiments = safeExperimentsQuery.data?.safe ?? [];
|
||||||
|
const invalidExperiments =
|
||||||
|
enabledExperimentsQuery.data?.filter((exp) => {
|
||||||
|
return !safeExperiments.includes(exp);
|
||||||
|
}) ?? [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -24,7 +31,8 @@ const GeneralSettingsPage: FC = () => {
|
||||||
deploymentDAUs={deploymentDAUsQuery.data}
|
deploymentDAUs={deploymentDAUsQuery.data}
|
||||||
deploymentDAUsError={deploymentDAUsQuery.error}
|
deploymentDAUsError={deploymentDAUsQuery.error}
|
||||||
entitlements={entitlementsQuery.data}
|
entitlements={entitlementsQuery.data}
|
||||||
safeExperiments={experimentsQuery.data?.safe ?? []}
|
invalidExperiments={invalidExperiments}
|
||||||
|
safeExperiments={safeExperiments}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,6 +40,7 @@ const meta: Meta<typeof GeneralSettingsPageView> = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
deploymentDAUs: MockDeploymentDAUResponse,
|
deploymentDAUs: MockDeploymentDAUResponse,
|
||||||
|
invalidExperiments: [],
|
||||||
safeExperiments: [],
|
safeExperiments: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -102,6 +103,43 @@ export const allExperimentsEnabled: Story = {
|
||||||
hidden: false,
|
hidden: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
safeExperiments: [],
|
safeExperiments: ["shared-ports"],
|
||||||
|
invalidExperiments: ["invalid"],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const invalidExperimentsEnabled: Story = {
|
||||||
|
args: {
|
||||||
|
deploymentOptions: [
|
||||||
|
{
|
||||||
|
name: "Access URL",
|
||||||
|
description:
|
||||||
|
"The URL that users will use to access the Coder deployment.",
|
||||||
|
flag: "access-url",
|
||||||
|
flag_shorthand: "",
|
||||||
|
value: "https://dev.coder.com",
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Wildcard Access URL",
|
||||||
|
description:
|
||||||
|
'Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".',
|
||||||
|
flag: "wildcard-access-url",
|
||||||
|
flag_shorthand: "",
|
||||||
|
value: "*--apps.dev.coder.com",
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Experiments",
|
||||||
|
description:
|
||||||
|
"Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.",
|
||||||
|
flag: "experiments",
|
||||||
|
value: ["invalid", "*"],
|
||||||
|
flag_shorthand: "",
|
||||||
|
hidden: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
safeExperiments: ["shared-ports"],
|
||||||
|
invalidExperiments: ["invalid"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import AlertTitle from "@mui/material/AlertTitle";
|
||||||
import type { FC } from "react";
|
import type { FC } from "react";
|
||||||
import type {
|
import type {
|
||||||
SerpentOption,
|
SerpentOption,
|
||||||
|
@ -13,6 +14,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||||
import { Stack } from "components/Stack/Stack";
|
import { Stack } from "components/Stack/Stack";
|
||||||
import { useDeploymentOptions } from "utils/deployOptions";
|
import { useDeploymentOptions } from "utils/deployOptions";
|
||||||
import { docs } from "utils/docs";
|
import { docs } from "utils/docs";
|
||||||
|
import { Alert } from "../../../components/Alert/Alert";
|
||||||
import { Header } from "../Header";
|
import { Header } from "../Header";
|
||||||
import OptionsTable from "../OptionsTable";
|
import OptionsTable from "../OptionsTable";
|
||||||
import { ChartSection } from "./ChartSection";
|
import { ChartSection } from "./ChartSection";
|
||||||
|
@ -22,7 +24,8 @@ export type GeneralSettingsPageViewProps = {
|
||||||
deploymentDAUs?: DAUsResponse;
|
deploymentDAUs?: DAUsResponse;
|
||||||
deploymentDAUsError: unknown;
|
deploymentDAUsError: unknown;
|
||||||
entitlements: Entitlements | undefined;
|
entitlements: Entitlements | undefined;
|
||||||
safeExperiments: Experiments | undefined;
|
readonly invalidExperiments: Experiments | string[];
|
||||||
|
readonly safeExperiments: Experiments | string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
|
export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
|
||||||
|
@ -31,6 +34,7 @@ export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
|
||||||
deploymentDAUsError,
|
deploymentDAUsError,
|
||||||
entitlements,
|
entitlements,
|
||||||
safeExperiments,
|
safeExperiments,
|
||||||
|
invalidExperiments,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -58,6 +62,28 @@ export const GeneralSettingsPageView: FC<GeneralSettingsPageViewProps> = ({
|
||||||
</ChartSection>
|
</ChartSection>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{invalidExperiments.length > 0 && (
|
||||||
|
<Alert severity="warning">
|
||||||
|
<AlertTitle>Invalid experiments in use:</AlertTitle>
|
||||||
|
<ul>
|
||||||
|
{invalidExperiments.map((it) => (
|
||||||
|
<li key={it}>
|
||||||
|
<pre>{it}</pre>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
It is recommended that you remove these experiments from your
|
||||||
|
configuration as they have no effect. See{" "}
|
||||||
|
<a
|
||||||
|
href="https://coder.com/docs/v2/latest/cli/server#--experiments"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
the documentation
|
||||||
|
</a>{" "}
|
||||||
|
for more details.
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
<OptionsTable
|
<OptionsTable
|
||||||
options={useDeploymentOptions(
|
options={useDeploymentOptions(
|
||||||
deploymentOptions,
|
deploymentOptions,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
|
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||||
import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined";
|
import BuildCircleOutlinedIcon from "@mui/icons-material/BuildCircleOutlined";
|
||||||
import type { FC, HTMLAttributes, PropsWithChildren } from "react";
|
import type { FC, HTMLAttributes, PropsWithChildren } from "react";
|
||||||
import { DisabledBadge, EnabledBadge } from "components/Badges/Badges";
|
import { DisabledBadge, EnabledBadge } from "components/Badges/Badges";
|
||||||
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
|
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
|
||||||
|
@ -91,11 +91,11 @@ export const OptionValue: FC<OptionValueProps> = (props) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isEnabled && (
|
{isEnabled && (
|
||||||
<CheckCircleOutlined
|
<BuildCircleOutlinedIcon
|
||||||
css={(theme) => ({
|
css={(theme) => ({
|
||||||
width: 16,
|
width: 16,
|
||||||
height: 16,
|
height: 16,
|
||||||
color: theme.palette.success.light,
|
color: theme.palette.mode,
|
||||||
margin: "0 8px",
|
margin: "0 8px",
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -38,13 +38,13 @@ export function optionValue(
|
||||||
([key, value]) => `"${key}"->"${value}"`,
|
([key, value]) => `"${key}"->"${value}"`,
|
||||||
);
|
);
|
||||||
case "Experiments": {
|
case "Experiments": {
|
||||||
const experimentMap: Record<string, boolean> | undefined =
|
const experimentMap = additionalValues?.reduce<Record<string, boolean>>(
|
||||||
additionalValues?.reduce(
|
(acc, v) => {
|
||||||
(acc, v) => {
|
acc[v] = option.value.includes("*");
|
||||||
return { ...acc, [v]: option.value.includes("*") ? true : false };
|
return acc;
|
||||||
},
|
},
|
||||||
{} as Record<string, boolean>,
|
{},
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!experimentMap) {
|
if (!experimentMap) {
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue