|
1 | 1 | import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'fs'; |
2 | 2 | import { tmpdir } from 'os'; |
3 | | -import { dirname, join } from 'path'; |
| 3 | +import { dirname, join, resolve } from 'path'; |
4 | 4 | import { fileURLToPath } from 'url'; |
5 | 5 | import { afterEach, describe, expect, it } from 'bun:test'; |
6 | 6 | import { |
| 7 | + formatTemporalTarget, |
7 | 8 | getScriptDatabaseTarget, |
| 9 | + getScriptTemporalTarget, |
8 | 10 | readActiveInstance, |
9 | 11 | redactConnectionString, |
10 | | -} from '../lib/script-database-target'; |
| 12 | +} from '../../../scripts/lib/local-script-runtime'; |
11 | 13 |
|
12 | 14 | let cleanupDirs: string[] = []; |
13 | 15 | const scriptsDir = dirname(dirname(fileURLToPath(import.meta.url))); |
| 16 | +const repoRoot = resolve(scriptsDir, '..', '..'); |
14 | 17 |
|
15 | 18 | function createRootWithInstance(instance: string): string { |
16 | 19 | const root = mkdtempSync(join(tmpdir(), 'sentris-script-db-target-')); |
@@ -97,19 +100,105 @@ describe('script database target resolver', () => { |
97 | 100 | ).toBe('postgresql://sentris:***@localhost:5433/sentris_instance_0'); |
98 | 101 | }); |
99 | 102 |
|
| 103 | + it('uses the active instance instead of stale Temporal env for local scripts', () => { |
| 104 | + const target = getScriptTemporalTarget({ |
| 105 | + env: { |
| 106 | + SENTRIS_INSTANCE: '4', |
| 107 | + TEMPORAL_NAMESPACE: 'sentris-dev', |
| 108 | + TEMPORAL_TASK_QUEUE: 'sentris-default', |
| 109 | + }, |
| 110 | + repoRoot: createRootWithInstance('2'), |
| 111 | + }); |
| 112 | + |
| 113 | + expect(target.namespace).toBe('sentris-dev-4'); |
| 114 | + expect(target.taskQueue).toBe('sentris-dev-4'); |
| 115 | + expect(target.source).toBe('env:SENTRIS_INSTANCE'); |
| 116 | + expect(target.ignoredTemporalEnv).toBe(true); |
| 117 | + expect(formatTemporalTarget(target)).toContain( |
| 118 | + 'TEMPORAL_NAMESPACE/TEMPORAL_TASK_QUEUE ignored', |
| 119 | + ); |
| 120 | + }); |
| 121 | + |
| 122 | + it('allows script-specific Temporal overrides when intentionally targeting another namespace', () => { |
| 123 | + const target = getScriptTemporalTarget({ |
| 124 | + namespaceOverrideEnvVar: 'WORKFLOW_RUNNER_TEMPORAL_NAMESPACE', |
| 125 | + taskQueueOverrideEnvVar: 'WORKFLOW_RUNNER_TEMPORAL_TASK_QUEUE', |
| 126 | + env: { |
| 127 | + SENTRIS_INSTANCE: '4', |
| 128 | + SENTRIS_SCRIPT_TEMPORAL_NAMESPACE: 'generic-namespace', |
| 129 | + SENTRIS_SCRIPT_TEMPORAL_TASK_QUEUE: 'generic-task-queue', |
| 130 | + WORKFLOW_RUNNER_TEMPORAL_NAMESPACE: 'manual-namespace', |
| 131 | + WORKFLOW_RUNNER_TEMPORAL_TASK_QUEUE: 'manual-task-queue', |
| 132 | + }, |
| 133 | + repoRoot: createRootWithInstance('2'), |
| 134 | + }); |
| 135 | + |
| 136 | + expect(target.namespace).toBe('manual-namespace'); |
| 137 | + expect(target.taskQueue).toBe('manual-task-queue'); |
| 138 | + expect(target.source).toBe( |
| 139 | + 'env:WORKFLOW_RUNNER_TEMPORAL_NAMESPACE/env:WORKFLOW_RUNNER_TEMPORAL_TASK_QUEUE', |
| 140 | + ); |
| 141 | + }); |
| 142 | + |
100 | 143 | it('prevents backend maintenance scripts from reading DATABASE_URL directly', () => { |
101 | 144 | const scriptFiles = readdirSync(scriptsDir) |
102 | 145 | .filter((file) => file.endsWith('.ts')) |
103 | 146 | .filter((file) => file !== 'generate-openapi.ts' && file !== 'version-check-summary.ts'); |
104 | 147 |
|
105 | 148 | for (const file of scriptFiles) { |
106 | 149 | const source = readFileSync(join(scriptsDir, file), 'utf-8'); |
107 | | - expect(source, `${file} should use script-database-target.ts`).not.toContain( |
| 150 | + expect(source, `${file} should use local-script-runtime.ts`).not.toContain( |
108 | 151 | 'process.env.DATABASE_URL', |
109 | 152 | ); |
110 | 153 | expect(source, `${file} should not fall back to the legacy sentris database`).not.toContain( |
111 | 154 | 'postgresql://sentris:sentris@localhost:5433/sentris', |
112 | 155 | ); |
113 | 156 | } |
114 | 157 | }); |
| 158 | + |
| 159 | + it('prevents all local database maintenance scripts from reading DATABASE_URL directly', () => { |
| 160 | + const databaseScriptFiles = [ |
| 161 | + join(scriptsDir, 'delete-all-workflow-runs.ts'), |
| 162 | + join(scriptsDir, 'migration-smoke.ts'), |
| 163 | + join(scriptsDir, 'seed-stress-test.ts'), |
| 164 | + join(scriptsDir, 'seed-templates.ts'), |
| 165 | + join(repoRoot, 'worker', 'scripts', 'run-long-lived-workflow.ts'), |
| 166 | + join(repoRoot, 'worker', 'scripts', 'workflow-execute-inline.ts'), |
| 167 | + join(repoRoot, 'worker', 'scripts', 'workflow-runner.ts'), |
| 168 | + ]; |
| 169 | + |
| 170 | + for (const file of databaseScriptFiles) { |
| 171 | + const source = readFileSync(file, 'utf-8'); |
| 172 | + expect(source, `${file} should use the shared script database resolver`).toContain( |
| 173 | + 'getScriptDatabaseTarget', |
| 174 | + ); |
| 175 | + expect(source, `${file} should not read DATABASE_URL directly`).not.toContain( |
| 176 | + 'process.env.DATABASE_URL', |
| 177 | + ); |
| 178 | + expect(source, `${file} should not fall back to the legacy sentris database`).not.toContain( |
| 179 | + 'postgresql://sentris:sentris@localhost:5433/sentris', |
| 180 | + ); |
| 181 | + } |
| 182 | + }); |
| 183 | + |
| 184 | + it('prevents local Temporal scripts from reading stale Temporal env directly', () => { |
| 185 | + const temporalScriptFiles = [ |
| 186 | + join(repoRoot, 'worker', 'scripts', 'benchmark-scheduler.ts'), |
| 187 | + join(repoRoot, 'worker', 'scripts', 'run-long-lived-workflow.ts'), |
| 188 | + join(repoRoot, 'worker', 'scripts', 'workflow-runner.ts'), |
| 189 | + ]; |
| 190 | + |
| 191 | + for (const file of temporalScriptFiles) { |
| 192 | + const source = readFileSync(file, 'utf-8'); |
| 193 | + expect(source, `${file} should use the shared script Temporal resolver`).toContain( |
| 194 | + 'getScriptTemporalTarget', |
| 195 | + ); |
| 196 | + expect(source, `${file} should not read TEMPORAL_NAMESPACE directly`).not.toContain( |
| 197 | + 'process.env.TEMPORAL_NAMESPACE', |
| 198 | + ); |
| 199 | + expect(source, `${file} should not read TEMPORAL_TASK_QUEUE directly`).not.toContain( |
| 200 | + 'process.env.TEMPORAL_TASK_QUEUE', |
| 201 | + ); |
| 202 | + } |
| 203 | + }); |
115 | 204 | }); |
0 commit comments