test(server): expand workspace routing fixed-id coverage (#26458)
This commit is contained in:
20
packages/opencode/test/fixture/flag.ts
Normal file
20
packages/opencode/test/fixture/flag.ts
Normal file
@@ -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
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import { instanceRouterMiddleware } from "../../src/server/routes/instance/httpa
|
|||||||
import { workspaceRouterMiddleware } from "../../src/server/routes/instance/httpapi/middleware/workspace-routing"
|
import { workspaceRouterMiddleware } from "../../src/server/routes/instance/httpapi/middleware/workspace-routing"
|
||||||
import { resetDatabase } from "../fixture/db"
|
import { resetDatabase } from "../fixture/db"
|
||||||
import { disposeAllInstances, tmpdirScoped } from "../fixture/fixture"
|
import { disposeAllInstances, tmpdirScoped } from "../fixture/fixture"
|
||||||
|
import { withFixedWorkspaceID } from "../fixture/flag"
|
||||||
import { waitGlobalBusEvent } from "./global-bus"
|
import { waitGlobalBusEvent } from "./global-bus"
|
||||||
import { testEffect } from "../lib/effect"
|
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* () {
|
Effect.gen(function* () {
|
||||||
const originalWorkspaceID = Flag.OPENCODE_WORKSPACE_ID
|
|
||||||
const fixedWorkspaceID = WorkspaceID.ascending()
|
const fixedWorkspaceID = WorkspaceID.ascending()
|
||||||
Flag.OPENCODE_WORKSPACE_ID = fixedWorkspaceID
|
yield* withFixedWorkspaceID(fixedWorkspaceID)
|
||||||
yield* Effect.addFinalizer(() =>
|
|
||||||
Effect.sync(() => {
|
|
||||||
Flag.OPENCODE_WORKSPACE_ID = originalWorkspaceID
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
const dir = yield* tmpdirScoped({ git: true })
|
const dir = yield* tmpdirScoped({ git: true })
|
||||||
const project = yield* Project.use.fromDirectory(dir)
|
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", () =>
|
it.live("preserves selected workspace id on instance disposal events", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const dir = yield* tmpdirScoped({ git: true })
|
const dir = yield* tmpdirScoped({ git: true })
|
||||||
|
|||||||
Reference in New Issue
Block a user