Skip to content

Commit ff3c3d3

Browse files
authored
ci: add ecosystem test for http-proxy-middleware (#142)
1 parent 77dcc78 commit ff3c3d3

4 files changed

Lines changed: 124 additions & 8 deletions

File tree

.github/workflows/ecosystem.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: ecosystem
2+
on:
3+
push:
4+
branches: [main, ci/hpm]
5+
workflow_dispatch:
6+
jobs:
7+
http-proxy-middleware:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v6
11+
- run: npm i -fg corepack && corepack enable
12+
- uses: actions/setup-node@v6
13+
with: { node-version: lts/*, cache: "pnpm" }
14+
- run: pnpm install
15+
- run: pnpm test:ecosystem http-proxy-middleware

AGENTS.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,14 +169,15 @@ pnpm test # Lint + typecheck + tests with coverage
169169

170170
## Tooling
171171

172-
| Tool | Command | Notes |
173-
| --------- | ---------------- | --------------------------------------------- |
174-
| Build | `pnpm build` | Uses `unbuild` → CJS + ESM + types in `dist/` |
175-
| Dev | `pnpm dev` | Vitest watch mode |
176-
| Lint | `pnpm lint` | `oxlint` + `oxfmt --check` |
177-
| Format | `pnpm fmt` | `oxlint --fix` + `oxfmt` |
178-
| Typecheck | `pnpm typecheck` | `tsgo --noEmit` (native TS preview) |
179-
| Test | `pnpm test` | Full: lint + typecheck + vitest with coverage |
172+
| Tool | Command | Notes |
173+
| --------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
174+
| Build | `pnpm build` | Uses `unbuild` → CJS + ESM + types in `dist/` |
175+
| Dev | `pnpm dev` | Vitest watch mode |
176+
| Lint | `pnpm lint` | `oxlint` + `oxfmt --check` |
177+
| Format | `pnpm fmt` | `oxlint --fix` + `oxfmt` |
178+
| Typecheck | `pnpm typecheck` | `tsgo --noEmit` (native TS preview) |
179+
| Test | `pnpm test` | Full: lint + typecheck + vitest with coverage |
180+
| Ecosystem | `pnpm test:ecosystem [target]` | Builds + `npm pack`s httpxy, clones an upstream consumer in a temp dir, overrides its httpxy dep with the local tarball, and runs its tests. Default target: `http-proxy-middleware`. Env: `KEEP=1` retains temp dirs; `REF=<git-ref>` pins the upstream checkout. Script: [scripts/ecosystem-test.mjs](scripts/ecosystem-test.mjs). |
180181

181182
## Key Types
182183

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"scripts": {
1717
"build": "obuild",
1818
"dev": "vitest",
19+
"test:ecosystem": "node scripts/ecosystem-test.mjs",
1920
"lint": "oxlint . && oxfmt --check",
2021
"fmt": "oxlint . --fix && oxfmt",
2122
"prepack": "pnpm run build",

scripts/ecosystem-test.mjs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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

Comments
 (0)