Automated testing pipeline
Build a testing pipeline that clones Git repositories, installs dependencies, runs tests, and reports results.
Time to complete: 25 minutes
- Sign up for a Cloudflare account ↗.
 - Install 
Node.js↗. 
Node.js version manager
 Use a Node version manager like Volta ↗ or nvm ↗ to avoid permission issues and change Node.js versions. Wrangler, discussed later in this guide, requires a Node version of 16.17.0 or later.
You'll also need a GitHub repository with tests (public or private with access token).
npm create cloudflare@latest -- test-pipeline --template=cloudflare/sandbox-sdk/examples/minimalyarn create cloudflare test-pipeline --template=cloudflare/sandbox-sdk/examples/minimalpnpm create cloudflare@latest test-pipeline --template=cloudflare/sandbox-sdk/examples/minimalcd test-pipelineReplace src/index.ts:
import { getSandbox, proxyToSandbox, type Sandbox } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
interface Env {  Sandbox: DurableObjectNamespace<Sandbox>;  GITHUB_TOKEN?: string;}
export default {  async fetch(request: Request, env: Env): Promise<Response> {    const proxyResponse = await proxyToSandbox(request, env);    if (proxyResponse) return proxyResponse;
    if (request.method !== 'POST') {      return new Response('POST { "repoUrl": "https://github.com/owner/repo", "branch": "main" }');    }
    try {      const { repoUrl, branch = 'main' } = await request.json();
      if (!repoUrl) {        return Response.json({ error: 'repoUrl required' }, { status: 400 });      }
      const sandbox = getSandbox(env.Sandbox, `test-${Date.now()}`);
      try {        // Clone repository        let cloneUrl = repoUrl;        if (env.GITHUB_TOKEN && repoUrl.includes('github.com')) {          cloneUrl = repoUrl.replace('https://', `https://${env.GITHUB_TOKEN}@`);        }
        await sandbox.exec(`git clone --depth=1 --branch=${branch} ${cloneUrl} /workspace/repo`);
        // Detect project type        const projectType = await detectProjectType(sandbox);
        // Install dependencies        const installCmd = getInstallCommand(projectType);        if (installCmd) {          const installResult = await sandbox.exec(`cd /workspace/repo && ${installCmd}`);          if (!installResult.success) {            return Response.json({              success: false,              error: 'Install failed',              output: installResult.stderr            });          }        }
        // Run tests        const testCmd = getTestCommand(projectType);        const testResult = await sandbox.exec(`cd /workspace/repo && ${testCmd}`);
        return Response.json({          success: testResult.exitCode === 0,          exitCode: testResult.exitCode,          output: testResult.stdout,          errors: testResult.stderr,          projectType        });
      } finally {        await sandbox.destroy();      }
    } catch (error: any) {      return Response.json({ error: error.message }, { status: 500 });    }  },};
async function detectProjectType(sandbox: any): Promise<string> {  try {    await sandbox.readFile('/workspace/repo/package.json');    return 'nodejs';  } catch {}
  try {    await sandbox.readFile('/workspace/repo/requirements.txt');    return 'python';  } catch {}
  try {    await sandbox.readFile('/workspace/repo/go.mod');    return 'go';  } catch {}
  return 'unknown';}
function getInstallCommand(projectType: string): string {  switch (projectType) {    case 'nodejs': return 'npm install';    case 'python': return 'pip install -r requirements.txt || pip install -e .';    case 'go': return 'go mod download';    default: return '';  }}
function getTestCommand(projectType: string): string {  switch (projectType) {    case 'nodejs': return 'npm test';    case 'python': return 'python -m pytest || python -m unittest discover';    case 'go': return 'go test ./...';    default: return 'echo "Unknown project type"';  }}Start the dev server:
npm run devTest with a repository:
curl -X POST http://localhost:8787 \  -H "Content-Type: application/json" \  -d '{    "repoUrl": "https://github.com/sindresorhus/is-promise",    "branch": "main"  }'Response:
{  "success": true,  "exitCode": 0,  "output": "...test output...",  "projectType": "nodejs"}npx wrangler deployFor private repositories, set your GitHub token:
npx wrangler secret put GITHUB_TOKENAn automated testing pipeline that:
- Clones Git repositories
 - Detects project type (Node.js, Python, Go)
 - Installs dependencies automatically
 - Runs tests and reports results
 
- Streaming output - Add real-time test output
 - Background processes - Handle long-running tests
 - Sessions API - Cache dependencies between runs
 
Was this helpful?
- Resources
 - API
 - New to Cloudflare?
 - Directory
 - Sponsorships
 - Open Source
 
- Support
 - Help Center
 - System Status
 - Compliance
 - GDPR
 
- Company
 - cloudflare.com
 - Our team
 - Careers
 
- © 2025 Cloudflare, Inc.
 - Privacy Policy
 - Terms of Use
 - Report Security Issues
 - Trademark