Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ async function bootstrap(): Promise<void> {
setCliContext(earlyContext);

try {
validateEnvironment();
const earlyExit = findEarlyBootstrapExit(rawArgs);
if (earlyExit?.id === "help") {
const [command, parent] = await resolveSubCommandForUsage(main, rawArgs);
Expand All @@ -180,6 +179,7 @@ async function bootstrap(): Promise<void> {
return;
}

validateEnvironment();
await runCommand(main, { rawArgs });
await maybeShowUpdateNotice({
context: getCliContext(),
Expand Down
11 changes: 0 additions & 11 deletions cli/src/lib/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,6 @@ export function copyProcessEnv(): NodeJS.ProcessEnv {
}

export function validateEnvironment(source: EnvSource = process.env): void {
const knownNames = new Set<string>(Object.keys(ENV_SCHEMA));
const unknownNames = Object.keys(source)
.filter((name) => name.startsWith("ALTERTABLE_") && !knownNames.has(name))
.sort();
if (unknownNames.length > 0) {
const noun = unknownNames.length === 1 ? "variable" : "variables";
throw new ConfigurationError(
`Unknown Altertable environment ${noun}: ${unknownNames.join(", ")}. Check the spelling against the documented ALTERTABLE_* variables.`,
);
}

for (const name of Object.keys(ENV_SCHEMA) as EnvName[]) {
if (name.startsWith("ALTERTABLE_")) {
readEnvFrom(source, name);
Expand Down
10 changes: 7 additions & 3 deletions cli/tests/env.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,14 @@ describe("environment schema", () => {
).toThrow("Secret environment variables must declare secret: true: ALTERTABLE_NEW_TOKEN");
});

test("rejects misspelled Altertable variable names", () => {
test("ignores unknown Altertable variable names", () => {
expect(() =>
validateEnvironment({ ALTERTABLE_API_KEI: "secret", ALTERTABLE_API_KEY: "valid" }),
).toThrow("Unknown Altertable environment variable: ALTERTABLE_API_KEI");
validateEnvironment({
ALTERTABLE_CATALOG: "analytics",
ALTERTABLE_SCHEMA: "reporting",
ALTERTABLE_TABLE: "events",
}),
).not.toThrow();
});

test("validates every configured Altertable value at startup", () => {
Expand Down
6 changes: 5 additions & 1 deletion tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type TestEnvName =
| "ALTERTABLE_API_BASE"
| "ALTERTABLE_API_KEY"
| "ALTERTABLE_BASIC_AUTH_TOKEN"
| "ALTERTABLE_CATALOG"
| "ALTERTABLE_CONFIG_HOME"
| "ALTERTABLE_ENV"
| "ALTERTABLE_HTTP_LOG"
Expand All @@ -20,7 +21,10 @@ type TestEnvName =
| "ALTERTABLE_MANAGEMENT_API_BASE"
| "ALTERTABLE_MOCK_HTTP_FILE"
| "ALTERTABLE_PROFILE"
| "ALTERTABLE_SECRET_BACKEND";
| "ALTERTABLE_SCHEMA"
| "ALTERTABLE_SECRET_BACKEND"
| "ALTERTABLE_TABLE"
| "ALTERTABLE_UPDATE_SOURCE";
export type TestEnv = Partial<Record<TestEnvName, EnvValue>>;

type RunOptions = {
Expand Down
24 changes: 24 additions & 0 deletions tests/scripting.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ describe("scriptable exit codes and JSON errors", () => {
expect(JSON.parse(result.stdout).profile.name).toBe("_from_env");
});

test("ignores unrelated Altertable workflow variables", async () => {
const result = await workspace.runCommand("altertable --json profile show", {
env: {
ALTERTABLE_CATALOG: "analytics",
ALTERTABLE_SCHEMA: "reporting",
ALTERTABLE_TABLE: "events",
},
});

expect(result.exitCode).toBe(0);
expect(result.stderr).toBe("");
expect(JSON.parse(result.stdout).profile.name).toBe("_from_env");
});

test.each(["--help", "--version"])("%s bypasses environment validation", async (flag) => {
const result = await workspace.runCommand(`altertable ${flag}`, {
env: { ALTERTABLE_UPDATE_SOURCE: "gitlab" },
});

expect(result.exitCode).toBe(0);
expect(result.stderr).toBe("");
expect(result.stdout.length).toBeGreaterThan(0);
});

test.each([
["auth", statusMocks.auth, "altertable --json api GET /whoami", 2, "auth_failed"],
["not found", statusMocks.missing, "altertable --json api GET /environments/production/connections/missing", 4, undefined],
Expand Down
Loading