Skip to content

chore: env management overhaul#9408

Open
AdityaHegde wants to merge 14 commits into
mainfrom
feat/env-edit-session
Open

chore: env management overhaul#9408
AdityaHegde wants to merge 14 commits into
mainfrom
feat/env-edit-session

Conversation

@AdityaHegde

@AdityaHegde AdityaHegde commented May 7, 2026

Copy link
Copy Markdown
Collaborator

We have multiple places where we read .env and assign variables for secrets. This leads to fragmented code especially with the new ducklake form changes.

Adding a service to manage env variables.

  1. EnvStore manages the full list of variables. Has hooks for getter and setter so that in future we can separate the file write and admin API calls.
  2. EnvEditSession manages the variables in flight during an edit. Managed which variables are assigned so that new env vars that come during the add data process is not overwritten.
  3. This also allows for yaml construction and env assignment to happen in a single method, compileConnectorYAML. This makes things like ducklake utils to not worry about env, just focus on attach.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

@AdityaHegde AdityaHegde force-pushed the feat/env-edit-session branch from 478764a to eeef6a0 Compare May 28, 2026 04:10
@AdityaHegde AdityaHegde requested a review from djbarnwal May 28, 2026 04:11
@AdityaHegde AdityaHegde marked this pull request as ready for review May 28, 2026 04:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR centralizes .env handling in web-common by introducing an env management layer (EnvStore + EnvEditSession) and wiring it through connector/source YAML generation and the add-data flows. It reduces scattered .env read/write logic and makes YAML compilation responsible for acquiring and mapping secrets via a session that can later be backed by different persistence mechanisms.

Changes:

  • Add EnvStore / EnvEditSession abstractions and a Svelte-context-backed createEnvFileStore that tracks /.env and refreshes on file watcher events.
  • Refactor connector/source YAML generation (including DuckLake helpers and sensitive headers) to acquire secrets via EnvEditSession and emit {{ .env.VAR }} references consistently.
  • Update add-data + AI connector flows to commit/rollback env edits via sessions instead of directly editing .env blobs.

Reviewed changes

Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
web-common/src/runtime-client/v2/RuntimeProvider.svelte Initializes the env file store alongside the runtime client lifecycle.
web-common/src/runtime-client/invalidation/file-invalidators.ts Emits env-file-updated on /.env writes to trigger env store refresh.
web-common/src/lib/event-bus/event-bus.ts Adds env-file-updated event type.
web-common/src/features/templates/schemas/ducklake-utils.ts Routes DuckLake secret handling through EnvEditSession (no direct .env blob munging).
web-common/src/features/templates/schemas/ducklake-utils.spec.ts Updates DuckLake tests to use env sessions and validate acquired env entries.
web-common/src/features/sources/sourceUtils.ts Renames and refactors source YAML generation to use EnvEditSession.
web-common/src/features/sources/sourceUtils.spec.ts Updates source YAML tests to use env sessions.
web-common/src/features/env-management/test/test-env-store.ts Adds test helpers for EnvStore / EnvEditSession.
web-common/src/features/env-management/env-variable.ts Introduces an env variable model object.
web-common/src/features/env-management/env-store.ts Adds store abstraction for pulling/flushing/rollback of env entries.
web-common/src/features/env-management/env-file-store.ts Implements .env-backed EnvStore with Svelte context + file watcher integration.
web-common/src/features/env-management/env-file-store.spec.ts Tests env file store getter/setter and event subscription behavior.
web-common/src/features/env-management/env-edit-session.ts Adds edit session to track allocations/in-flight entries and commit/rollback.
web-common/src/features/env-management/env-edit-session-variable.ts Defines env edit session entry type.
web-common/src/features/env-management/dot-env.ts Adds dotenv-style parser + serializer.
web-common/src/features/env-management/dot-env.spec.ts Adds parser/serializer tests (including round-trip).
web-common/src/features/connectors/env-utils.ts Extracts generic env var naming utility.
web-common/src/features/connectors/code-utils.ts Refactors connector YAML generation + header secret handling to use EnvEditSession and DuckLake pipeline.
web-common/src/features/connectors/code-utils.spec.ts Updates connector YAML + header formatting tests to use env sessions.
web-common/src/features/connectors/ai/saveAiConnector.ts Uses env sessions to generate YAML and commit env changes when saving AI connectors.
web-common/src/features/connectors/ai/AddAiConnectorDialog.svelte Creates an env session for AI connector creation and passes it through save.
web-common/src/features/add-data/manager/steps/types.ts Replaces envBlob with envEditSession in import step config.
web-common/src/features/add-data/manager/steps/import.ts Commits/rolls back env changes via session during import flow.
web-common/src/features/add-data/manager/steps/connector.ts Uses getConnectorYAML + env sessions for connector creation and rollback on cleanup.
web-common/src/features/add-data/manager/GenerateDashboardStatus.svelte Updates cleanup call signature after import cleanup refactor.
web-common/src/features/add-data/manager/AddDataStateManager.svelte.spec.ts Adjusts test config typing after envEditSession addition.
web-common/src/features/add-data/manager/AddDataManager.svelte Switches from wrapper component to direct ConnectorForm.
web-common/src/features/add-data/form/SourceForm.svelte Uses getSourceYAML and an env session instead of managing .env blobs directly.
web-common/src/features/add-data/form/ImportTableForm.svelte Adds env session to import config for table import path.
web-common/src/features/add-data/form/ConnectorFormWrapper.svelte Removes wrapper that previously handled async env blob caching.
web-common/src/features/add-data/form/ConnectorForm.svelte Uses cached env edit sessions from form cache and new YAML generator.
web-common/src/features/add-data/form/connector-source-yaml-generator.ts Consolidates connector/source YAML preview generation around env sessions.
web-common/src/features/add-data/form/connector-source-yaml-generator.spec.ts Adds broad integration-style tests for env session behavior across schemas.
Comments suppressed due to low confidence (1)

