Files
OmniRoute/tests/unit/services/installers/bifrost-transport-version-format.test.ts
Sean Ford 14468cdec5 fix(bifrost): send v-prefixed transport version, not bare semver (#8194)
* fix(bifrost): send v-prefixed transport version, not bare semver

bifrost.ts resolveSpawnArgs() set BIFROST_TRANSPORT_VERSION straight from
getInstalledVersionSync(), which reads the raw "version" field out of
node_modules/@maximhq/bifrost/package.json - always bare semver per npm
convention (e.g. "1.6.3").

@maximhq/bifrost's own bin.js validates that env var against
/^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/ or the literal "latest" and rejects
anything else with "Invalid transport version format", exiting immediately.
Every embedded Bifrost instance failed to start as a result.

Adds formatTransportVersion() to normalize at the call site that owns the
env var, so bifrost.ts and the upstream @maximhq/bifrost package both stay
exactly as designed - no changes needed to bifrost itself.

Strengthens the existing resolveSpawnArgs test to assert the actual v-prefix
format (it previously only checked for a non-empty string, the same gap
#6877 called out for cliproxy's pre-existing test), and adds a dedicated
regression test file covering the pure formatTransportVersion() helper plus
a real-filesystem resolveSpawnArgs() integration check.

Found and fixed while self-hosting OmniRoute and diagnosing why bifrost
kept crash-looping on startup.

* fix(bifrost): resolve install dir lazily so version read honors runtime DATA_DIR

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
Co-authored-by: seanford <seanford@users.noreply.github.com>
2026-07-23 11:25:28 -03:00

113 lines
4.3 KiB
TypeScript

/**
* Regression test - bifrost resolveSpawnArgs() must pass a v-prefixed (or
* "latest") BIFROST_TRANSPORT_VERSION, never the bare semver string that
* getInstalledVersion() reads out of node_modules/@maximhq/bifrost/package.json.
*
* Bifrost's own bin.js validates the env var against
* /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/ or the literal "latest" and exits
* immediately with "Invalid transport version format" on anything else.
* package.json's "version" field is always bare semver per npm convention
* (e.g. "1.6.3"), so every embedded Bifrost instance failed to start until
* this fix - unlike cliproxy's #6877 regression, this was silent at the
* resolveSpawnArgs() call site itself; the failure only surfaced once the
* spawned process actually ran.
*
* Covers both the pure formatTransportVersion() helper directly, and the
* real resolveSpawnArgs() integration path against a filesystem-backed
* fake npm, matching the pattern used by
* tests/unit/services/installers/cliproxy-resolve-spawn-args-6877.test.ts.
*/
import { describe, it, before, after } from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
describe("formatTransportVersion (pure)", () => {
it("prepends v to bare semver", async () => {
const { formatTransportVersion } = await import(
"../../../../src/lib/services/installers/bifrost.ts"
);
assert.equal(formatTransportVersion("1.6.3"), "v1.6.3");
assert.equal(formatTransportVersion("2.0.0-beta.1"), "v2.0.0-beta.1");
});
it("leaves an already-v-prefixed version untouched", async () => {
const { formatTransportVersion } = await import(
"../../../../src/lib/services/installers/bifrost.ts"
);
assert.equal(formatTransportVersion("v1.6.3"), "v1.6.3");
});
it('passes through "latest" untouched', async () => {
const { formatTransportVersion } = await import(
"../../../../src/lib/services/installers/bifrost.ts"
);
assert.equal(formatTransportVersion("latest"), "latest");
});
it('defaults null to "latest"', async () => {
const { formatTransportVersion } = await import(
"../../../../src/lib/services/installers/bifrost.ts"
);
assert.equal(formatTransportVersion(null), "latest");
});
});
describe("resolveSpawnArgs BIFROST_TRANSPORT_VERSION (real filesystem)", () => {
const ORIGINAL_DATA_DIR = process.env.DATA_DIR;
const ORIGINAL_PATH = process.env.PATH ?? "";
let dataDir: string;
let fakeBinDir: string;
before(() => {
dataDir = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-bifrost-vfix-"));
fakeBinDir = fs.mkdtempSync(path.join(os.tmpdir(), "omniroute-bifrost-vfix-bin-"));
process.env.DATA_DIR = dataDir;
process.env.PATH = `${fakeBinDir}:${ORIGINAL_PATH}`;
// Same package.json shape a real `npm install @maximhq/bifrost@1.6.3` would
// leave behind - bare semver "version" field, no "v" prefix.
const pkgDir = path.join(dataDir, "services", "bifrost", "node_modules", "@maximhq", "bifrost");
fs.mkdirSync(pkgDir, { recursive: true });
fs.writeFileSync(
path.join(pkgDir, "package.json"),
JSON.stringify({ name: "@maximhq/bifrost", version: "1.6.3" }),
"utf8"
);
fs.writeFileSync(path.join(pkgDir, "bin.js"), "", "utf8");
});
after(() => {
if (ORIGINAL_DATA_DIR === undefined) {
delete process.env.DATA_DIR;
} else {
process.env.DATA_DIR = ORIGINAL_DATA_DIR;
}
process.env.PATH = ORIGINAL_PATH;
fs.rmSync(dataDir, { recursive: true, force: true });
fs.rmSync(fakeBinDir, { recursive: true, force: true });
});
it("BIFROST_TRANSPORT_VERSION is v-prefixed, matching what bin.js requires", async () => {
const { resolveSpawnArgs } = await import(
"../../../../src/lib/services/installers/bifrost.ts"
);
const args = resolveSpawnArgs(8080);
assert.equal(
args.env.BIFROST_TRANSPORT_VERSION,
"v1.6.3",
"must be v-prefixed - a bare '1.6.3' is rejected by bifrost's bin.js with " +
"'Invalid transport version format'"
);
assert.match(
args.env.BIFROST_TRANSPORT_VERSION as string,
/^(latest|v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?)$/,
"must satisfy bifrost bin.js's own validateTransportVersion() regex"
);
});
});