Skip to content

Commit

Permalink
Merge pull request #1016 from pascalbreuninger/feat/additional-env-vars
Browse files Browse the repository at this point in the history
feat(desktop): add experimental extra environment variables setting
  • Loading branch information
89luca89 authored Apr 22, 2024
2 parents ca73d7c + f381eeb commit c3f49b7
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 24 deletions.
2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ tauri-build = { version = "1.2", features = [] }

[dependencies]
# Tauri
tauri = { version = "1.2.4", features = [ "updater",
tauri = { version = "1.2.4", features = [
"process-relaunch",
"window-close",
"notification-all",
Expand Down
1 change: 1 addition & 0 deletions desktop/src-tauri/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub struct Settings {
#[serde(rename = "experimental_devPodPro")]
experimental_devpod_pro: bool,
additional_cli_flags: String,
additional_env_vars: String,
}

#[derive(Debug, Serialize, TS)]
Expand Down
18 changes: 17 additions & 1 deletion desktop/src/client/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,26 @@ export class Command implements TCommand<ChildProcess> {
private childProcess?: Child
private args: string[]

public static ADDITIONAL_ENV_VARS: string = ""

constructor(args: string[]) {
debug("commands", "Creating Devpod command with args: ", args)
const extraEnvVars = Command.ADDITIONAL_ENV_VARS.split(",")
.map((envVarStr) => envVarStr.split("="))
.reduce((acc, pair) => {
const [key, value] = pair
if (key === undefined || value === undefined) {
return acc
}

return { ...acc, [key]: value }
}, {})

this.sidecarCommand = ShellCommand.sidecar(DEVPOD_BINARY, args, {
env: { [DEVPOD_UI_ENV_VAR]: "true" },
env: {
...extraEnvVars,
[DEVPOD_UI_ENV_VAR]: "true",
},
})
this.args = args
}
Expand Down
5 changes: 4 additions & 1 deletion desktop/src/contexts/SettingsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ const initialSettings: TSettings = {
experimental_vscodeInsiders: true,
experimental_devPodPro: false,
additionalCliFlags: "",
additionalEnvVars: "",
}
function getSettingKeys(): readonly TSetting[] {
return getKeys(initialSettings)
}

// WARN: needs to match the filename on the rust side
const SETTING_STORE_KEY = "settings"
const settingsStore = new Store(new LocalStorageToFileMigrationBackend(SETTING_STORE_KEY))
const settingsStore = new Store<Record<TSetting, string | boolean | unknown>>(
new LocalStorageToFileMigrationBackend(SETTING_STORE_KEY)
)

export function SettingsProvider({ children }: Readonly<{ children?: ReactNode }>) {
const [settings, setSettings] = useState(initialSettings)
Expand Down
1 change: 1 addition & 0 deletions desktop/src/gen/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export interface Settings {
experimental_vscodeInsiders: boolean
experimental_devPodPro: boolean
additionalCliFlags: string
additionalEnvVars: string
}
14 changes: 12 additions & 2 deletions desktop/src/views/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ import {
useVersion,
} from "../../lib"
import { useWelcomeModal } from "../../useWelcomeModal"
import { useCLIFlagsOption, useAgentURLOption, useTelemetryOption } from "./useContextOptions"
import {
useCLIFlagsOption,
useAgentURLOption,
useTelemetryOption,
useExtraEnvVarsOption,
} from "./useContextOptions"
import { useIDESettings } from "./useIDESettings"

const SETTINGS_TABS = [
Expand Down Expand Up @@ -319,6 +324,7 @@ function UpdateSettings() {

function ExperimentalSettings() {
const { input: cliFlagsInput, helpText: cliFlagsHelpText } = useCLIFlagsOption()
const { input: extraEnvVarsInput, helpText: extraEnvVarsHelpText } = useExtraEnvVarsOption()
const { settings, set } = useChangeSettings()

return (
Expand Down Expand Up @@ -365,10 +371,14 @@ function ExperimentalSettings() {
</HStack>
</SettingSection>

<SettingSection title="CLI Additional Flags" description={cliFlagsHelpText}>
<SettingSection title="Additional CLI Flags" description={cliFlagsHelpText}>
{cliFlagsInput}
</SettingSection>

<SettingSection title="Additional Environment Variables" description={extraEnvVarsHelpText}>
{extraEnvVarsInput}
</SettingSection>

<SettingSection
showDivider={false}
title="DevPod Pro (alpha)"
Expand Down
105 changes: 86 additions & 19 deletions desktop/src/views/Settings/useContextOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { client } from "../../client"
import { useChangeSettings } from "../../contexts"
import { QueryKeys } from "../../queryKeys"
import { TContextOptionName } from "../../types"
import { Command } from "../../client/command"

const DEFAULT_DEVPOD_AGENT_URL = "https://github.com/loft-sh/devpod/releases/latest/download/"

Expand All @@ -40,34 +41,22 @@ export function useContextOptions() {
[options, updateOption]
)
}

export function useSettingsOptions() {
export function useCLIFlagsOption() {
const { settings, set } = useChangeSettings()
const { mutate: updateOption } = useMutation({
mutationFn: async ({ value }: { value: string }) => {
const updateOption = useCallback(
(value: string) => {
set("additionalCliFlags", value)
client.setSetting("additionalCliFlags", value)
},
})

return useMemo(
() => ({
settings,
updateOption,
}),
[settings, updateOption]
[set]
)
}

export function useCLIFlagsOption() {
const { settings, updateOption } = useSettingsOptions()
const [hasFocus, setHasFocus] = useState(false)
const inputRef = useRef<HTMLInputElement>(null)

const handleBlur = useCallback(
(e: FocusEvent<HTMLInputElement>) => {
const value = e.target.value.trim()
updateOption({ value })
updateOption(value)
setHasFocus(false)
},
[updateOption]
Expand Down Expand Up @@ -96,7 +85,7 @@ export function useCLIFlagsOption() {
<Input
ref={inputRef}
spellCheck={false}
placeholder="CLI Additional Flags"
placeholder="Additional CLI Flags"
defaultValue={settings.additionalCliFlags}
onBlur={handleBlur}
onKeyUp={handleKeyUp}
Expand Down Expand Up @@ -129,10 +118,11 @@ export function useCLIFlagsOption() {
]
)

const helpText = useMemo(() => <>Set the additional CLI Flags to use.</>, [])
const helpText = useMemo(() => <>Set additional CLI Flags to use.</>, [])

return { input, helpText }
}

export function useAgentURLOption() {
const { options, updateOption } = useContextOptions()
const [hasFocus, setHasFocus] = useState(false)
Expand Down Expand Up @@ -244,3 +234,80 @@ export function useTelemetryOption() {

return { input, helpText }
}

export function useExtraEnvVarsOption() {
const { settings, set } = useChangeSettings()
const [hasFocus, setHasFocus] = useState(false)
const inputRef = useRef<HTMLInputElement>(null)

const handleBlur = useCallback(
(e: FocusEvent<HTMLInputElement>) => {
const value = e.target.value.trim()
set("additionalEnvVars", value)
Command.ADDITIONAL_ENV_VARS = value
setHasFocus(false)
},
[set]
)

const handleKeyUp = useCallback((e: KeyboardEvent<HTMLInputElement>) => {
if (e.key !== "Enter") return

e.currentTarget.blur()
}, [])

const handleFocus = useCallback(() => {
setHasFocus(true)
}, [])

const handleClear = useCallback(() => {
const el = inputRef.current
if (!el) return

el.value = ""
}, [])

const input = useMemo(
() => (
<InputGroup maxWidth="72">
<Input
ref={inputRef}
spellCheck={false}
placeholder="Additional Environment Variables"
defaultValue={settings.additionalEnvVars}
onBlur={handleBlur}
onKeyUp={handleKeyUp}
onFocus={handleFocus}
/>
<InputRightElement>
<IconButton
visibility={hasFocus ? "visible" : "hidden"}
size="xs"
borderRadius="full"
icon={<CloseIcon />}
aria-label="clear"
onMouseDown={(e) => {
// needed to prevent losing focus from input
e.stopPropagation()
e.preventDefault()
}}
onClick={handleClear}
/>
</InputRightElement>
</InputGroup>
),
[settings.additionalEnvVars, handleBlur, handleKeyUp, handleFocus, hasFocus, handleClear]
)

const helpText = useMemo(
() => (
<>
Set additional environment variables DevPod passes to all commands. Accepts a comma
separated list, e.g. FOO=bar,BAZ=false
</>
),
[]
)

return { input, helpText }
}

0 comments on commit c3f49b7

Please sign in to comment.