From 71966571fbc2da180b4b3b415823b180cc0fb8c2 Mon Sep 17 00:00:00 2001 From: Scott Prutton Date: Thu, 13 Jun 2024 12:50:17 -0400 Subject: [PATCH] feat: allow setting arbitrary runtime env vars in the web container --- app/web/.env | 1 + app/web/Dockerfile | 2 +- app/web/docker-entrypoint.sh | 9 +++++++++ app/web/src/main.ts | 11 ++++++++--- app/web/src/shared/dynamicEnvVars.ts | 23 +++++++++++++++++++++++ app/web/src/vite-env.d.ts | 9 +++++++++ app/web/vite.config.ts | 14 ++++++++++++++ 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 app/web/src/shared/dynamicEnvVars.ts create mode 100644 app/web/src/vite-env.d.ts diff --git a/app/web/.env b/app/web/.env index 6733ad2874..d7eeaf64d8 100644 --- a/app/web/.env +++ b/app/web/.env @@ -44,3 +44,4 @@ VITE_POSTHOG_API_HOST=https://e.systeminit.com # VITE_LOG_WS=true # turn on console logging for all WS events except cursor and online events # VITE_LOG_WS_CURSOR=true # turn on console logging for cursor related WS events # VITE_LOG_WS_ONLINE=true # turn on console logging for online related WS events +VITE_OTEL_EXPORTER_OTLP_ENDPOINT="http://$DEV_HOST" diff --git a/app/web/Dockerfile b/app/web/Dockerfile index 115beb23c5..95c9ec6538 100644 --- a/app/web/Dockerfile +++ b/app/web/Dockerfile @@ -23,7 +23,7 @@ ARG APP=web # hadolint ignore=DL3018 RUN set -eux; \ - apk add --no-cache runuser; \ + apk add --no-cache runuser moreutils envsubst; \ for dir in /run /etc /usr/local/etc; do \ mkdir -pv "$dir/$APP"; \ done; \ diff --git a/app/web/docker-entrypoint.sh b/app/web/docker-entrypoint.sh index b551029a25..4de3d759f2 100755 --- a/app/web/docker-entrypoint.sh +++ b/app/web/docker-entrypoint.sh @@ -6,6 +6,15 @@ main() { echo "Info: SI__WEB__SDF_HOST supplied [ $SI__WEB__SDF_HOST ]! Registering in nginx.conf" sed -i "s^server sdf:5156^server $SI__WEB__SDF_HOST^g" "$(find /nix/store/ -path '/nix/store/*web/conf/nginx.conf')" fi + + if [ -n "${VITE_OTEL_EXPORTER_OTLP_ENDPOINT:-}" ]; then + echo "Info: VITE_OTEL_EXPORTER_OTLP_ENDPOINT supplied [ $VITE_OTEL_EXPORTER_OTLP_ENDPOINT ]! Setting in web" + projectEnvVariables=$(find /nix/store -name "projectEnvVar*.js" | head -n 1) + tmp=$(mktemp) + envsubst <"$projectEnvVariables" >"$tmp" + mv "$tmp" "$projectEnvVariables" + chmod +rx "$projectEnvVariables" + fi exec @@nginx@@ -c @@conf@@ -p @@prefix@@ -g "daemon off;" "$@" } diff --git a/app/web/src/main.ts b/app/web/src/main.ts index c95133309e..e0f1533487 100644 --- a/app/web/src/main.ts +++ b/app/web/src/main.ts @@ -19,19 +19,24 @@ import "@si/vue-lib/tailwind/main.css"; import "@si/vue-lib/tailwind/tailwind.css"; import App from "@/App.vue"; +import { getProjectEnvVariables } from "./shared/dynamicEnvVars"; import "./utils/posthog"; import router from "./router"; import store from "./store"; +const { envVariables } = getProjectEnvVariables(); + const backendHosts = import.meta.env.VITE_BACKEND_HOSTS ? JSON.parse(import.meta.env.VITE_BACKEND_HOSTS).map( (r: string) => new RegExp(r), ) : []; + +const otelEndpoint = + envVariables.VITE_OTEL_EXPORTER_OTLP_ENDPOINT ?? + import.meta.env.VITE_OTEL_EXPORTER_OTLP_ENDPOINT; const sdk = new HoneycombWebSDK({ - endpoint: `${ - import.meta.env.VITE_OTEL_EXPORTER_OTLP_ENDPOINT - }:4318/v1/traces`, + endpoint: `${otelEndpoint}:4318/v1/traces`, serviceName: "si-vue", skipOptionsValidation: true, instrumentations: [ diff --git a/app/web/src/shared/dynamicEnvVars.ts b/app/web/src/shared/dynamicEnvVars.ts new file mode 100644 index 0000000000..2e4e3d3fea --- /dev/null +++ b/app/web/src/shared/dynamicEnvVars.ts @@ -0,0 +1,23 @@ +type ProjectEnvVariablesType = Pick< + ImportMetaEnv, + "VITE_OTEL_EXPORTER_OTLP_ENDPOINT" +>; + +// We must use `${}` so this variable gets replaced in the docker container +const projectEnvVariables: ProjectEnvVariablesType = { + VITE_OTEL_EXPORTER_OTLP_ENDPOINT: "${VITE_OTEL_EXPORTER_OTLP_ENDPOINT}", // eslint-disable-line no-template-curly-in-string +}; + +// Returning the variable value from runtime or obtained as a result of the build +export const getProjectEnvVariables = (): { + envVariables: ProjectEnvVariablesType; +} => { + return { + envVariables: { + VITE_OTEL_EXPORTER_OTLP_ENDPOINT: + !projectEnvVariables.VITE_OTEL_EXPORTER_OTLP_ENDPOINT.includes("VITE_") + ? projectEnvVariables.VITE_OTEL_EXPORTER_OTLP_ENDPOINT + : import.meta.env.VITE_OTEL_EXPORTER_OTLP_ENDPOINT, + }, + }; +}; diff --git a/app/web/src/vite-env.d.ts b/app/web/src/vite-env.d.ts new file mode 100644 index 0000000000..34160870b1 --- /dev/null +++ b/app/web/src/vite-env.d.ts @@ -0,0 +1,9 @@ +/// + +interface ImportMetaEnv { + readonly VITE_OTEL_EXPORTER_OTLP_ENDPOINT: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/app/web/vite.config.ts b/app/web/vite.config.ts index 3520cd3094..e6a511cb1a 100644 --- a/app/web/vite.config.ts +++ b/app/web/vite.config.ts @@ -106,6 +106,20 @@ export default (opts: { mode: string }) => { }, build: { manifest: true, + rollupOptions: { + output: { + format: 'es', + globals: { + react: 'React', + 'react-dom': 'ReactDOM', + }, + manualChunks(id) { + if (/dynamicEnvVars.ts/.test(id)) { + return 'projectEnvVariables' + } + }, + }, + } }, }); };