Introducing the concept of flagging an automation as 'in test' which means it can run with triggers and everything as it normally would in development.

This commit is contained in:
mike12345567 2021-09-10 14:37:34 +01:00
parent 84cdec5907
commit 3eeb7c27b8
6 changed files with 39 additions and 20 deletions

View File

@ -13,6 +13,7 @@ exports.Databases = {
DEBOUNCE: "debounce",
SESSIONS: "session",
USER_CACHE: "users",
FLAGS: "flags",
}
exports.SEPARATOR = SEPARATOR

View File

@ -7,6 +7,7 @@ const {
checkForWebhooks,
updateTestHistory,
} = require("../../automations/utils")
const { setTestFlag, clearTestFlag } = require("../../utilities/redis")
/*************************
* *
@ -163,6 +164,7 @@ exports.test = async function (ctx) {
const appId = ctx.appId
const db = new CouchDB(appId)
let automation = await db.get(ctx.params.id)
await setTestFlag(automation._id)
const response = await triggers.externalTrigger(
automation,
{
@ -176,5 +178,6 @@ exports.test = async function (ctx) {
...ctx.request.body,
occurredAt: new Date().toISOString(),
})
await clearTestFlag(automation._id)
ctx.body = response
}

View File

@ -2,7 +2,7 @@ const {
checkBuilderEndpoint,
getAllTableRows,
clearAllAutomations,
triggerAutomation,
testAutomation,
} = require("./utilities/TestFunctions")
const setup = require("./utilities")
const { basicAutomation } = setup.structures
@ -160,14 +160,13 @@ describe("/automations", () => {
automation.definition.steps[0].inputs.row.tableId = table._id
automation = await config.createAutomation(automation)
await setup.delay(500)
const res = await triggerAutomation(config, automation)
const res = await testAutomation(config, automation)
// this looks a bit mad but we don't actually have a way to wait for a response from the automation to
// know that it has finished all of its actions - this is currently the best way
// also when this runs in CI it is very temper-mental so for now trying to make run stable by repeating until it works
// TODO: update when workflow logs are a thing
for (let tries = 0; tries < MAX_RETRIES; tries++) {
expect(res.body.message).toEqual(`Automation ${automation._id} has been triggered.`)
expect(res.body.automation.name).toEqual(automation.name)
expect(res.body).toBeDefined()
await setup.delay(500)
let elements = await getAllTableRows(config)
// don't test it unless there are values to test

View File

@ -102,19 +102,15 @@ exports.getDB = config => {
return new CouchDB(config.getAppId())
}
exports.triggerAutomation = async (config, automation) => {
return await config.request
.post(`/api/automations/${automation._id}/trigger`)
.send({ name: "Test", description: "TEST" })
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
}
exports.testAutomation = async (config, automation) => {
return await config.request
.post(`/api/automations/${automation._id}/test`)
.send({ name: "Test", description: "TEST" })
.send({
row: {
name: "Test",
description: "TEST",
},
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)

View File

@ -7,6 +7,7 @@ const { isDevAppID } = require("../db/utils")
// need this to call directly, so we can get a response
const { processEvent } = require("./utils")
const { queue } = require("./bullboard")
const { checkTestFlag } = require("../utilities/redis")
const TRIGGER_DEFINITIONS = definitions
@ -14,11 +15,7 @@ async function queueRelevantRowAutomations(event, eventType) {
if (event.appId == null) {
throw `No appId specified for ${eventType} - check event emitters.`
}
// don't queue events which are for dev apps, only way to test automations is
// running tests on them
if (isDevAppID(event.appId)) {
return
}
const db = new CouchDB(event.appId)
let automations = await db.allDocs(
getAutomationParams(null, { include_docs: true })
@ -33,6 +30,12 @@ async function queueRelevantRowAutomations(event, eventType) {
})
for (let automation of automations) {
// don't queue events which are for dev apps, only way to test automations is
// running tests on them
// in production the test flag will never be checked due to lazy evaluation (first always false)
if (isDevAppID(event.appId) && !(await checkTestFlag(automation._id))) {
return
}
let automationDef = automation.definition
let automationTrigger = automationDef ? automationDef.trigger : {}
if (

View File

@ -2,20 +2,24 @@ const { Client, utils } = require("@budibase/auth/redis")
const { getGlobalIDFromUserMetadataID } = require("../db/utils")
const APP_DEV_LOCK_SECONDS = 600
let devAppClient, debounceClient
const AUTOMATION_TEST_FLAG_SECONDS = 60
let devAppClient, debounceClient, flagClient
// we init this as we want to keep the connection open all the time
// reduces the performance hit
exports.init = async () => {
devAppClient = new Client(utils.Databases.DEV_LOCKS)
debounceClient = new Client(utils.Databases.DEBOUNCE)
flagClient = new Client(utils.Databases.FLAGS)
await devAppClient.init()
await debounceClient.init()
await flagClient.init()
}
exports.shutdown = async () => {
if (devAppClient) await devAppClient.finish()
if (debounceClient) await debounceClient.finish()
if (flagClient) await flagClient.finish()
}
exports.doesUserHaveLock = async (devAppId, user) => {
@ -67,3 +71,16 @@ exports.checkDebounce = async id => {
exports.setDebounce = async (id, seconds) => {
await debounceClient.store(id, "debouncing", seconds)
}
exports.setTestFlag = async id => {
await flagClient.store(id, { testing: true }, AUTOMATION_TEST_FLAG_SECONDS)
}
exports.checkTestFlag = async id => {
const flag = await flagClient.get(id)
return !!(flag && flag.testing)
}
exports.clearTestFlag = async id => {
await devAppClient.delete(id)
}