import { execFileSync, spawnSync } from "node:child_process"; import { copyFileSync, mkdtempSync, symlinkSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { describe, expect, it } from "vitest"; const shimPath = (name: string) => fileURLToPath(new URL(`../../computer/bin/${name}`, import.meta.url)); /** * Runs the computer's git shim through a symlink, as /usr/bin/git does, next to a stub broker that * echoes what it would send. The stub is not on PATH: login shells reset PATH in the computer. */ function brokerPayload(args: string[], cwd: string, shim = "rakazo-git") { const bin = mkdtempSync(path.join(tmpdir(), "rakazo-git-shim-")); copyFileSync(shimPath(shim), path.join(bin, shim)); writeFileSync(path.join(bin, "rakazo-broker"), '#!/bin/sh\nprintf "%s\\n%s" "$1" "$2"\n', { mode: 0o755, }); const linked = mkdtempSync(path.join(tmpdir(), "rakazo-git-link-")); symlinkSync(path.join(bin, shim), path.join(linked, shim)); const output = execFileSync("bash", [path.join(linked, shim), ...args], { cwd, encoding: "utf8", env: { PATH: process.env.PATH, RAKAZO_GITHUB_BROKER_URL: "http://host.docker.internal:7091/internal/github-broker", RAKAZO_GITHUB_BROKER_RUN_TOKEN: "rgb1.test", }, }); const [endpoint, payload] = output.split("\n"); return { endpoint, body: JSON.parse(payload ?? "{}") as { argv: string[]; cwd: string } }; } describe("computer git and gh shims", () => { it("brokers a plain clone from the current directory", () => { const cwd = mkdtempSync(path.join(tmpdir(), "rakazo-git-cwd-")); const { endpoint, body } = brokerPayload(["clone", "https://github.com/example/demo"], cwd); expect(endpoint).toBe("v1/git"); expect(body).toEqual({ argv: ["git", "clone", "https://github.com/example/demo"], cwd }); }); it("brokers clones behind global options and drops config overrides", () => { const cwd = mkdtempSync(path.join(tmpdir(), "rakazo-git-cwd-")); const { body } = brokerPayload( ["-c", "credential.helper=!echo password=x", "-C", tmpdir(), "fetch", "origin"], cwd, ); expect(body.argv).toEqual(["git", "fetch", "origin"]); expect(body.cwd).toBe( execFileSync("bash", ["-c", 'cd "$1" && pwd', "-", tmpdir()], { encoding: "utf8" }).trim(), ); }); it("brokers gh pull request commands", () => { const { endpoint, body } = brokerPayload(["pr", "list"], tmpdir(), "rakazo-gh"); expect(endpoint).toBe("v1/gh"); expect(body.argv).toEqual(["gh", "pr", "list"]); }); it("names the failed path when the broker is unreachable", () => { // Port 1 refuses at once, and a plain loopback URL has no gateway fallback. const result = spawnSync("bash", [shimPath("rakazo-broker"), "v1/git", "{}"], { encoding: "utf8", env: { PATH: process.env.PATH, RAKAZO_GITHUB_BROKER_URL: "http://127.0.0.1:1/internal/github-broker", RAKAZO_GITHUB_BROKER_RUN_TOKEN: "rgb1.test", }, }); expect(result.status).toBe(1); expect(result.stderr).toContain("(no socket; curl exit 7)"); }); });