Skip to content

Commit f85d4e4

Browse files
experimental IDEs feature flag (#17240)
* `experimental` IDEs feature flag * [debug, do not merge]: test with experimental VS Code
1 parent 0058d68 commit f85d4e4

File tree

5 files changed

+25
-3
lines changed

5 files changed

+25
-3
lines changed

components/dashboard/src/components/SelectIDEComponent.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
*/
66

77
import { IDEOption, IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol";
8-
import { useCallback, useEffect, useState } from "react";
8+
import { useCallback, useContext, useEffect, useState } from "react";
99
import { getGitpodService } from "../service/service";
1010
import { DropDown2, DropDown2Element } from "./DropDown2";
1111
import Editor from "../icons/Editor.svg";
12+
import { FeatureFlagContext } from "../contexts/FeatureFlagContext";
1213

1314
interface SelectIDEComponentProps {
1415
selectedIdeOption?: string;
@@ -17,8 +18,16 @@ interface SelectIDEComponentProps {
1718
setError?: (error?: string) => void;
1819
}
1920

21+
function filteredIdeOptions(ideOptions: IDEOptions, experimentalTurnedOn: boolean) {
22+
return IDEOptions.asArray(ideOptions)
23+
.filter((x) => !x.hidden)
24+
.filter((x) => (x.experimental ? experimentalTurnedOn : true));
25+
}
26+
2027
export default function SelectIDEComponent(props: SelectIDEComponentProps) {
2128
const [ideOptions, setIdeOptions] = useState<IDEOptions>();
29+
const { experimentalIdes } = useContext(FeatureFlagContext);
30+
2231
useEffect(() => {
2332
getGitpodService().server.getIDEOptions().then(setIdeOptions);
2433
}, []);
@@ -27,7 +36,7 @@ export default function SelectIDEComponent(props: SelectIDEComponentProps) {
2736
if (!ideOptions) {
2837
return [];
2938
}
30-
const options = IDEOptions.asArray(ideOptions);
39+
const options = filteredIdeOptions(ideOptions, experimentalIdes);
3140
const result: DropDown2Element[] = [];
3241
for (const ide of options.filter((ide) =>
3342
`${ide.label}${ide.title}${ide.notes}${ide.id}`.toLowerCase().includes(search.toLowerCase()),
@@ -48,7 +57,7 @@ export default function SelectIDEComponent(props: SelectIDEComponentProps) {
4857
}
4958
return result;
5059
},
51-
[ideOptions, props.useLatest],
60+
[experimentalIdes, ideOptions, props.useLatest],
5261
);
5362
const internalOnSelectionChange = (id: string) => {
5463
const { ide, useLatest } = parseId(id);

components/dashboard/src/contexts/FeatureFlagContext.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const defaultFeatureFlags = {
2929
userGitAuthProviders: false,
3030
newSignupFlow: false,
3131
linkedinConnectionForOnboarding: false,
32+
experimentalIdes: false,
3233
};
3334

3435
const FeatureFlagContext = createContext<FeatureFlagsType>(defaultFeatureFlags);
@@ -47,6 +48,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
4748
const [userGitAuthProviders, setUserGitAuthProviders] = useState<boolean>(false);
4849
const [newSignupFlow, setNewSignupFlow] = useState<boolean>(false);
4950
const [linkedinConnectionForOnboarding, setLinkedinConnectionForOnboarding] = useState<boolean>(false);
51+
const [experimentalIdes, setExperimentalIdes] = useState<boolean>(false);
5052

5153
useEffect(() => {
5254
if (!user) return;
@@ -65,6 +67,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
6567
userGitAuthProviders: { defaultValue: false, setter: setUserGitAuthProviders },
6668
newSignupFlow: { defaultValue: false, setter: setNewSignupFlow },
6769
linkedinConnectionForOnboarding: { defaultValue: false, setter: setLinkedinConnectionForOnboarding },
70+
experimentalIdes: { defaultValue: false, setter: setExperimentalIdes },
6871
};
6972

7073
for (const [flagName, config] of Object.entries(featureFlags)) {
@@ -112,6 +115,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
112115
userGitAuthProviders,
113116
newSignupFlow,
114117
linkedinConnectionForOnboarding,
118+
experimentalIdes,
115119
};
116120
}, [
117121
enablePersonalAccessTokens,
@@ -123,6 +127,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => {
123127
startWithOptions,
124128
usePublicApiWorkspacesService,
125129
userGitAuthProviders,
130+
experimentalIdes,
126131
]);
127132

128133
return <FeatureFlagContext.Provider value={flags}>{children}</FeatureFlagContext.Provider>;

components/gitpod-protocol/src/ide-protocol.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ export interface IDEOption {
105105
*/
106106
hidden?: boolean;
107107

108+
/**
109+
* If `true` this IDE option is conditionally shown in the IDE preferences
110+
*/
111+
experimental?: boolean;
112+
108113
/**
109114
* The image ref to the IDE image.
110115
*/

components/ide-service-api/go/config/ideconfig.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ type IDEOption struct {
4444
Notes []string `json:"notes,omitempty"`
4545
// Hidden this IDE option is not visible in the IDE preferences.
4646
Hidden bool `json:"hidden,omitempty"`
47+
// Experimental this IDE option is to only be shown to some users
48+
Experimental bool `json:"experimental,omitempty"`
4749
// Image ref to the IDE image.
4850
Image string `json:"image"`
4951
// LatestImage ref to the IDE image, this image ref always resolve to digest.

install/installer/pkg/components/ide-service/ide_config_configmap.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func ideConfigConfigmap(ctx *common.RenderContext) ([]runtime.Object, error) {
8888
ImageLayers: []string{codeWebExtensionImage, codeHelperImage},
8989
LatestImage: resolveLatestImage(ide.CodeIDEImage, "nightly", ctx.VersionManifest.Components.Workspace.CodeImage),
9090
LatestImageLayers: []string{codeWebExtensionImage, codeHelperImage},
91+
Experimental: true,
9192
},
9293
codeDesktop: {
9394
OrderKey: "02",

0 commit comments

Comments
 (0)