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,4 +1,23 @@
import { db } from '@/db/knex'
import {
AutomationFunctionRunRecord,
AutomationRecord,
AutomationRevisionFunctionRecord,
AutomationRevisionRecord,
AutomationRunRecord,
AutomationRunTriggerRecord,
AutomationTokenRecord,
AutomationTriggerDefinitionRecord
} from '@/modules/automate/helpers/types'
import {
AutomationFunctionRuns,
AutomationRevisionFunctions,
AutomationRevisions,
AutomationRuns,
AutomationRunTriggers,
AutomationTokens,
AutomationTriggers
} from '@/modules/core/dbSchema'
import { AllScopes } from '@/modules/core/helpers/mainConstants'
import { createRandomEmail } from '@/modules/core/helpers/testHelpers'
import {
@@ -35,6 +54,10 @@ import {
TestApolloServer
} from '@/test/graphqlHelper'
import { beforeEachContext } from '@/test/hooks'
import {
createTestAutomation,
createTestAutomationRun
} from '@/test/speckle-helpers/automationHelper'
import { BasicTestBranch, createTestBranch } from '@/test/speckle-helpers/branchHelper'
import {
BasicTestCommit,
@@ -58,7 +81,20 @@ const tables = {
versions: (db: Knex) => db.table<CommitRecord>('commits'),
streamCommits: (db: Knex) => db.table<StreamCommitRecord>('stream_commits'),
branchCommits: (db: Knex) => db.table<BranchCommitRecord>('branch_commits'),
objects: (db: Knex) => db.table<ObjectRecord>('objects')
objects: (db: Knex) => db.table<ObjectRecord>('objects'),
automations: (db: Knex) => db.table<AutomationRecord>('automations'),
automationTokens: (db: Knex) => db<AutomationTokenRecord>(AutomationTokens.name),
automationRevisions: (db: Knex) =>
db<AutomationRevisionRecord>(AutomationRevisions.name),
automationTriggers: (db: Knex) =>
db<AutomationTriggerDefinitionRecord>(AutomationTriggers.name),
automationRevisionFunctions: (db: Knex) =>
db<AutomationRevisionFunctionRecord>(AutomationRevisionFunctions.name),
automationRuns: (db: Knex) => db<AutomationRunRecord>(AutomationRuns.name),
automationRunTriggers: (db: Knex) =>
db<AutomationRunTriggerRecord>(AutomationRunTriggers.name),
automationFunctionRuns: (db: Knex) =>
db<AutomationFunctionRunRecord>(AutomationFunctionRuns.name)
}
const grantStreamPermissions = grantStreamPermissionsFactory({ db })
@@ -344,6 +380,12 @@ isMultiRegionTestMode()
authorId: ''
}
let testAutomation: AutomationRecord
let testAutomationToken: AutomationTokenRecord
let testAutomationRevision: AutomationRevisionRecord
let testAutomationRun: AutomationRunRecord
let testAutomationFunctionRuns: AutomationFunctionRunRecord[]
let apollo: TestApolloServer
let targetRegionDb: Knex
@@ -382,6 +424,32 @@ isMultiRegionTestMode()
owner: adminUser,
stream: testProject
})
const { automation, revision } = await createTestAutomation({
userId: adminUser.id,
projectId: testProject.id,
revision: {
functionId: cryptoRandomString({ length: 9 }),
functionReleaseId: cryptoRandomString({ length: 9 })
}
})
if (!revision) {
throw new Error('Failed to create automation revision.')
}
testAutomation = automation.automation
testAutomationToken = automation.token
testAutomationRevision = revision
const { automationRun, functionRuns } = await createTestAutomationRun({
userId: adminUser.id,
projectId: testProject.id,
automationId: testAutomation.id
})
testAutomationRun = automationRun
testAutomationFunctionRuns = functionRuns
})
it('moves project record to target regional db', async () => {
@@ -468,5 +536,83 @@ isMultiRegionTestMode()
expect(object).to.not.be.undefined
})
it('moves project automation data to target regional db', async () => {
const res = await apollo.execute(UpdateProjectRegionDocument, {
projectId: testProject.id,
regionKey: regionKey2
})
expect(res).to.not.haveGraphQLErrors()
// TODO: Replace with gql query when possible
const automation = await tables
.automations(targetRegionDb)
.select('*')
.where({ id: testAutomation.id })
.first()
expect(automation).to.not.be.undefined
const automationToken = await tables
.automationTokens(targetRegionDb)
.select('*')
.where({ automationId: testAutomation.id })
.first()
expect(automationToken).to.not.be.undefined
expect(automationToken?.automateToken).to.equal(
testAutomationToken.automateToken
)
const automationRevision = await tables
.automationRevisions(targetRegionDb)
.select('*')
.where({ automationId: testAutomation.id })
.first()
expect(automationRevision).to.not.be.undefined
expect(automationRevision?.id).to.equal(testAutomationRevision.id)
const automationTrigger = await tables
.automationTriggers(targetRegionDb)
.select('*')
.where({ automationRevisionId: testAutomationRevision.id })
.first()
expect(automationTrigger).to.not.be.undefined
})
it('moves project automation runs to target regional db', async () => {
const res = await apollo.execute(UpdateProjectRegionDocument, {
projectId: testProject.id,
regionKey: regionKey2
})
expect(res).to.not.haveGraphQLErrors()
// TODO: Replace with gql query when possible
const automationRun = await tables
.automationRuns(targetRegionDb)
.select('*')
.where({ id: testAutomationRun.id })
.first()
expect(automationRun).to.not.be.undefined
const automationRunTriggers = await tables
.automationRunTriggers(targetRegionDb)
.select('*')
.where({ automationRunId: testAutomationRun.id })
expect(automationRunTriggers.length).to.not.equal(0)
const automationFunctionRuns = await tables
.automationFunctionRuns(targetRegionDb)
.select('*')
.where({ runId: testAutomationRun.id })
expect(automationFunctionRuns.length).to.equal(
testAutomationFunctionRuns.length
)
expect(
automationFunctionRuns.every((run) =>
testAutomationFunctionRuns.some((testRun) => testRun.id === run.id)
)
)
})
})
: void 0