Vibengine
Use Cases

CI/CD Pipelines

Use Vibengine sandboxes in CI/CD workflows

CI/CD Pipelines

Integrate Vibengine sandboxes into your CI/CD workflows for isolated, reproducible, and parallel test execution.

Why Use Sandboxes for CI/CD

  • Isolation — Each test run gets a completely fresh environment, eliminating flaky tests caused by shared state
  • Clean State — No leftover files, processes, or database entries from previous runs
  • Parallelism — Spin up dozens of sandboxes simultaneously to run test suites in parallel
  • Reproducibility — Custom templates guarantee the same environment every time
  • Security — Untrusted code from pull requests runs in fully isolated containers

GitHub Actions Integration

Basic Setup

Add the VE_API_KEY to your GitHub repository secrets, then use it in your workflow.

# .github/workflows/test.yml
name: Run Tests in Vibengine Sandboxes

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  VE_API_KEY: ${{ secrets.VE_API_KEY }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20"

      - name: Install dependencies
        run: npm ci

      - name: Run tests in sandbox
        run: node scripts/run-tests-in-sandbox.js

Test Runner Script

import { Sandbox } from "vibengine"
import fs from "fs"

async function runTestsInSandbox() {
  const sandbox = await Sandbox.create({
    template: "ci-node20",
    timeoutMs: 3 * 60 * 1000,
  })

  // Upload the project files to the sandbox
  const testFiles = fs.readdirSync("./tests")
  for (const file of testFiles) {
    const content = fs.readFileSync(`./tests/${file}`, "utf-8")
    await sandbox.writeFile(`/home/user/project/tests/${file}`, content)
  }

  // Install dependencies and run tests
  const result = await sandbox.runCode(`
    const { execSync } = require("child_process");
    process.chdir("/home/user/project");
    console.log(execSync("npm ci && npm test", { encoding: "utf-8" }));
  `)

  console.log(result.stdout)

  if (result.exitCode !== 0) {
    console.error("Tests failed:", result.stderr)
    process.exit(1)
  }

  await sandbox.kill()
}

runTestsInSandbox()
import sys
from vibengine import Sandbox

def run_tests_in_sandbox():
    sandbox = Sandbox.create(template="ci-python311", timeout=180)

    # Upload test files
    sandbox.upload_file("./tests", "/home/user/project/tests")

    result = sandbox.run_code("""
import subprocess
result = subprocess.run(
    ["python", "-m", "pytest", "/home/user/project/tests", "-v"],
    capture_output=True, text=True
)
print(result.stdout)
print(result.stderr)
exit(result.returncode)
""")

    print(result.stdout)

    if result.exit_code != 0:
        print("Tests failed:", result.stderr, file=sys.stderr)
        sys.exit(1)

    sandbox.kill()

run_tests_in_sandbox()

Parallel Test Execution

Split your test suite across multiple sandboxes to dramatically reduce CI time.

import { Sandbox } from "vibengine"

async function runTestsInParallel(testGroups) {
  const results = await Promise.all(
    testGroups.map(async (group) => {
      const sandbox = await Sandbox.create({
        template: "ci-node20",
        timeoutMs: 3 * 60 * 1000,
      })

      const result = await sandbox.runCode(`
        const { execSync } = require("child_process");
        console.log(execSync("npx jest ${group.join(" ")}", { encoding: "utf-8" }));
      `)

      await sandbox.kill()
      return { group, exitCode: result.exitCode, output: result.stdout }
    })
  )

  const failed = results.filter((r) => r.exitCode !== 0)
  if (failed.length > 0) {
    console.error(`${failed.length} test group(s) failed`)
    process.exit(1)
  }

  console.log("All test groups passed")
}
import asyncio
from vibengine import AsyncSandbox

async def run_tests_in_parallel(test_groups: list[list[str]]):
    async def run_group(group):
        sandbox = await AsyncSandbox.create(template="ci-python311", timeout=180)
        files = " ".join(group)
        result = await sandbox.run_code(f"""
import subprocess
r = subprocess.run(["python", "-m", "pytest"] + "{files}".split(), capture_output=True, text=True)
print(r.stdout)
exit(r.returncode)
""")
        await sandbox.kill()
        return {"group": group, "exit_code": result.exit_code}

    results = await asyncio.gather(*[run_group(g) for g in test_groups])
    failed = [r for r in results if r["exit_code"] != 0]

    if failed:
        raise Exception(f"{len(failed)} test group(s) failed")
    print("All test groups passed")

Custom CI Templates

Create a template with your project dependencies pre-installed for faster sandbox startup.

# vibengine.Dockerfile
FROM vibengine/base:latest

# System dependencies
RUN apt-get update && apt-get install -y git curl

# Node.js project dependencies
COPY package.json package-lock.json /home/user/project/
WORKDIR /home/user/project
RUN npm ci

# Python project dependencies
COPY requirements.txt /home/user/project/
RUN pip install -r requirements.txt
ve template build --name ci-myproject --dockerfile vibengine.Dockerfile

Cost optimization — Sandboxes are billed per second. Always call sandbox.kill() after tests complete. Set reasonable timeouts to prevent runaway sandboxes from accumulating charges.

On this page