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
-