Skip to content

Commit 2efa0d7

Browse files
fix(scripts): support production workflow backfill
1 parent 0e9c9ea commit 2efa0d7

2 files changed

Lines changed: 51 additions & 32 deletions

File tree

apps/sim/scripts/backfill-table-workflow-deployments.test.ts

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,31 @@ describe('backfillTableWorkflowDeployments', () => {
8282
restoreEnvironmentVariable('SIM_ENV_SECRET_ID')
8383
})
8484

85-
it('loads the staging runtime secret before database modules are needed', async () => {
86-
Reflect.deleteProperty(process.env, 'DATABASE_URL')
87-
Reflect.deleteProperty(process.env, 'DATABASE_URL_WEB')
88-
Reflect.deleteProperty(process.env, 'REDIS_TLS_SERVERNAME')
89-
Reflect.deleteProperty(process.env, 'REDIS_URL')
90-
Reflect.deleteProperty(process.env, 'SIM_ENV_SECRET_ID')
91-
mockLoadRuntimeSecrets.mockImplementation(async () => {
92-
process.env.DATABASE_URL = 'postgres://staging/database'
93-
process.env.REDIS_TLS_SERVERNAME = 'cache.staging.internal'
94-
process.env.REDIS_URL = 'rediss://cache.staging.internal:6379'
95-
})
96-
97-
await prepareTableWorkflowDeploymentBackfillEnvironment(['--environment=staging'])
98-
99-
expect(process.env.SIM_ENV_SECRET_ID).toBe('/staging/sim/env-vars')
100-
expect(process.env.REDIS_TLS_SERVERNAME).toBeUndefined()
101-
expect(process.env.REDIS_URL).toBeUndefined()
102-
expect(mockLoadRuntimeSecrets).toHaveBeenCalledTimes(1)
103-
})
85+
it.each([
86+
['production', '/production/sim/env-vars'],
87+
['staging', '/staging/sim/env-vars'],
88+
] as const)(
89+
'loads the %s runtime secret before database modules are needed',
90+
async (environment, runtimeSecretId) => {
91+
Reflect.deleteProperty(process.env, 'DATABASE_URL')
92+
Reflect.deleteProperty(process.env, 'DATABASE_URL_WEB')
93+
Reflect.deleteProperty(process.env, 'REDIS_TLS_SERVERNAME')
94+
Reflect.deleteProperty(process.env, 'REDIS_URL')
95+
Reflect.deleteProperty(process.env, 'SIM_ENV_SECRET_ID')
96+
mockLoadRuntimeSecrets.mockImplementation(async () => {
97+
process.env.DATABASE_URL = `postgres://${environment}/database`
98+
process.env.REDIS_TLS_SERVERNAME = `cache.${environment}.internal`
99+
process.env.REDIS_URL = `rediss://cache.${environment}.internal:6379`
100+
})
101+
102+
await prepareTableWorkflowDeploymentBackfillEnvironment([`--environment=${environment}`])
103+
104+
expect(process.env.SIM_ENV_SECRET_ID).toBe(runtimeSecretId)
105+
expect(process.env.REDIS_TLS_SERVERNAME).toBeUndefined()
106+
expect(process.env.REDIS_URL).toBeUndefined()
107+
expect(mockLoadRuntimeSecrets).toHaveBeenCalledTimes(1)
108+
}
109+
)
104110