web-common/src/features/add-data/manager/AddDataStateManager.svelte.spec.ts:23

  • This test constructs an ImportStepConfig via a cast but omits the now-required envEditSession field. That makes the test less representative of production behavior and can hide regressions if future code paths start using config.envEditSession during transitions.
const ClickhouseImportConfig = {
  importSteps: [
    ImportDataStep.CreateMetricsView,
    ImportDataStep.CreateDashboard,
  ],

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +29
await runtimeServicePutFile(runtimeClient, {
path: "/.env",
blob: serializeDotEnv(entries),
});
Comment on lines +46 to +66
this.assignedVars = new Set<string>(this.parentStore.store.keys());
}

public acquire(key: string, value: string, envVarName?: string) {
if (this.inflightEntries.has(key)) {
const entry = this.inflightEntries.get(key)!;
entry.value = value;
this.inflightEntries.delete(key);
this.entries.set(key, entry);
this.assignedVars.add(key);
return entry;
}

envVarName ??= getGenericEnvVarName(this.namespace, key, this.schema);
const mappedEnvVarName = this.acquireVarName(envVarName);
const entry = new EnvEditSessionVariable(key, value, mappedEnvVarName);

this.entries.set(key, entry);
this.assignedVars.add(key);
return entry;
}
Comment on lines +17 to +19
if (quote === '"') {
value = value.replace(/\\n/g, "\n").replace(/\\r/g, "\r");
}
Comment on lines +39 to +43
// Double-quoted: the parser only unescapes \n and \r, so those are
// the only sequences we escape. Backslashes are passed through
// verbatim because the parser would not unescape them either.
const escaped = v.replace(/\n/g, "\\n").replace(/\r/g, "\\r");
return `${k}="${escaped}"`;
Comment on lines +15 to +17
for (const key in newEntries) {
newStore.set(key, new EnvVariable(key, newEntries[key]));
}
Comment on lines +136 to +139
expect(runtimeServicePutFile).toHaveBeenCalledWith(runtimeClient, {
path: "/.env",
blob: "CLICKHOUSE_PASSWORD=secret",
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants