Skip to main content
Use this guide when you need to execute user-submitted code checks (tests/lint/build) in CI without risking host integrity.

Diagram: CI validation pipeline

For untrusted CI workloads, start with:
  • mode: "ephemeral"
  • network: "none" by default
  • explicit timeout and memory
  • no persistent state unless explicitly required
import { DockerIsol8 } from "@isol8/core";

const engine = new DockerIsol8({
  mode: "ephemeral",
  network: "none",
  timeoutMs: 30000,
  memoryLimit: "512m",
});

await engine.start();

Pattern 1: run unit tests against submitted code

async function runPythonTests(submittedCode: string, testCode: string) {
  const result = await engine.execute({
    runtime: "python",
    installPackages: ["pytest"],
    code: `
with open("/sandbox/solution.py", "w") as f:
  f.write("""${submittedCode.replace(/"""/g, '"""')}""")

with open("/sandbox/test_solution.py", "w") as f:
  f.write("""${testCode.replace(/"""/g, '"""')}""")

import subprocess
proc = subprocess.run(
  ["python3", "-m", "pytest", "/sandbox/test_solution.py", "-q", "--tb=short"],
  capture_output=True, text=True, timeout=20
)
print(proc.stdout)
if proc.stderr:
  print(proc.stderr)
raise SystemExit(proc.returncode)
`,
  });

  return {
    passed: result.exitCode === 0,
    stdout: result.stdout,
    stderr: result.stderr,
    durationMs: result.durationMs,
  };
}

Pattern 2: syntax validation (cheap fail-fast gate)

const result = await engine.execute({
  runtime: "python",
  stdin: code,
  code: `
import ast, sys
src = sys.stdin.read()
ast.parse(src)
print("VALID")
`,
});

Pattern 3: linting gate

const lint = await engine.execute({
  runtime: "python",
  installPackages: ["flake8"],
  stdin: submittedCode,
  code: `
import subprocess, sys
open("/sandbox/code.py", "w").write(sys.stdin.read())
proc = subprocess.run(
  ["python3", "-m", "flake8", "/sandbox/code.py", "--max-line-length=120"],
  capture_output=True, text=True
)
print(proc.stdout)
if proc.stderr:
  print(proc.stderr)
raise SystemExit(proc.returncode)
`,
});

Pattern 4: build verification

If build needs external dependency resolution, explicitly allow it.
const buildEngine = new DockerIsol8({
  mode: "ephemeral",
  network: "host", // trusted CI context only
  timeoutMs: 120000,
  memoryLimit: "1g",
});

await buildEngine.start();

const result = await buildEngine.execute({
  runtime: "bash",
  files: {
    "/sandbox/package.json": packageJson,
    "/sandbox/index.ts": indexTs,
    "/sandbox/tsconfig.json": JSON.stringify({
      compilerOptions: {
        strict: true,
        target: "ES2022",
        module: "ESNext",
      },
    }),
  },
  code: `
cd /sandbox
npm install --ignore-scripts
npx tsc --noEmit
`,
});

await buildEngine.stop();
network: "host" should be used only in trusted CI contexts where unrestricted network access is acceptable.

Pattern 5: artifact capture from test runs

Capture generated test reports using outputPaths.
const result = await engine.execute({
  runtime: "python",
  code: `
open("/sandbox/report.txt", "w").write("tests: 42\\npassed: 41\\nfailed: 1\\n")
print("report-ready")
`,
  outputPaths: ["/sandbox/report.txt"],
});

const reportBase64 = result.files?.["/sandbox/report.txt"];

Parallel CI jobs

Run independent validations concurrently; isol8 enforces concurrency with semaphores/maxConcurrent.
const jobs = submissions.map((s) =>
  engine.execute({
    runtime: "python",
    stdin: s.code,
    code: "import ast,sys; ast.parse(sys.stdin.read()); print('ok')",
  })
);

const results = await Promise.all(jobs);

Remote CI runners

For centralized build/test infrastructure, use remote server + RemoteIsol8.
import { RemoteIsol8 } from "@isol8/core";

const remote = new RemoteIsol8(
  {
    host: "http://ci-runner.internal:3000",
    apiKey: process.env.ISOL8_API_KEY!,
    sessionId: "pr-123-checks",
  },
  {
    network: "none",
    timeoutMs: 45000,
    memoryLimit: "768m",
  }
);

await remote.start();
const result = await remote.execute({
  runtime: "python",
  code: "print('remote checks start')",
});
await remote.stop();

Reliability patterns for CI pipelines

  • fail fast with syntax check before expensive test/build stages
  • keep network off unless a stage explicitly requires dependency downloads
  • pre-bake stable dependencies with isol8 setup for predictable timing
  • return structured machine-readable output from each stage (JSON/text summary)
  • enforce explicit timeouts per stage to avoid hanging workers