* init checkpoint * ui second pass... * round 1 backend + saving settings + detecting changes... * checkpoint * fix openapi * saving + correct wmill.yaml diff * cli refactor * cli and tests refactor done * cli multi workspace support * cli support skip core types to align with ui * new test framework * sqlx * openapi spec * frontend * sync + settings changes * some fixes * some fixes * security: Remove hardcoded EE license key, use environment variable only - Remove hardcoded license key from containerized test backend - Environment variable EE_LICENSE_KEY now required for EE features - License key no longer stored in database during tests * sqlx * tests * fixing tests * fix tests * checkpoint * checkpoint * cli build * frontend - cli exchange * settings match * ee repo ref * npm check * openapi * tests * checkpoint * cli + tests * reset to preview on changes * merge issue ee * cleanup * hubscript * simplifications * ee repo ref * cli fixes * fix sync and add tests * extra test * git sync settings / key change aware * ee-repo ref * ee-repo ref * ee repo ref * ee ref * review 1 * ee ref * Update frontend/src/lib/components/PullGitRepoPopover.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * Update frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com> * ee ref * remove extra includes from ui --------- Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
273 lines
11 KiB
TypeScript
273 lines
11 KiB
TypeScript
import { assertEquals, assert } from "https://deno.land/std@0.224.0/assert/mod.ts";
|
|
import { getEffectiveSettings } from "../conf.ts";
|
|
import { withContainerizedBackend } from "./containerized_backend.ts";
|
|
import { addWorkspace } from "../workspace.ts";
|
|
|
|
// =============================================================================
|
|
// OVERRIDE SETTINGS BEHAVIOR TESTS
|
|
// Tests for override inheritance and file filtering behavior
|
|
// =============================================================================
|
|
|
|
Deno.test("Override Settings: override inherits non-overridden settings from base config", () => {
|
|
const config = {
|
|
includes: ["default/**"],
|
|
skipVariables: true, // Base has this as true
|
|
skipResources: true, // Base has this as true
|
|
skipApps: false, // Base has this as false
|
|
defaultTs: "bun" as const,
|
|
overrides: {
|
|
"http://localhost:8000/:test:u/user/repo": {
|
|
includes: ["override/**"],
|
|
skipApps: true // Override only changes skipApps, should inherit other skip flags
|
|
}
|
|
}
|
|
};
|
|
|
|
const effective = getEffectiveSettings(
|
|
config,
|
|
"http://localhost:8000/",
|
|
"test",
|
|
"u/user/repo"
|
|
);
|
|
|
|
// Override values should be used
|
|
assertEquals(effective.includes, ["override/**"], "Must use override includes");
|
|
assertEquals(effective.skipApps, true, "Must use override skipApps");
|
|
|
|
// Should inherit skip flags from base config
|
|
assertEquals(effective.skipVariables, true, "Must inherit skipVariables=true from base config");
|
|
assertEquals(effective.skipResources, true, "Must inherit skipResources=true from base config");
|
|
assertEquals(effective.defaultTs, "bun", "Must inherit defaultTs from base config");
|
|
});
|
|
|
|
Deno.test("Override Settings: workspace wildcards with repo-specific precedence", () => {
|
|
const config = {
|
|
includes: ["default/**"],
|
|
skipVariables: false,
|
|
overrides: {
|
|
"http://localhost:8000/:test:*": {
|
|
skipVariables: true,
|
|
includes: ["workspace/**"]
|
|
},
|
|
"http://localhost:8000/:test:u/user/specific": {
|
|
includes: ["specific/**"]
|
|
}
|
|
}
|
|
};
|
|
|
|
// Test specific repo override (should take precedence over wildcard)
|
|
const specificEffective = getEffectiveSettings(
|
|
config,
|
|
"http://localhost:8000/",
|
|
"test",
|
|
"u/user/specific"
|
|
);
|
|
assertEquals(specificEffective.includes, ["specific/**"], "Specific repo override must take precedence over wildcard");
|
|
assertEquals(specificEffective.skipVariables, true, "Workspace wildcard setting must still apply");
|
|
|
|
// Test wildcard match
|
|
const wildcardEffective = getEffectiveSettings(
|
|
config,
|
|
"http://localhost:8000/",
|
|
"test",
|
|
"u/user/other"
|
|
);
|
|
assertEquals(wildcardEffective.includes, ["workspace/**"], "Wildcard must match repos without specific overrides");
|
|
assertEquals(wildcardEffective.skipVariables, true, "Workspace wildcard setting must apply");
|
|
});
|
|
|
|
// =============================================================================
|
|
// INTEGRATION TESTS - File Filtering Behavior
|
|
// =============================================================================
|
|
|
|
Deno.test("Integration: sync pull with skipVariables override excludes variable files", async () => {
|
|
await withContainerizedBackend(async (backend, tempDir) => {
|
|
// Set up workspace
|
|
const testWorkspace = {
|
|
remote: backend.baseUrl,
|
|
workspaceId: backend.workspace,
|
|
name: "skip_variables_test",
|
|
token: backend.token
|
|
};
|
|
await addWorkspace(testWorkspace, { force: true, configDir: backend.testConfigDir });
|
|
|
|
// Create wmill.yaml with override that skips variables
|
|
const backendUrl = new URL(backend.baseUrl).toString();
|
|
await Deno.writeTextFile(`${tempDir}/wmill.yaml`, `defaultTs: bun
|
|
includes:
|
|
- "**"
|
|
skipVariables: false
|
|
|
|
overrides:
|
|
"${backendUrl}:${backend.workspace}:u/test/test_repo":
|
|
skipVariables: true`);
|
|
|
|
// Verify backend has test variable before pull
|
|
const backendVariables = await backend.listAllVariables();
|
|
const hasTestVariable = backendVariables.some(v => v.path === 'u/admin/test_config');
|
|
assert(hasTestVariable, "Backend should have test variable before pull");
|
|
|
|
// Run sync pull (NOT dry-run) to actually write files
|
|
const result = await backend.runCLICommand([
|
|
'sync', 'pull',
|
|
'--repository', 'u/test/test_repo',
|
|
'--yes'
|
|
], tempDir);
|
|
|
|
assertEquals(result.code, 0, `Sync pull should succeed: ${result.stderr}`);
|
|
|
|
// Verify variable files were NOT written to filesystem due to skipVariables: true
|
|
const filesWritten = [];
|
|
for await (const entry of Deno.readDir(tempDir)) {
|
|
if (entry.isFile && entry.name.endsWith('.yaml')) {
|
|
filesWritten.push(entry.name);
|
|
}
|
|
}
|
|
|
|
const hasVariableFile = filesWritten.some(file => file.includes('.variable.yaml'));
|
|
assertEquals(hasVariableFile, false, "Variable files should NOT be written due to skipVariables override");
|
|
|
|
// Verify other files WERE written (since skipVariables only affects variables)
|
|
// Check what files were actually written
|
|
console.log("Files written:", filesWritten);
|
|
|
|
// Should have some files written (just not variable files)
|
|
assert(filesWritten.length > 0, `Some files should be written when skipVariables is true. Got: ${filesWritten.join(', ')}`);
|
|
|
|
// Should not have only wmill.yaml file
|
|
const nonWmillFiles = filesWritten.filter(f => !f.includes('wmill.yaml'));
|
|
assert(nonWmillFiles.length > 0, `Non-wmill.yaml files should be written when skipVariables is true. Got: ${nonWmillFiles.join(', ')}`);
|
|
});
|
|
});
|
|
|
|
Deno.test("Integration: sync push with skipVariables override excludes variable files", async () => {
|
|
await withContainerizedBackend(async (backend, tempDir) => {
|
|
// Set up workspace
|
|
const testWorkspace = {
|
|
remote: backend.baseUrl,
|
|
workspaceId: backend.workspace,
|
|
name: "push_skip_test",
|
|
token: backend.token
|
|
};
|
|
await addWorkspace(testWorkspace, { force: true, configDir: backend.testConfigDir });
|
|
|
|
// Create wmill.yaml with override that skips variables
|
|
const backendUrl = new URL(backend.baseUrl).toString();
|
|
await Deno.writeTextFile(`${tempDir}/wmill.yaml`, `defaultTs: bun
|
|
includes:
|
|
- "**"
|
|
skipVariables: false
|
|
|
|
overrides:
|
|
"${backendUrl}:${backend.workspace}:u/test/test_repo":
|
|
skipVariables: true`);
|
|
|
|
// Create local test files including variables and scripts
|
|
const timestamp = Date.now();
|
|
|
|
// Create variable file
|
|
await Deno.mkdir(`${tempDir}/u/admin`, { recursive: true });
|
|
await Deno.writeTextFile(`${tempDir}/u/admin/test_push_var_${timestamp}.variable.yaml`,
|
|
`value: test_value_${timestamp}
|
|
description: Test variable for push override test
|
|
is_secret: false`);
|
|
|
|
// Create script file
|
|
await Deno.mkdir(`${tempDir}/f/test`, { recursive: true });
|
|
await Deno.writeTextFile(`${tempDir}/f/test/push_script_${timestamp}.ts`,
|
|
`export async function main() {
|
|
return "Test script ${timestamp}";
|
|
}`);
|
|
await Deno.writeTextFile(`${tempDir}/f/test/push_script_${timestamp}.script.yaml`,
|
|
`summary: Test Push Script ${timestamp}
|
|
description: Script for testing push with override`);
|
|
|
|
// Get backend state before push
|
|
const beforeVariables = await backend.listAllVariables();
|
|
const beforeScripts = await backend.listAllScripts();
|
|
|
|
const variableExistsBefore = beforeVariables.some(v => v.path === `u/admin/test_push_var_${timestamp}`);
|
|
const scriptExistsBefore = beforeScripts.some(s => s.path === `f/test/push_script_${timestamp}`);
|
|
|
|
assertEquals(variableExistsBefore, false, "Variable should not exist before push");
|
|
assertEquals(scriptExistsBefore, false, "Script should not exist before push");
|
|
|
|
// Run sync push (NOT dry-run) to actually push files
|
|
const result = await backend.runCLICommand([
|
|
'sync', 'push',
|
|
'--repository', 'u/test/test_repo',
|
|
'--yes'
|
|
], tempDir);
|
|
|
|
assertEquals(result.code, 0, `Sync push should succeed: ${result.stderr}`);
|
|
|
|
// Verify variable was NOT pushed due to skipVariables: true
|
|
const afterVariables = await backend.listAllVariables();
|
|
const variableExistsAfter = afterVariables.some(v => v.path === `u/admin/test_push_var_${timestamp}`);
|
|
assertEquals(variableExistsAfter, false, "Variable should NOT be pushed due to skipVariables override");
|
|
|
|
// Verify script WAS pushed (not affected by skipVariables)
|
|
const afterScripts = await backend.listAllScripts();
|
|
const scriptExistsAfter = afterScripts.some(s => s.path === `f/test/push_script_${timestamp}`);
|
|
assertEquals(scriptExistsAfter, true, "Script should be pushed normally");
|
|
});
|
|
});
|
|
|
|
Deno.test("Integration: sync pull respects includes override for file filtering", async () => {
|
|
await withContainerizedBackend(async (backend, tempDir) => {
|
|
// Set up workspace
|
|
const testWorkspace = {
|
|
remote: backend.baseUrl,
|
|
workspaceId: backend.workspace,
|
|
name: "includes_test",
|
|
token: backend.token
|
|
};
|
|
await addWorkspace(testWorkspace, { force: true, configDir: backend.testConfigDir });
|
|
|
|
// Create wmill.yaml with override that only includes specific path
|
|
const backendUrl = new URL(backend.baseUrl).toString();
|
|
await Deno.writeTextFile(`${tempDir}/wmill.yaml`, `defaultTs: bun
|
|
includes:
|
|
- "**"
|
|
|
|
overrides:
|
|
"${backendUrl}:${backend.workspace}:u/test/test_repo":
|
|
includes:
|
|
- "u/admin/**" # Only include admin resources, exclude f/** apps/scripts`);
|
|
|
|
// Run sync pull to write files
|
|
const result = await backend.runCLICommand([
|
|
'sync', 'pull',
|
|
'--repository', 'u/test/test_repo',
|
|
'--yes'
|
|
], tempDir);
|
|
|
|
assertEquals(result.code, 0, `Sync pull should succeed: ${result.stderr}`);
|
|
|
|
// Verify admin files were written (since we have includes: ["u/admin/**"])
|
|
const adminFiles = [];
|
|
try {
|
|
for await (const entry of Deno.readDir(`${tempDir}/u/admin`)) {
|
|
if (entry.isFile) {
|
|
adminFiles.push(`u/admin/${entry.name}`);
|
|
}
|
|
}
|
|
} catch {
|
|
// Directory might not exist if no files matched
|
|
}
|
|
|
|
// We expect admin files to be written since backend has u/admin/test_config variable
|
|
assert(adminFiles.length > 0, `Admin files should be written due to includes override. Expected u/admin files but found: ${adminFiles.join(', ')}`);
|
|
|
|
// Verify f/** files were NOT written due to includes override
|
|
let fDirectoryExists = false;
|
|
try {
|
|
await Deno.stat(`${tempDir}/f`);
|
|
fDirectoryExists = true;
|
|
} catch {
|
|
// Directory doesn't exist, which is expected
|
|
}
|
|
|
|
assertEquals(fDirectoryExists, false, "f/ directory should not exist due to includes override excluding f/**");
|
|
});
|
|
}); |