Просмотр исходного кода

test(server): expand workspace routing fixed-id coverage (#26458)

Kit Langton 4 месяцев назад
Родитель
Сommit
cbdb2d9825

+ 20 - 0
packages/opencode/test/fixture/flag.ts

@@ -0,0 +1,20 @@
+import type { WorkspaceID } from "@/control-plane/schema"
+import { Flag } from "@opencode-ai/core/flag/flag"
+import { Effect, Scope } from "effect"
+
+/**
+ * Scoped override for `Flag.OPENCODE_WORKSPACE_ID`. Saves the previous value
+ * on entry and restores it via finalizer when the surrounding scope closes —
+ * preserves the original try/finally semantics regardless of test outcome.
+ */
+export function withFixedWorkspaceID(id: WorkspaceID): Effect.Effect<void, never, Scope.Scope> {
+  return Effect.gen(function* () {
+    const previous = Flag.OPENCODE_WORKSPACE_ID
+    Flag.OPENCODE_WORKSPACE_ID = id
+    yield* Effect.addFinalizer(() =>
+      Effect.sync(() => {
+        Flag.OPENCODE_WORKSPACE_ID = previous
+      }),
+    )
+  })
+}

+ 63 - 8
packages/opencode/test/server/httpapi-instance-context.test.ts

@@ -21,6 +21,7 @@ import { instanceRouterMiddleware } from "../../src/server/routes/instance/httpa
 import { workspaceRouterMiddleware } from "../../src/server/routes/instance/httpapi/middleware/workspace-routing"
 import { resetDatabase } from "../fixture/db"
 import { disposeAllInstances, tmpdirScoped } from "../fixture/fixture"
+import { withFixedWorkspaceID } from "../fixture/flag"
 import { waitGlobalBusEvent } from "./global-bus"
 import { testEffect } from "../lib/effect"
 
@@ -204,16 +205,10 @@ describe("HttpApi instance context middleware", () => {
     }),
   )
 
-  it.live("uses configured workspace id instead of routing to requested workspaces", () =>
+  it.live("uses configured workspace id instead of routing to the requested workspace", () =>
     Effect.gen(function* () {
-      const originalWorkspaceID = Flag.OPENCODE_WORKSPACE_ID
       const fixedWorkspaceID = WorkspaceID.ascending()
-      Flag.OPENCODE_WORKSPACE_ID = fixedWorkspaceID
-      yield* Effect.addFinalizer(() =>
-        Effect.sync(() => {
-          Flag.OPENCODE_WORKSPACE_ID = originalWorkspaceID
-        }),
-      )
+      yield* withFixedWorkspaceID(fixedWorkspaceID)
 
       const dir = yield* tmpdirScoped({ git: true })
       const project = yield* Project.use.fromDirectory(dir)
@@ -238,6 +233,66 @@ describe("HttpApi instance context middleware", () => {
     }),
   )
 
+  it.live("falls through to local instead of MissingWorkspace when configured workspace id is set", () =>
+    Effect.gen(function* () {
+      const fixedWorkspaceID = WorkspaceID.ascending()
+      yield* withFixedWorkspaceID(fixedWorkspaceID)
+
+      const dir = yield* tmpdirScoped({ git: true })
+      yield* Project.use.fromDirectory(dir)
+      yield* serveProbe()
+
+      // Reference a workspace id that is not registered locally. Without the
+      // configured env override, this would short-circuit to a 500
+      // MissingWorkspace response. With the env set, planRequest must skip the
+      // MissingWorkspace branch and fall through to Local with the configured
+      // workspace id.
+      const unknownWorkspaceID = WorkspaceID.ascending()
+      const response = yield* HttpClientRequest.get(`/probe?workspace=${unknownWorkspaceID}`).pipe(
+        HttpClientRequest.setHeader("x-opencode-directory", dir),
+        HttpClient.execute,
+      )
+
+      expect(response.status).toBe(200)
+      expect(yield* response.json).toMatchObject({
+        directory: dir,
+        workspaceID: fixedWorkspaceID,
+      })
+    }),
+  )
+
+  it.live("keeps configured workspace id on control-plane routes without remote routing", () =>
+    Effect.gen(function* () {
+      const fixedWorkspaceID = WorkspaceID.ascending()
+      yield* withFixedWorkspaceID(fixedWorkspaceID)
+
+      const dir = yield* tmpdirScoped({ git: true })
+      const project = yield* Project.use.fromDirectory(dir)
+      const workspaceDir = path.join(dir, ".workspace-local")
+      const workspace = yield* createLocalWorkspace({
+        projectID: project.project.id,
+        type: "instance-context-fixed-workspace-control-plane",
+        directory: workspaceDir,
+      })
+      // /session is matched by isLocalWorkspaceRoute, so shouldStayOnControlPlane
+      // is true. Combined with the env override, the route must stay Local with
+      // the configured workspace id (not divert to the requested workspace's
+      // local directory).
+      yield* serveProbe("/session")
+
+      const response = yield* HttpClientRequest.get(`/session?workspace=${workspace.id}`).pipe(
+        HttpClientRequest.setHeader("x-opencode-directory", dir),
+        HttpClient.execute,
+      )
+
+      expect(response.status).toBe(200)
+      expect(yield* response.json).toMatchObject({
+        directory: dir,
+        workspaceID: fixedWorkspaceID,
+      })
+    }),
+  )
+
   it.live("preserves selected workspace id on instance disposal events", () =>
     Effect.gen(function* () {
       const dir = yield* tmpdirScoped({ git: true })