feat(regions): move project automations (#3925)

* feat(regions): repo functions for copying project branches and commits

* chore(regions): wire up move to resolver

* chore(regions): successful basic test of project region change

* fix(regions): sabrina carpenter please please please

* fix(regions): repair multiregion test setup

* chore(regions): appease ts

* chore(multiregion): update test multiregion config

* chore(multiregion): fix test docker config and test

* chore(multiregion): use transaction

* chore(multiregion): maybe this will work

* fix(multiregion): drop subs synchronously

* chore(multiregion): desperate test logs

* chore(multiregion): somehow that worked?

* chore(multiregion): add load-bearing log statement

* chore(multiregion): move services

* fix(multiregion): test drop waits

* chore(regions): fix import

* chore(regions): make test a bit more thorough for good measure

* fix(regions): move project objects

* chore(regions): add tests for object move

* feat(regions): move project automations

* chore(regions): add tests for moving automations

* chore(regions): more tests for moving automate data

* fix(regions): speed up inserts

* fix(regions): simplify postgres usage

* chore(regions): repair build

* fix(regions): improve queries

* chore(regions): again
This commit is contained in:
Chuck Driesler
2025-02-18 15:48:00 +00:00
committed by GitHub
parent 974598b1fd
commit 86c113b29b
14 changed files with 469 additions and 47 deletions
@@ -1,8 +1,12 @@
import {
getAutomationFactory,
getFullAutomationRevisionMetadataFactory,
getFullAutomationRunByIdFactory,
getLatestAutomationRevisionFactory,
storeAutomationFactory,
storeAutomationRevisionFactory,
storeAutomationTokenFactory
storeAutomationTokenFactory,
upsertAutomationRunFactory
} from '@/modules/automate/repositories/automations'
import {
CreateAutomationRevisionDeps,
@@ -15,6 +19,7 @@ import cryptoRandomString from 'crypto-random-string'
import { createAutomation as clientCreateAutomation } from '@/modules/automate/clients/executionEngine'
import {
getBranchesByIdsFactory,
getBranchLatestCommitsFactory,
getLatestStreamBranchFactory
} from '@/modules/core/repositories/branches'
@@ -35,6 +40,7 @@ import {
import { faker } from '@faker-js/faker'
import {
getEncryptionKeyPair,
getEncryptionKeyPairFor,
getFunctionInputDecryptorFactory
} from '@/modules/automate/services/encryption'
import { buildDecryptor } from '@/modules/shared/utils/libsodium'
@@ -42,22 +48,28 @@ import { db } from '@/db/knex'
import { validateStreamAccessFactory } from '@/modules/core/services/streams/access'
import { authorizeResolver } from '@/modules/shared'
import { getEventBus } from '@/modules/shared/services/eventBus'
import { getProjectDbClient } from '@/modules/multiregion/utils/dbSelector'
import { Knex } from 'knex'
import { createTestAutomationRunFactory } from '@/modules/automate/services/trigger'
const storeAutomation = storeAutomationFactory({ db })
const storeAutomationToken = storeAutomationTokenFactory({ db })
const storeAutomationRevision = storeAutomationRevisionFactory({ db })
const getAutomation = getAutomationFactory({ db })
const getLatestStreamBranch = getLatestStreamBranchFactory({ db })
const validateStreamAccess = validateStreamAccessFactory({ authorizeResolver })
export const generateFunctionId = () => cryptoRandomString({ length: 10 })
export const generateFunctionReleaseId = () => cryptoRandomString({ length: 10 })
/**
* @param overrides By default, we mock requests to the execution engine. You can replace those mocks here.
*/
export const buildAutomationCreate = (
overrides?: Partial<{
createDbAutomation: typeof clientCreateAutomation
}>
params: {
dbClient?: Knex
overrides?: Partial<{
createDbAutomation: typeof clientCreateAutomation
}>
} = {}
) => {
const { dbClient = db, overrides } = params
const create = createAutomationFactory({
createAuthCode: createStoredAuthCodeFactory({ redis: createInmemoryRedisClient() }),
automateCreateAutomation:
@@ -66,8 +78,8 @@ export const buildAutomationCreate = (
automationId: cryptoRandomString({ length: 10 }),
token: cryptoRandomString({ length: 10 })
})),
storeAutomation,
storeAutomationToken,
storeAutomation: storeAutomationFactory({ db: dbClient }),
storeAutomationToken: storeAutomationTokenFactory({ db: dbClient }),
validateStreamAccess,
eventEmit: getEventBus().emit
})
@@ -75,9 +87,17 @@ export const buildAutomationCreate = (
return create
}
/**
* @param overrides By default, we mock requests to the execution engine. You can replace those mocks here.
*/
export const buildAutomationRevisionCreate = (
overrides?: Partial<CreateAutomationRevisionDeps>
params: {
dbClient?: Knex
overrides?: Partial<CreateAutomationRevisionDeps>
} = {}
) => {
const { dbClient = db, overrides } = params
const fakeGetRelease = (params: {
functionReleaseId: string
functionId: string
@@ -91,9 +111,9 @@ export const buildAutomationRevisionCreate = (
})
const create = createAutomationRevisionFactory({
getAutomation,
storeAutomationRevision,
getBranchesByIds: getBranchesByIdsFactory({ db }),
getAutomation: getAutomationFactory({ db: dbClient }),
storeAutomationRevision: storeAutomationRevisionFactory({ db: dbClient }),
getBranchesByIds: getBranchesByIdsFactory({ db: dbClient }),
getFunctionRelease: async (params) => fakeGetRelease(params),
getFunctionReleases: async (params) => params.ids.map(fakeGetRelease),
getEncryptionKeyPair,
@@ -128,8 +148,10 @@ export const createTestAutomation = async (params: {
revision: { input: revisionInput, functionReleaseId, functionId } = {}
} = params
const createAutomation = buildAutomationCreate()
const createRevision = buildAutomationRevisionCreate()
const projectDb = await getProjectDbClient({ projectId })
const createAutomation = buildAutomationCreate({ dbClient: projectDb })
const createRevision = buildAutomationRevisionCreate({ dbClient: projectDb })
const automationRet = await createAutomation({
input: {
@@ -143,7 +165,7 @@ export const createTestAutomation = async (params: {
let revisionRet: Awaited<ReturnType<typeof createRevision>> | null = null
if (functionReleaseId?.length && functionId?.length) {
const firstModel = await getLatestStreamBranch(projectId)
const firstModel = await getLatestStreamBranchFactory({ db: projectDb })(projectId)
if (!firstModel)
throw new Error(
@@ -186,6 +208,55 @@ export type TestAutomationWithRevision = Awaited<
ReturnType<typeof createTestAutomation>
>
export const createTestAutomationRun = async (params: {
userId: string
projectId: string
automationId: string
}) => {
const { userId, projectId, automationId } = params
const projectDb = await getProjectDbClient({ projectId })
const { automationRunId } = await createTestAutomationRunFactory({
getEncryptionKeyPairFor,
getFunctionInputDecryptor: getFunctionInputDecryptorFactory({
buildDecryptor
}),
getAutomation: getAutomationFactory({
db: projectDb
}),
getLatestAutomationRevision: getLatestAutomationRevisionFactory({
db: projectDb
}),
getFullAutomationRevisionMetadata: getFullAutomationRevisionMetadataFactory({
db: projectDb
}),
upsertAutomationRun: upsertAutomationRunFactory({
db: projectDb
}),
getBranchLatestCommits: getBranchLatestCommitsFactory({
db: projectDb
}),
validateStreamAccess
})({ projectId, automationId, userId })
const automationRunData = await getFullAutomationRunByIdFactory({ db: projectDb })(
automationRunId
)
if (!automationRunData) {
throw new Error('Failed to create test automation run!')
}
const { triggers, functionRuns, ...automationRun } = automationRunData
return {
automationRun,
functionRuns,
triggers
}
}
export const truncateAutomations = async () => {
await truncateTables([
AutomationRunTriggers.name,