Rely on withEnv and setEnv functions in respective environment.ts files.

This commit is contained in:
Sam Rose 2024-08-09 10:30:27 +01:00
parent 858bb77c00
commit 3d590e879e
No known key found for this signature in database
17 changed files with 109 additions and 109 deletions

View File

@ -27,7 +27,7 @@ export * as locks from "./redis/redlockImpl"
export * as utils from "./utils" export * as utils from "./utils"
export * as errors from "./errors" export * as errors from "./errors"
export * as timers from "./timers" export * as timers from "./timers"
export { default as env } from "./environment" export { default as env, withEnv, setEnv } from "./environment"
export * as blacklist from "./blacklist" export * as blacklist from "./blacklist"
export * as docUpdates from "./docUpdates" export * as docUpdates from "./docUpdates"
export * from "./utils/Duration" export * from "./utils/Duration"

View File

@ -1,11 +1,12 @@
const setup = require("./utilities") import { withEnv } from "../../../environment"
const { checkBuilderEndpoint } = require("./utilities/TestFunctions") import { getRequest, getConfig, afterAll as _afterAll } from "./utilities"
import { checkBuilderEndpoint } from "./utilities/TestFunctions"
describe("/api/keys", () => { describe("/api/keys", () => {
let request = setup.getRequest() let request = getRequest()
let config = setup.getConfig() let config = getConfig()
afterAll(setup.afterAll) afterAll(_afterAll)
beforeAll(async () => { beforeAll(async () => {
await config.init() await config.init()
@ -13,7 +14,7 @@ describe("/api/keys", () => {
describe("fetch", () => { describe("fetch", () => {
it("should allow fetching", async () => { it("should allow fetching", async () => {
await config.withEnv({ SELF_HOSTED: "true" }, async () => { await withEnv({ SELF_HOSTED: "true" }, async () => {
const res = await request const res = await request
.get(`/api/keys`) .get(`/api/keys`)
.set(config.defaultHeaders()) .set(config.defaultHeaders())
@ -34,7 +35,7 @@ describe("/api/keys", () => {
describe("update", () => { describe("update", () => {
it("should allow updating a value", async () => { it("should allow updating a value", async () => {
await config.withEnv({ SELF_HOSTED: "true" }, async () => { await withEnv({ SELF_HOSTED: "true" }, async () => {
const res = await request const res = await request
.put(`/api/keys/TEST`) .put(`/api/keys/TEST`)
.send({ .send({

View File

@ -14,7 +14,12 @@ jest.mock("../../../utilities/redis", () => ({
import { checkBuilderEndpoint } from "./utilities/TestFunctions" import { checkBuilderEndpoint } from "./utilities/TestFunctions"
import * as setup from "./utilities" import * as setup from "./utilities"
import { AppStatus } from "../../../db/utils" import { AppStatus } from "../../../db/utils"
import { events, utils, context } from "@budibase/backend-core" import {
events,
utils,
context,
withEnv as withCoreEnv,
} from "@budibase/backend-core"
import env from "../../../environment" import env from "../../../environment"
import { type App } from "@budibase/types" import { type App } from "@budibase/types"
import tk from "timekeeper" import tk from "timekeeper"
@ -353,7 +358,7 @@ describe("/applications", () => {
.delete(`/api/global/roles/${prodAppId}`) .delete(`/api/global/roles/${prodAppId}`)
.reply(200, {}) .reply(200, {})
await config.withCoreEnv({ SQS_SEARCH_ENABLE: "true" }, async () => { await withCoreEnv({ SQS_SEARCH_ENABLE: "true" }, async () => {
await config.api.application.delete(app.appId) await config.api.application.delete(app.appId)
}) })
}) })

View File

@ -1,3 +1,4 @@
import { withEnv } from "../../../environment"
import * as setup from "./utilities" import * as setup from "./utilities"
import { APIError } from "@budibase/types" import { APIError } from "@budibase/types"
@ -28,7 +29,7 @@ describe("/api/applications/:appId/sync", () => {
}) })
it("should reject an upload with a malicious file extension", async () => { it("should reject an upload with a malicious file extension", async () => {
await config.withEnv({ SELF_HOSTED: undefined }, async () => { await withEnv({ SELF_HOSTED: undefined }, async () => {
let resp = (await config.api.attachment.process( let resp = (await config.api.attachment.process(
"ohno.exe", "ohno.exe",
Buffer.from([0]), Buffer.from([0]),
@ -39,7 +40,7 @@ describe("/api/applications/:appId/sync", () => {
}) })
it("should reject an upload with a malicious uppercase file extension", async () => { it("should reject an upload with a malicious uppercase file extension", async () => {
await config.withEnv({ SELF_HOSTED: undefined }, async () => { await withEnv({ SELF_HOSTED: undefined }, async () => {
let resp = (await config.api.attachment.process( let resp = (await config.api.attachment.process(
"OHNO.EXE", "OHNO.EXE",
Buffer.from([0]), Buffer.from([0]),

View File

@ -40,6 +40,7 @@ import _, { merge } from "lodash"
import * as uuid from "uuid" import * as uuid from "uuid"
import { Knex } from "knex" import { Knex } from "knex"
import { InternalTables } from "../../../db/utils" import { InternalTables } from "../../../db/utils"
import { withEnv } from "../../../environment"
const timestamp = new Date("2023-01-26T11:48:57.597Z").toISOString() const timestamp = new Date("2023-01-26T11:48:57.597Z").toISOString()
tk.freeze(timestamp) tk.freeze(timestamp)
@ -1688,7 +1689,7 @@ describe.each([
} }
const row = await config.api.row.save(testTable._id!, draftRow) const row = await config.api.row.save(testTable._id!, draftRow)
await config.withEnv({ SELF_HOSTED: "true" }, async () => { await withEnv({ SELF_HOSTED: "true" }, async () => {
return context.doInAppContext(config.getAppId(), async () => { return context.doInAppContext(config.getAppId(), async () => {
const enriched: Row[] = await outputProcessing(table, [row]) const enriched: Row[] = await outputProcessing(table, [row])
const [targetRow] = enriched const [targetRow] = enriched
@ -2456,7 +2457,7 @@ describe.each([
describe("Formula JS protection", () => { describe("Formula JS protection", () => {
it("should time out JS execution if a single cell takes too long", async () => { it("should time out JS execution if a single cell takes too long", async () => {
await config.withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => { await withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => {
const js = Buffer.from( const js = Buffer.from(
` `
let i = 0; let i = 0;
@ -2494,7 +2495,7 @@ describe.each([
}) })
it("should time out JS execution if a multiple cells take too long", async () => { it("should time out JS execution if a multiple cells take too long", async () => {
await config.withEnv( await withEnv(
{ {
JS_PER_INVOCATION_TIMEOUT_MS: 40, JS_PER_INVOCATION_TIMEOUT_MS: 40,
JS_PER_REQUEST_TIMEOUT_MS: 80, JS_PER_REQUEST_TIMEOUT_MS: 80,

View File

@ -11,6 +11,8 @@ import {
MIN_VALID_DATE, MIN_VALID_DATE,
SQLITE_DESIGN_DOC_ID, SQLITE_DESIGN_DOC_ID,
utils, utils,
withEnv as withCoreEnv,
setEnv as setCoreEnv,
} from "@budibase/backend-core" } from "@budibase/backend-core"
import * as setup from "./utilities" import * as setup from "./utilities"
@ -64,9 +66,9 @@ describe.each([
let rows: Row[] let rows: Row[]
beforeAll(async () => { beforeAll(async () => {
await config.withCoreEnv({ SQS_SEARCH_ENABLE: "true" }, () => config.init()) await withCoreEnv({ SQS_SEARCH_ENABLE: "true" }, () => config.init())
if (isSqs) { if (isSqs) {
envCleanup = config.setCoreEnv({ envCleanup = setCoreEnv({
SQS_SEARCH_ENABLE: "true", SQS_SEARCH_ENABLE: "true",
SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()], SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()],
}) })
@ -2668,7 +2670,7 @@ describe.each([
}) })
it("can still page when the hard limit is hit", async () => { it("can still page when the hard limit is hit", async () => {
await config.withCoreEnv( await withCoreEnv(
{ {
SQL_MAX_ROWS: "6", SQL_MAX_ROWS: "6",
}, },

View File

@ -8,23 +8,24 @@ jest.mock("aws-sdk", () => ({
})), })),
})) }))
const setup = require("./utilities") import { Datasource, SourceName } from "@budibase/types"
const { constants } = require("@budibase/backend-core") import { setEnv } from "../../../environment"
import { getRequest, getConfig, afterAll as _afterAll } from "./utilities"
import { constants } from "@budibase/backend-core"
describe("/static", () => { describe("/static", () => {
let request = setup.getRequest() let request = getRequest()
let config = setup.getConfig() let config = getConfig()
let app let cleanupEnv: () => void
let cleanupEnv
afterAll(() => { afterAll(() => {
setup.afterAll() _afterAll()
cleanupEnv() cleanupEnv()
}) })
beforeAll(async () => { beforeAll(async () => {
cleanupEnv = config.setEnv({ SELF_HOSTED: "true" }) cleanupEnv = setEnv({ SELF_HOSTED: "true" })
app = await config.init() await config.init()
}) })
describe("/app", () => { describe("/app", () => {
@ -49,7 +50,7 @@ describe("/static", () => {
delete headers[constants.Header.APP_ID] delete headers[constants.Header.APP_ID]
const res = await request const res = await request
.get(`/app${config.prodApp.url}`) .get(`/app${config.getProdApp().url}`)
.set(headers) .set(headers)
.expect(200) .expect(200)
@ -68,14 +69,14 @@ describe("/static", () => {
describe("/attachments", () => { describe("/attachments", () => {
describe("generateSignedUrls", () => { describe("generateSignedUrls", () => {
let datasource let datasource: Datasource
beforeEach(async () => { beforeEach(async () => {
datasource = await config.createDatasource({ datasource = await config.createDatasource({
datasource: { datasource: {
type: "datasource", type: "datasource",
name: "Test", name: "Test",
source: "S3", source: SourceName.S3,
config: {}, config: {},
}, },
}) })

View File

@ -2,6 +2,7 @@ import * as setup from "./utilities"
import path from "path" import path from "path"
import nock from "nock" import nock from "nock"
import { generator } from "@budibase/backend-core/tests" import { generator } from "@budibase/backend-core/tests"
import { withEnv as withCoreEnv } from "@budibase/backend-core"
interface App { interface App {
background: string background: string
@ -89,7 +90,7 @@ describe("/templates", () => {
SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()], SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()],
} }
await config.withCoreEnv(env, async () => { await withCoreEnv(env, async () => {
const name = generator.guid().replaceAll("-", "") const name = generator.guid().replaceAll("-", "")
const url = `/${name}` const url = `/${name}`

View File

@ -24,7 +24,12 @@ import { generator, mocks } from "@budibase/backend-core/tests"
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils" import { DatabaseName, getDatasource } from "../../../integrations/tests/utils"
import merge from "lodash/merge" import merge from "lodash/merge"
import { quotas } from "@budibase/pro" import { quotas } from "@budibase/pro"
import { db, roles } from "@budibase/backend-core" import {
db,
roles,
withEnv as withCoreEnv,
setEnv as setCoreEnv,
} from "@budibase/backend-core"
describe.each([ describe.each([
["lucene", undefined], ["lucene", undefined],
@ -89,12 +94,11 @@ describe.each([
} }
beforeAll(async () => { beforeAll(async () => {
await config.withCoreEnv( await withCoreEnv({ SQS_SEARCH_ENABLE: isSqs ? "true" : "false" }, () =>
{ SQS_SEARCH_ENABLE: isSqs ? "true" : "false" }, config.init()
() => config.init()
) )
if (isSqs) { if (isSqs) {
envCleanup = config.setCoreEnv({ envCleanup = setCoreEnv({
SQS_SEARCH_ENABLE: "true", SQS_SEARCH_ENABLE: "true",
SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()], SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()],
}) })

View File

@ -2,6 +2,7 @@ import { Webhook } from "@budibase/types"
import * as setup from "./utilities" import * as setup from "./utilities"
import { checkBuilderEndpoint } from "./utilities/TestFunctions" import { checkBuilderEndpoint } from "./utilities/TestFunctions"
import { mocks } from "@budibase/backend-core/tests" import { mocks } from "@budibase/backend-core/tests"
import { setEnv } from "../../../environment"
const { basicWebhook, basicAutomation, collectAutomation } = setup.structures const { basicWebhook, basicAutomation, collectAutomation } = setup.structures
@ -17,7 +18,7 @@ describe("/webhooks", () => {
}) })
const setupTest = async () => { const setupTest = async () => {
cleanupEnv = config.setEnv({ SELF_HOSTED: "true" }) cleanupEnv = setEnv({ SELF_HOSTED: "true" })
await config.init() await config.init()
const autoConfig = basicAutomation() const autoConfig = basicAutomation()
autoConfig.definition.trigger.schema = { autoConfig.definition.trigger.schema = {

View File

@ -1,6 +1,10 @@
import * as setup from "../../../api/routes/tests/utilities" import * as setup from "../../../api/routes/tests/utilities"
import { basicTable } from "../../../tests/utilities/structures" import { basicTable } from "../../../tests/utilities/structures"
import { db as dbCore, SQLITE_DESIGN_DOC_ID } from "@budibase/backend-core" import {
db as dbCore,
SQLITE_DESIGN_DOC_ID,
withEnv as withCoreEnv,
} from "@budibase/backend-core"
import { import {
LinkDocument, LinkDocument,
DocumentType, DocumentType,
@ -69,11 +73,11 @@ function oldLinkDocument(): Omit<LinkDocument, "tableId"> {
type SQSEnvVar = "SQS_MIGRATION_ENABLE" | "SQS_SEARCH_ENABLE" type SQSEnvVar = "SQS_MIGRATION_ENABLE" | "SQS_SEARCH_ENABLE"
async function sqsDisabled(envVar: SQSEnvVar, cb: () => Promise<void>) { async function sqsDisabled(envVar: SQSEnvVar, cb: () => Promise<void>) {
await config.withCoreEnv({ [envVar]: "", SQS_SEARCH_ENABLE_TENANTS: [] }, cb) await withCoreEnv({ [envVar]: "", SQS_SEARCH_ENABLE_TENANTS: [] }, cb)
} }
async function sqsEnabled(envVar: SQSEnvVar, cb: () => Promise<void>) { async function sqsEnabled(envVar: SQSEnvVar, cb: () => Promise<void>) {
await config.withCoreEnv( await withCoreEnv(
{ [envVar]: "1", SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()] }, { [envVar]: "1", SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()] },
cb cb
) )

View File

@ -1,5 +1,6 @@
import { getConfig, runStep, afterAll as _afterAll } from "./utilities" import { getConfig, runStep, afterAll as _afterAll } from "./utilities"
import { OpenAI } from "openai" import { OpenAI } from "openai"
import { withEnv as withCoreEnv, setEnv as setCoreEnv } from "@budibase/backend-core"
jest.mock("openai", () => ({ jest.mock("openai", () => ({
OpenAI: jest.fn().mockImplementation(() => ({ OpenAI: jest.fn().mockImplementation(() => ({
@ -32,7 +33,7 @@ describe("test the openai action", () => {
}) })
beforeEach(() => { beforeEach(() => {
resetEnv = config.setCoreEnv({ OPENAI_API_KEY: "abc123" }) resetEnv = setCoreEnv({ OPENAI_API_KEY: "abc123" })
}) })
afterEach(() => { afterEach(() => {
@ -42,7 +43,7 @@ describe("test the openai action", () => {
afterAll(_afterAll) afterAll(_afterAll)
it("should present the correct error message when the OPENAI_API_KEY variable isn't set", async () => { it("should present the correct error message when the OPENAI_API_KEY variable isn't set", async () => {
await config.withCoreEnv({ OPENAI_API_KEY: "" }, async () => { await withCoreEnv({ OPENAI_API_KEY: "" }, async () => {
let res = await runStep("OPENAI", { prompt: OPENAI_PROMPT }) let res = await runStep("OPENAI", { prompt: OPENAI_PROMPT })
expect(res.response).toEqual( expect(res.response).toEqual(
"OpenAI API Key not configured - please add the OPENAI_API_KEY environment variable." "OpenAI API Key not configured - please add the OPENAI_API_KEY environment variable."

View File

@ -1,5 +1,6 @@
import { env as coreEnv } from "@budibase/backend-core" import { env as coreEnv } from "@budibase/backend-core"
import { ServiceType } from "@budibase/types" import { ServiceType } from "@budibase/types"
import cloneDeep from "lodash/cloneDeep"
coreEnv._set("SERVICE_TYPE", ServiceType.APPS) coreEnv._set("SERVICE_TYPE", ServiceType.APPS)
import { join } from "path" import { join } from "path"
@ -133,6 +134,32 @@ const environment = {
}, },
} }
export function setEnv(newEnvVars: Partial<typeof environment>): () => void {
const oldEnv = cloneDeep(environment)
let key: keyof typeof newEnvVars
for (key in newEnvVars) {
environment._set(key, newEnvVars[key])
}
return () => {
for (const [key, value] of Object.entries(oldEnv)) {
environment._set(key, value)
}
}
}
export function withEnv<T>(envVars: Partial<typeof environment>, f: () => T) {
const cleanup = setEnv(envVars)
const result = f()
if (result instanceof Promise) {
return result.finally(cleanup)
} else {
cleanup()
return result
}
}
function cleanVariables() { function cleanVariables() {
// clean up any environment variable edge cases // clean up any environment variable edge cases
for (let [key, value] of Object.entries(environment)) { for (let [key, value] of Object.entries(environment)) {

View File

@ -1,3 +1,4 @@
import { setEnv as setCoreEnv } from "@budibase/backend-core"
import type { GoogleSpreadsheetWorksheet } from "google-spreadsheet" import type { GoogleSpreadsheetWorksheet } from "google-spreadsheet"
import nock from "nock" import nock from "nock"
@ -40,7 +41,7 @@ describe("Google Sheets Integration", () => {
let cleanupEnv: () => void let cleanupEnv: () => void
beforeAll(() => { beforeAll(() => {
cleanupEnv = config.setCoreEnv({ cleanupEnv = setCoreEnv({
GOOGLE_CLIENT_ID: "test", GOOGLE_CLIENT_ID: "test",
GOOGLE_CLIENT_SECRET: "test", GOOGLE_CLIENT_SECRET: "test",
}) })

View File

@ -3,6 +3,10 @@ import { Datasource, FieldType, Row, Table } from "@budibase/types"
import TestConfiguration from "../../../../../tests/utilities/TestConfiguration" import TestConfiguration from "../../../../../tests/utilities/TestConfiguration"
import { search } from "../../../../../sdk/app/rows/search" import { search } from "../../../../../sdk/app/rows/search"
import { generator } from "@budibase/backend-core/tests" import { generator } from "@budibase/backend-core/tests"
import {
withEnv as withCoreEnv,
setEnv as setCoreEnv,
} from "@budibase/backend-core"
import { import {
DatabaseName, DatabaseName,
getDatasource, getDatasource,
@ -31,13 +35,12 @@ describe.each([
let rows: Row[] let rows: Row[]
beforeAll(async () => { beforeAll(async () => {
await config.withCoreEnv( await withCoreEnv({ SQS_SEARCH_ENABLE: isSqs ? "true" : "false" }, () =>
{ SQS_SEARCH_ENABLE: isSqs ? "true" : "false" }, config.init()
() => config.init()
) )
if (isSqs) { if (isSqs) {
envCleanup = config.setCoreEnv({ envCleanup = setCoreEnv({
SQS_SEARCH_ENABLE: "true", SQS_SEARCH_ENABLE: "true",
SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()], SQS_SEARCH_ENABLE_TENANTS: [config.getTenantId()],
}) })

View File

@ -1,6 +1,12 @@
import { withEnv } from "../../environment"
import TestConfiguration from "../../tests/utilities/TestConfiguration" import TestConfiguration from "../../tests/utilities/TestConfiguration"
import { startup } from "../index" import { startup } from "../index"
import { users, utils, tenancy } from "@budibase/backend-core" import {
users,
utils,
tenancy,
withEnv as withCoreEnv,
} from "@budibase/backend-core"
import nock from "nock" import nock from "nock"
describe("check BB_ADMIN environment variables", () => { describe("check BB_ADMIN environment variables", () => {
@ -23,13 +29,13 @@ describe("check BB_ADMIN environment variables", () => {
const EMAIL = "budibase@budibase.com", const EMAIL = "budibase@budibase.com",
PASSWORD = "budibase" PASSWORD = "budibase"
await tenancy.doInTenant(tenancy.DEFAULT_TENANT_ID, async () => { await tenancy.doInTenant(tenancy.DEFAULT_TENANT_ID, async () => {
await config.withEnv( await withEnv(
{ {
MULTI_TENANCY: "0", MULTI_TENANCY: "0",
SELF_HOSTED: "1", SELF_HOSTED: "1",
}, },
() => () =>
config.withCoreEnv( withCoreEnv(
{ {
BB_ADMIN_USER_EMAIL: EMAIL, BB_ADMIN_USER_EMAIL: EMAIL,
BB_ADMIN_USER_PASSWORD: PASSWORD, BB_ADMIN_USER_PASSWORD: PASSWORD,

View File

@ -247,65 +247,6 @@ export default class TestConfiguration {
} }
} }
async withEnv<T>(newEnvVars: Partial<typeof env>, f: () => Promise<T>) {
let cleanup = this.setEnv(newEnvVars)
try {
return await f()
} finally {
cleanup()
}
}
/*
* Sets the environment variables to the given values and returns a function
* that can be called to reset the environment variables to their original values.
*/
setEnv(newEnvVars: Partial<typeof env>): () => void {
const oldEnv = cloneDeep(env)
let key: keyof typeof newEnvVars
for (key in newEnvVars) {
env._set(key, newEnvVars[key])
}
return () => {
for (const [key, value] of Object.entries(oldEnv)) {
env._set(key, value)
}
}
}
async withCoreEnv<T>(
newEnvVars: Partial<typeof coreEnv>,
f: () => Promise<T>
) {
let cleanup = this.setCoreEnv(newEnvVars)
try {
return await f()
} finally {
cleanup()
}
}
/*
* Sets the environment variables to the given values and returns a function
* that can be called to reset the environment variables to their original values.
*/
setCoreEnv(newEnvVars: Partial<typeof coreEnv>): () => void {
const oldEnv = cloneDeep(coreEnv)
let key: keyof typeof newEnvVars
for (key in newEnvVars) {
coreEnv._set(key, newEnvVars[key])
}
return () => {
for (const [key, value] of Object.entries(oldEnv)) {
coreEnv._set(key, value)
}
}
}
async withUser(user: User, f: () => Promise<void>) { async withUser(user: User, f: () => Promise<void>) {
const oldUser = this.user const oldUser = this.user
this.user = user this.user = user