|
| 1 | +#!/usr/bin/env node |
| 2 | +// Ecosystem test runner: builds & packs httpxy, clones an upstream consumer |
| 3 | +// in a temp dir, installs deps with the local tarball overriding the published |
| 4 | +// httpxy version, and runs the consumer's test suite. |
| 5 | +// |
| 6 | +// Usage: |
| 7 | +// node scripts/ecosystem-test.mjs [target] |
| 8 | +// |
| 9 | +// Targets: |
| 10 | +// http-proxy-middleware (default) |
| 11 | +// |
| 12 | +// Env: |
| 13 | +// KEEP=1 Keep temp dirs after run for debugging. |
| 14 | +// REF=<ref> Git ref to check out from the upstream repo (branch/tag/sha). |
| 15 | + |
| 16 | +import { execSync } from "node:child_process"; |
| 17 | +import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; |
| 18 | +import { tmpdir } from "node:os"; |
| 19 | +import { dirname, join, resolve } from "node:path"; |
| 20 | +import { fileURLToPath } from "node:url"; |
| 21 | + |
| 22 | +const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), ".."); |
| 23 | + |
| 24 | +const TARGETS = { |
| 25 | + "http-proxy-middleware": { |
| 26 | + repo: "https://github.com/chimurai/http-proxy-middleware.git", |
| 27 | + // TODO: revert to default branch once `httpxy-0.5.2` is merged upstream. |
| 28 | + ref: "master", |
| 29 | + install: "yarn install --ignore-scripts", |
| 30 | + steps: ["yarn build", "yarn test"], |
| 31 | + }, |
| 32 | +}; |
| 33 | + |
| 34 | +const targetName = process.argv[2] || "http-proxy-middleware"; |
| 35 | +const target = TARGETS[targetName]; |
| 36 | +if (!target) { |
| 37 | + console.error(`Unknown target: ${targetName}`); |
| 38 | + console.error(`Available: ${Object.keys(TARGETS).join(", ")}`); |
| 39 | + process.exit(1); |
| 40 | +} |
| 41 | + |
| 42 | +const KEEP = process.env.KEEP === "1"; |
| 43 | +const REF = process.env.REF; |
| 44 | + |
| 45 | +const packDir = mkdtempSync(join(tmpdir(), "httpxy-pack-")); |
| 46 | +const workDir = mkdtempSync(join(tmpdir(), `httpxy-eco-${targetName}-`)); |
| 47 | +const upstreamDir = join(workDir, targetName); |
| 48 | + |
| 49 | +const cleanup = () => { |
| 50 | + if (KEEP) { |
| 51 | + console.log(`\n(KEEP=1) Leaving artifacts:`); |
| 52 | + console.log(` pack: ${packDir}`); |
| 53 | + console.log(` upstream: ${upstreamDir}`); |
| 54 | + return; |
| 55 | + } |
| 56 | + rmSync(packDir, { recursive: true, force: true }); |
| 57 | + rmSync(workDir, { recursive: true, force: true }); |
| 58 | +}; |
| 59 | + |
| 60 | +process.on("exit", cleanup); |
| 61 | +process.on("SIGINT", () => process.exit(130)); |
| 62 | + |
| 63 | +const run = (cmd, cwd = ROOT) => { |
| 64 | + console.log(`\n$ (${cwd === ROOT ? "httpxy" : targetName}) ${cmd}`); |
| 65 | + execSync(cmd, { stdio: "inherit", cwd }); |
| 66 | +}; |
| 67 | + |
| 68 | +// 1. Build httpxy and pack into a tarball |
| 69 | +run("pnpm build"); |
| 70 | +run(`npm pack --pack-destination ${packDir}`); |
| 71 | +const tarball = readdirSync(packDir).find((f) => f.endsWith(".tgz")); |
| 72 | +if (!tarball) { |
| 73 | + throw new Error(`No tarball produced in ${packDir}`); |
| 74 | +} |
| 75 | +const tarballPath = join(packDir, tarball); |
| 76 | +console.log(`\nPacked: ${tarballPath}`); |
| 77 | + |
| 78 | +// 2. Clone upstream consumer at a shallow depth |
| 79 | +const ref = REF || target.ref; |
| 80 | +const branchArg = ref ? `--branch ${ref} ` : ""; |
| 81 | +run(`git clone --depth 1 ${branchArg}${target.repo} ${upstreamDir}`); |
| 82 | + |
| 83 | +// 3. Pin httpxy to the local tarball via deps + yarn `resolutions` |
| 84 | +const pkgPath = join(upstreamDir, "package.json"); |
| 85 | +const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); |
| 86 | +const fileSpec = `file:${tarballPath}`; |
| 87 | +if (pkg.dependencies?.httpxy) pkg.dependencies.httpxy = fileSpec; |
| 88 | +if (pkg.devDependencies?.httpxy) pkg.devDependencies.httpxy = fileSpec; |
| 89 | +pkg.resolutions = { ...pkg.resolutions, httpxy: fileSpec }; |
| 90 | +writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n"); |
| 91 | +console.log(`\nPatched ${pkgPath} to use ${fileSpec}`); |
| 92 | + |
| 93 | +// 4. Install deps and run upstream tests |
| 94 | +run(target.install, upstreamDir); |
| 95 | +for (const step of target.steps) { |
| 96 | + run(step, upstreamDir); |
| 97 | +} |
| 98 | + |
| 99 | +console.log(`\n✓ ${targetName} tests passed against local httpxy build`); |
0 commit comments