105111
it('keeps the existing local DATABASE_URL mode when no environment is requested', async () => {
106112
process.env.DATABASE_URL = 'postgres://local/database'
@@ -114,8 +120,8 @@ describe('backfillTableWorkflowDeployments', () => {
114120
})
115121

116122
it('rejects unsupported, unknown, duplicate, and locally configured staging arguments', async () => {
117-
expect(() => parseTableWorkflowDeploymentBackfillArgs(['--environment=production'])).toThrow(
118-
'Unsupported backfill environment: production'
123+
expect(() => parseTableWorkflowDeploymentBackfillArgs(['--environment=prod'])).toThrow(
124+
'Unsupported backfill environment: prod'
119125
)
120126
expect(() => parseTableWorkflowDeploymentBackfillArgs(['--dry-run'])).toThrow(
121127
'Unknown argument: --dry-run'

apps/sim/scripts/backfill-table-workflow-deployments.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* Usage:
1313
* DATABASE_URL=... bun run apps/sim/scripts/backfill-table-workflow-deployments.ts
1414
* AWS_PROFILE=sim-admin bun --no-env-file apps/sim/scripts/backfill-table-workflow-deployments.ts --environment=staging
15+
* AWS_PROFILE=sim-admin bun --no-env-file apps/sim/scripts/backfill-table-workflow-deployments.ts --environment=production
1516
*/
1617

1718
import { createLogger } from '@sim/logger'
@@ -25,12 +26,17 @@ const logger = createLogger('BackfillTableWorkflowDeployments')
2526
export const TABLE_WORKFLOW_DEPLOYMENT_BATCH_SIZE = 25
2627
const BACKFILL_ACTOR_ID = 'table-workflow-deployment-backfill'
2728
const BACKFILL_OPERATION_VERSION = 'v2'
28-
const STAGING_RUNTIME_SECRET_ID = '/staging/sim/env-vars'
29-
/** Container-private services that a locally executed staging backfill must not initialize. */
30-
const LOCAL_STAGING_OMITTED_VARIABLES = ['REDIS_URL', 'REDIS_TLS_SERVERNAME'] as const
29+
const RUNTIME_SECRET_IDS = {
30+
production: '/production/sim/env-vars',
31+
staging: '/staging/sim/env-vars',
32+
} as const
33+
/** Container-private services that a locally executed hosted backfill must not initialize. */
34+
const LOCAL_HOSTED_OMITTED_VARIABLES = ['REDIS_URL', 'REDIS_TLS_SERVERNAME'] as const
35+
36+
type TableWorkflowDeploymentBackfillEnvironment = keyof typeof RUNTIME_SECRET_IDS
3137

3238
interface TableWorkflowDeploymentBackfillCliOptions {
33-
environment?: 'staging'
39+
environment?: TableWorkflowDeploymentBackfillEnvironment
3440
}
3541

3642
export interface TableWorkflowDeploymentCandidate {
@@ -95,6 +101,12 @@ interface DeploymentStateRow extends Record<string, unknown> {
95101
is_deployed: boolean
96102
}
97103

104+
function isTableWorkflowDeploymentBackfillEnvironment(
105+
value: string
106+
): value is TableWorkflowDeploymentBackfillEnvironment {
107+
return Object.hasOwn(RUNTIME_SECRET_IDS, value)
108+
}
109+
98110
/** Parses the deliberately small CLI surface for the backfill. */
99111
export function parseTableWorkflowDeploymentBackfillArgs(
100112
args: readonly string[]
@@ -110,7 +122,7 @@ export function parseTableWorkflowDeploymentBackfillArgs(
110122
}
111123

112124
const requestedEnvironment = arg.slice('--environment='.length)
113-
if (requestedEnvironment !== 'staging') {
125+
if (!isTableWorkflowDeploymentBackfillEnvironment(requestedEnvironment)) {
114126
throw new Error(`Unsupported backfill environment: ${requestedEnvironment || '(empty)'}`)
115127
}
116128
environment = requestedEnvironment
@@ -126,10 +138,11 @@ export async function prepareTableWorkflowDeploymentBackfillEnvironment(
126138
const { environment } = parseTableWorkflowDeploymentBackfillArgs(args)
127139
if (!environment) return
128140

141+
const runtimeSecretId = RUNTIME_SECRET_IDS[environment]
129142
const configuredSecretId = process.env.SIM_ENV_SECRET_ID
130-
if (configuredSecretId && configuredSecretId !== STAGING_RUNTIME_SECRET_ID) {
143+
if (configuredSecretId && configuredSecretId !== runtimeSecretId) {
131144
throw new Error(
132-
`SIM_ENV_SECRET_ID is already set to ${configuredSecretId}; expected ${STAGING_RUNTIME_SECRET_ID}`
145+
`SIM_ENV_SECRET_ID is already set to ${configuredSecretId}; expected ${runtimeSecretId}`
133146
)
134147
}
135148

@@ -138,18 +151,18 @@ export async function prepareTableWorkflowDeploymentBackfillEnvironment(
138151
)
139152
if (configuredDatabaseVariables.length > 0) {
140153
throw new Error(
141-
`Unset ${configuredDatabaseVariables.join(', ')} before using --environment=staging so local configuration cannot override staging`
154+
`Unset ${configuredDatabaseVariables.join(', ')} before using --environment=${environment} so local configuration cannot override ${environment}`
142155
)
143156
}
144157

145-
process.env.SIM_ENV_SECRET_ID = STAGING_RUNTIME_SECRET_ID
158+
process.env.SIM_ENV_SECRET_ID = runtimeSecretId
146159
await loadRuntimeSecrets()
147160

148161
if (!process.env.DATABASE_URL && !process.env.DATABASE_URL_WEB) {
149-
throw new Error(`${STAGING_RUNTIME_SECRET_ID} did not provide a database URL`)
162+
throw new Error(`${runtimeSecretId} did not provide a database URL`)
150163
}
151164

152-
for (const key of LOCAL_STAGING_OMITTED_VARIABLES) {
165+
for (const key of LOCAL_HOSTED_OMITTED_VARIABLES) {
153166
Reflect.deleteProperty(process.env, key)
154167
}
155168
}

0 commit comments

Comments
 (0)