debug-config.test.ts 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import { describe, expect, test } from "bun:test"
  2. import fs from "node:fs/promises"
  3. import os from "node:os"
  4. import path from "node:path"
  5. import { OPENCODE_VERSION } from "../src/version"
  6. describe("debug config command", () => {
  7. test("is included in troubleshooting help", async () => {
  8. const [debug, config] = await Promise.all([cli(["debug", "--help"]), cli(["debug", "config", "--help"])])
  9. expect(debug.exitCode).toBe(0)
  10. expect(debug.stdout).toContain("config")
  11. expect(debug.stdout).toContain("Show resolved configuration")
  12. expect(config.exitCode).toBe(0)
  13. expect(config.stdout).toContain("opencode debug config [flags]")
  14. })
  15. test("prints config entries from the invoking directory without reordering permissions", async () => {
  16. const root = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-debug-config-"))
  17. const project = path.join(import.meta.dir, "..")
  18. const registration = path.join(root, "state", "opencode", "service-local.json")
  19. const entries = [
  20. {
  21. type: "document",
  22. path: path.join(project, "opencode.json"),
  23. info: {
  24. permissions: [
  25. { action: "shell", resource: "*", effect: "ask" },
  26. { action: "shell", resource: "git status", effect: "allow" },
  27. ],
  28. },
  29. },
  30. { type: "file", path: path.join(project, "opencode.json") },
  31. ]
  32. let requested: URL | undefined
  33. const authorization: Array<string | null> = []
  34. const server = Bun.serve({
  35. port: 0,
  36. fetch(request) {
  37. const url = new URL(request.url)
  38. if (url.pathname === "/api/health") {
  39. return Response.json({ healthy: true, version: OPENCODE_VERSION, pid: process.pid })
  40. }
  41. requested = url
  42. authorization.push(request.headers.get("authorization"))
  43. return Response.json(entries)
  44. },
  45. })
  46. try {
  47. await fs.mkdir(path.dirname(registration), { recursive: true })
  48. await fs.writeFile(
  49. registration,
  50. JSON.stringify({ version: OPENCODE_VERSION, url: server.url.toString(), pid: process.pid, password: "secret" }),
  51. )
  52. const result = await cli(["debug", "config"], project, { XDG_STATE_HOME: path.join(root, "state") })
  53. expect({ exitCode: result.exitCode, stderr: result.stderr }).toEqual({ exitCode: 0, stderr: "" })
  54. expect(JSON.parse(result.stdout)).toEqual(entries)
  55. expect(requested?.pathname).toBe("/api/config")
  56. expect(requested?.searchParams.get("location[directory]")).toBe(project)
  57. expect(authorization).toEqual([`Basic ${btoa("opencode:secret")}`])
  58. } finally {
  59. server.stop(true)
  60. await fs.rm(root, { recursive: true, force: true })
  61. }
  62. })
  63. })
  64. async function cli(args: string[], cwd = path.join(import.meta.dir, ".."), env?: Record<string, string>) {
  65. const child = Bun.spawn([process.execPath, "run", path.join(import.meta.dir, "../src/index.ts"), ...args], {
  66. cwd,
  67. env: { ...process.env, ...env },
  68. stdout: "pipe",
  69. stderr: "pipe",
  70. })
  71. const [stdout, stderr, exitCode] = await Promise.all([
  72. new Response(child.stdout).text(),
  73. new Response(child.stderr).text(),
  74. child.exited,
  75. ])
  76. return { stdout, stderr, exitCode }
  77. }