Merge pull request #13569 from Budibase/make-reuse-containers-default

Make REUSE_CONTAINERS the default for running tests.
This commit is contained in:
Sam Rose 2024-04-26 15:02:54 +01:00 committed by GitHub
commit 0624ba4925
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 71 additions and 24 deletions

View File

@ -92,8 +92,6 @@ jobs:
test-libraries: test-libraries:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
REUSE_CONTAINERS: true
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -150,8 +148,6 @@ jobs:
test-server: test-server:
runs-on: budi-tubby-tornado-quad-core-150gb runs-on: budi-tubby-tornado-quad-core-150gb
env:
REUSE_CONTAINERS: true
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@ -1,16 +1,49 @@
import { GenericContainer, Wait } from "testcontainers" import {
GenericContainer,
Wait,
getContainerRuntimeClient,
} from "testcontainers"
import { ContainerInfo } from "dockerode"
import path from "path" import path from "path"
import lockfile from "proper-lockfile" import lockfile from "proper-lockfile"
async function getBudibaseContainers() {
const client = await getContainerRuntimeClient()
const conatiners = await client.container.list()
return conatiners.filter(
container =>
container.Labels["com.budibase"] === "true" &&
container.Labels["org.testcontainers"] === "true"
)
}
async function killContainers(containers: ContainerInfo[]) {
const client = await getContainerRuntimeClient()
for (const container of containers) {
const c = client.container.getById(container.Id)
await c.kill()
await c.remove()
}
}
export default async function setup() { export default async function setup() {
const lockPath = path.resolve(__dirname, "globalSetup.ts") const lockPath = path.resolve(__dirname, "globalSetup.ts")
if (process.env.REUSE_CONTAINERS) { // If you run multiple tests at the same time, it's possible for the CouchDB
// If you run multiple tests at the same time, it's possible for the CouchDB // shared container to get started multiple times despite having an
// shared container to get started multiple times despite having an // identical reuse hash. To avoid that, we do a filesystem-based lock so
// identical reuse hash. To avoid that, we do a filesystem-based lock so // that only one globalSetup.ts is running at a time.
// that only one globalSetup.ts is running at a time. lockfile.lockSync(lockPath)
lockfile.lockSync(lockPath)
} // Remove any containers that are older than 24 hours. This is to prevent
// containers getting full volumes or accruing any other problems from being
// left up for very long periods of time.
const threshold = new Date(Date.now() - 1000 * 60 * 60 * 24)
const containers = (await getBudibaseContainers()).filter(container => {
const created = new Date(container.Created * 1000)
return created < threshold
})
await killContainers(containers)
try { try {
let couchdb = new GenericContainer("budibase/couchdb:v3.2.1-sqs") let couchdb = new GenericContainer("budibase/couchdb:v3.2.1-sqs")
@ -28,20 +61,16 @@ export default async function setup() {
target: "/opt/couchdb/etc/local.d/test-couchdb.ini", target: "/opt/couchdb/etc/local.d/test-couchdb.ini",
}, },
]) ])
.withLabels({ "com.budibase": "true" })
.withReuse()
.withWaitStrategy( .withWaitStrategy(
Wait.forSuccessfulCommand( Wait.forSuccessfulCommand(
"curl http://budibase:budibase@localhost:5984/_up" "curl http://budibase:budibase@localhost:5984/_up"
).withStartupTimeout(20000) ).withStartupTimeout(20000)
) )
if (process.env.REUSE_CONTAINERS) {
couchdb = couchdb.withReuse()
}
await couchdb.start() await couchdb.start()
} finally { } finally {
if (process.env.REUSE_CONTAINERS) { lockfile.unlockSync(lockPath)
lockfile.unlockSync(lockPath)
}
} }
} }

View File

@ -59,7 +59,8 @@
"dev:all": "yarn run kill-all && lerna run --stream dev", "dev:all": "yarn run kill-all && lerna run --stream dev",
"dev:built": "yarn run kill-all && cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream dev:built", "dev:built": "yarn run kill-all && cd packages/server && yarn dev:stack:up && cd ../../ && lerna run --stream dev:built",
"dev:docker": "./scripts/devDocker.sh", "dev:docker": "./scripts/devDocker.sh",
"test": "REUSE_CONTAINERS=1 lerna run --concurrency 1 --stream test --stream", "test": "lerna run --concurrency 1 --stream test --stream",
"test:containers:kill": "./scripts/killTestcontainers.sh",
"lint:eslint": "eslint packages --max-warnings=0", "lint:eslint": "eslint packages --max-warnings=0",
"lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\"", "lint:prettier": "prettier --check \"packages/**/*.{js,ts,svelte}\" && prettier --write \"examples/**/*.{js,ts,svelte}\"",
"lint": "yarn run lint:eslint && yarn run lint:prettier", "lint": "yarn run lint:eslint && yarn run lint:prettier",

View File

@ -28,7 +28,11 @@ function getTestcontainers(): ContainerInfo[] {
.split("\n") .split("\n")
.filter(x => x.length > 0) .filter(x => x.length > 0)
.map(x => JSON.parse(x) as ContainerInfo) .map(x => JSON.parse(x) as ContainerInfo)
.filter(x => x.Labels.includes("org.testcontainers=true")) .filter(
x =>
x.Labels.includes("org.testcontainers=true") &&
x.Labels.includes("com.budibase=true")
)
} }
export function getContainerByImage(image: string) { export function getContainerByImage(image: string) {

View File

@ -65,9 +65,7 @@ export async function rawQuery(ds: Datasource, sql: string): Promise<any> {
} }
export async function startContainer(container: GenericContainer) { export async function startContainer(container: GenericContainer) {
if (process.env.REUSE_CONTAINERS) { container = container.withReuse().withLabels({ "com.budibase": "true" })
container = container.withReuse()
}
const startedContainer = await container.start() const startedContainer = await container.start()

19
scripts/killTestcontainers.sh Executable file
View File

@ -0,0 +1,19 @@
#!/bin/bash
# Find all Docker containers with the label "org.testcontainers=true"
containers=$(docker ps -q -f "label=org.testcontainers=true")
# Check if there are any containers to stop
if [ -z "$containers" ]; then
echo "No containers with label 'org.testcontainers=true' found."
else
# Stop the containers
echo "Stopping containers..."
docker stop $containers
# Remove the containers
echo "Removing containers..."
docker rm $containers
echo "Containers have been stopped and removed."
fi