Skip to content

Commit 89e7550

Browse files
Make server settings test layer stateful
- Track settings updates in the test service - Point Codex tests at the fake binary via server settings instead of env vars
1 parent 7757947 commit 89e7550

2 files changed

Lines changed: 117 additions & 179 deletions

File tree

apps/server/src/git/Layers/CodexTextGeneration.test.ts

Lines changed: 97 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,20 @@ const CodexTextGenerationTestLayer = CodexTextGenerationLive.pipe(
2424
Layer.provideMerge(NodeServices.layer),
2525
);
2626

27-
function makeFakeCodexBinary(dir: string) {
27+
function makeFakeCodexBinary(
28+
dir: string,
29+
input: {
30+
output: string;
31+
exitCode?: number;
32+
stderr?: string;
33+
requireImage?: boolean;
34+
requireFastServiceTier?: boolean;
35+
requireReasoningEffort?: string;
36+
forbidReasoningEffort?: boolean;
37+
stdinMustContain?: string;
38+
stdinMustNotContain?: string;
39+
},
40+
) {
2841
return Effect.gen(function* () {
2942
const fs = yield* FileSystem.FileSystem;
3043
const path = yield* Path.Path;
@@ -37,12 +50,16 @@ function makeFakeCodexBinary(dir: string) {
3750
[
3851
"#!/bin/sh",
3952
'output_path=""',
53+
'seen_image="0"',
54+
'seen_fast_service_tier="0"',
55+
'seen_reasoning_effort=""',
4056
"while [ $# -gt 0 ]; do",
4157
' if [ "$1" = "--image" ]; then',
4258
" shift",
4359
' if [ -n "$1" ]; then',
4460
' seen_image="1"',
4561
" fi",
62+
" shift",
4663
" continue",
4764
" fi",
4865
' if [ "$1" = "--config" ]; then',
@@ -55,55 +72,80 @@ function makeFakeCodexBinary(dir: string) {
5572
' seen_reasoning_effort="$1"',
5673
" ;;",
5774
" esac",
75+
" shift",
5876
" continue",
5977
" fi",
6078
' if [ "$1" = "--output-last-message" ]; then',
6179
" shift",
6280
' output_path="$1"',
81+
" shift",
82+
" continue",
6383
" fi",
6484
" shift",
6585
"done",
6686
'stdin_content="$(cat)"',
67-
'if [ "$T3_FAKE_CODEX_REQUIRE_IMAGE" = "1" ] && [ "$seen_image" != "1" ]; then',
68-
' printf "%s\\n" "missing --image input" >&2',
69-
" exit 2",
70-
"fi",
71-
'if [ "$T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER" = "1" ] && [ "$seen_fast_service_tier" != "1" ]; then',
72-
' printf "%s\\n" "missing fast service tier config" >&2',
73-
" exit 5",
74-
"fi",
75-
'if [ -n "$T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT" ] && [ "$seen_reasoning_effort" != "model_reasoning_effort=\\"$T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT\\"" ]; then',
76-
' printf "%s\\n" "unexpected reasoning effort config: $seen_reasoning_effort" >&2',
77-
" exit 6",
78-
"fi",
79-
'if [ "$T3_FAKE_CODEX_FORBID_REASONING_EFFORT" = "1" ] && [ -n "$seen_reasoning_effort" ]; then',
80-
' printf "%s\\n" "reasoning effort config should be omitted: $seen_reasoning_effort" >&2',
81-
" exit 7",
82-
"fi",
83-
'if [ -n "$T3_FAKE_CODEX_STDIN_MUST_CONTAIN" ]; then',
84-
' printf "%s" "$stdin_content" | grep -F -- "$T3_FAKE_CODEX_STDIN_MUST_CONTAIN" >/dev/null || {',
85-
' printf "%s\\n" "stdin missing expected content" >&2',
86-
" exit 3",
87-
" }",
88-
"fi",
89-
'if [ -n "$T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN" ]; then',
90-
' if printf "%s" "$stdin_content" | grep -F -- "$T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN" >/dev/null; then',
91-
' printf "%s\\n" "stdin contained forbidden content" >&2',
92-
" exit 4",
93-
" fi",
94-
"fi",
95-
'if [ -n "$T3_FAKE_CODEX_STDERR" ]; then',
96-
' printf "%s\\n" "$T3_FAKE_CODEX_STDERR" >&2',
97-
"fi",
87+
...(input.requireImage
88+
? [
89+
'if [ "$seen_image" != "1" ]; then',
90+
' printf "%s\\n" "missing --image input" >&2',
91+
` exit 2`,
92+
"fi",
93+
]
94+
: []),
95+
...(input.requireFastServiceTier
96+
? [
97+
'if [ "$seen_fast_service_tier" != "1" ]; then',
98+
' printf "%s\\n" "missing fast service tier config" >&2',
99+
` exit 5`,
100+
"fi",
101+
]
102+
: []),
103+
...(input.requireReasoningEffort !== undefined
104+
? [
105+
`if [ "$seen_reasoning_effort" != "model_reasoning_effort=\\"${input.requireReasoningEffort}\\"" ]; then`,
106+
' printf "%s\\n" "unexpected reasoning effort config: $seen_reasoning_effort" >&2',
107+
` exit 6`,
108+
"fi",
109+
]
110+
: []),
111+
...(input.forbidReasoningEffort
112+
? [
113+
'if [ -n "$seen_reasoning_effort" ]; then',
114+
' printf "%s\\n" "reasoning effort config should be omitted: $seen_reasoning_effort" >&2',
115+
` exit 7`,
116+
"fi",
117+
]
118+
: []),
119+
...(input.stdinMustContain !== undefined
120+
? [
121+
`if ! printf "%s" "$stdin_content" | grep -F -- ${JSON.stringify(input.stdinMustContain)} >/dev/null; then`,
122+
' printf "%s\\n" "stdin missing expected content" >&2',
123+
` exit 3`,
124+
"fi",
125+
]
126+
: []),
127+
...(input.stdinMustNotContain !== undefined
128+
? [
129+
`if printf "%s" "$stdin_content" | grep -F -- ${JSON.stringify(input.stdinMustNotContain)} >/dev/null; then`,
130+
' printf "%s\\n" "stdin contained forbidden content" >&2',
131+
` exit 4`,
132+
"fi",
133+
]
134+
: []),
135+
...(input.stderr !== undefined
136+
? [`printf "%s\\n" ${JSON.stringify(input.stderr)} >&2`]
137+
: []),
98138
'if [ -n "$output_path" ]; then',
99-
' node -e \'const fs=require("node:fs"); const value=process.argv[2] ?? ""; fs.writeFileSync(process.argv[1], Buffer.from(value, "base64"));\' "$output_path" "${T3_FAKE_CODEX_OUTPUT_B64:-e30=}"',
139+
" cat > \"$output_path\" <<'__T3CODE_FAKE_CODEX_OUTPUT__'",
140+
input.output,
141+
"__T3CODE_FAKE_CODEX_OUTPUT__",
100142
"fi",
101-
'exit "${T3_FAKE_CODEX_EXIT_CODE:-0}"',
143+
`exit ${input.exitCode ?? 0}`,
102144
"",
103145
].join("\n"),
104146
);
105147
yield* fs.chmod(codexPath, 0o755);
106-
return binDir;
148+
return codexPath;
107149
});
108150
}
109151

@@ -125,146 +167,29 @@ function withFakeCodexEnv<A, E, R>(
125167
Effect.gen(function* () {
126168
const fs = yield* FileSystem.FileSystem;
127169
const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3code-codex-text-" });
128-
const binDir = yield* makeFakeCodexBinary(tempDir);
129-
const previousPath = process.env.PATH;
130-
const previousOutput = process.env.T3_FAKE_CODEX_OUTPUT_B64;
131-
const previousExitCode = process.env.T3_FAKE_CODEX_EXIT_CODE;
132-
const previousStderr = process.env.T3_FAKE_CODEX_STDERR;
133-
const previousRequireImage = process.env.T3_FAKE_CODEX_REQUIRE_IMAGE;
134-
const previousRequireFastServiceTier = process.env.T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER;
135-
const previousRequireReasoningEffort = process.env.T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT;
136-
const previousForbidReasoningEffort = process.env.T3_FAKE_CODEX_FORBID_REASONING_EFFORT;
137-
const previousStdinMustContain = process.env.T3_FAKE_CODEX_STDIN_MUST_CONTAIN;
138-
const previousStdinMustNotContain = process.env.T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN;
139-
140-
yield* Effect.sync(() => {
141-
process.env.PATH = `${binDir}:${previousPath ?? ""}`;
142-
process.env.T3_FAKE_CODEX_OUTPUT_B64 = Buffer.from(input.output, "utf8").toString("base64");
143-
144-
if (input.exitCode !== undefined) {
145-
process.env.T3_FAKE_CODEX_EXIT_CODE = String(input.exitCode);
146-
} else {
147-
delete process.env.T3_FAKE_CODEX_EXIT_CODE;
148-
}
149-
150-
if (input.stderr !== undefined) {
151-
process.env.T3_FAKE_CODEX_STDERR = input.stderr;
152-
} else {
153-
delete process.env.T3_FAKE_CODEX_STDERR;
154-
}
155-
156-
if (input.requireImage) {
157-
process.env.T3_FAKE_CODEX_REQUIRE_IMAGE = "1";
158-
} else {
159-
delete process.env.T3_FAKE_CODEX_REQUIRE_IMAGE;
160-
}
161-
162-
if (input.requireFastServiceTier) {
163-
process.env.T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER = "1";
164-
} else {
165-
delete process.env.T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER;
166-
}
167-
168-
if (input.requireReasoningEffort !== undefined) {
169-
process.env.T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT = input.requireReasoningEffort;
170-
} else {
171-
delete process.env.T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT;
172-
}
173-
174-
if (input.forbidReasoningEffort) {
175-
process.env.T3_FAKE_CODEX_FORBID_REASONING_EFFORT = "1";
176-
} else {
177-
delete process.env.T3_FAKE_CODEX_FORBID_REASONING_EFFORT;
178-
}
179-
180-
if (input.stdinMustContain !== undefined) {
181-
process.env.T3_FAKE_CODEX_STDIN_MUST_CONTAIN = input.stdinMustContain;
182-
} else {
183-
delete process.env.T3_FAKE_CODEX_STDIN_MUST_CONTAIN;
184-
}
185-
186-
if (input.stdinMustNotContain !== undefined) {
187-
process.env.T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN = input.stdinMustNotContain;
188-
} else {
189-
delete process.env.T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN;
190-
}
170+
const codexPath = yield* makeFakeCodexBinary(tempDir, input);
171+
const serverSettings = yield* ServerSettingsService;
172+
const previousSettings = yield* serverSettings.getSettings;
173+
yield* serverSettings.updateSettings({
174+
providers: {
175+
codex: {
176+
binaryPath: codexPath,
177+
},
178+
},
191179
});
192-
193-
return {
194-
previousPath,
195-
previousOutput,
196-
previousExitCode,
197-
previousStderr,
198-
previousRequireImage,
199-
previousRequireFastServiceTier,
200-
previousRequireReasoningEffort,
201-
previousForbidReasoningEffort,
202-
previousStdinMustContain,
203-
previousStdinMustNotContain,
204-
};
180+
return { serverSettings, previousBinaryPath: previousSettings.providers.codex.binaryPath };
205181
}),
206182
() => effect,
207-
(previous) =>
208-
Effect.sync(() => {
209-
process.env.PATH = previous.previousPath;
210-
211-
if (previous.previousOutput === undefined) {
212-
delete process.env.T3_FAKE_CODEX_OUTPUT_B64;
213-
} else {
214-
process.env.T3_FAKE_CODEX_OUTPUT_B64 = previous.previousOutput;
215-
}
216-
217-
if (previous.previousExitCode === undefined) {
218-
delete process.env.T3_FAKE_CODEX_EXIT_CODE;
219-
} else {
220-
process.env.T3_FAKE_CODEX_EXIT_CODE = previous.previousExitCode;
221-
}
222-
223-
if (previous.previousStderr === undefined) {
224-
delete process.env.T3_FAKE_CODEX_STDERR;
225-
} else {
226-
process.env.T3_FAKE_CODEX_STDERR = previous.previousStderr;
227-
}
228-
229-
if (previous.previousRequireImage === undefined) {
230-
delete process.env.T3_FAKE_CODEX_REQUIRE_IMAGE;
231-
} else {
232-
process.env.T3_FAKE_CODEX_REQUIRE_IMAGE = previous.previousRequireImage;
233-
}
234-
235-
if (previous.previousRequireFastServiceTier === undefined) {
236-
delete process.env.T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER;
237-
} else {
238-
process.env.T3_FAKE_CODEX_REQUIRE_FAST_SERVICE_TIER =
239-
previous.previousRequireFastServiceTier;
240-
}
241-
242-
if (previous.previousRequireReasoningEffort === undefined) {
243-
delete process.env.T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT;
244-
} else {
245-
process.env.T3_FAKE_CODEX_REQUIRE_REASONING_EFFORT =
246-
previous.previousRequireReasoningEffort;
247-
}
248-
249-
if (previous.previousForbidReasoningEffort === undefined) {
250-
delete process.env.T3_FAKE_CODEX_FORBID_REASONING_EFFORT;
251-
} else {
252-
process.env.T3_FAKE_CODEX_FORBID_REASONING_EFFORT =
253-
previous.previousForbidReasoningEffort;
254-
}
255-
256-
if (previous.previousStdinMustContain === undefined) {
257-
delete process.env.T3_FAKE_CODEX_STDIN_MUST_CONTAIN;
258-
} else {
259-
process.env.T3_FAKE_CODEX_STDIN_MUST_CONTAIN = previous.previousStdinMustContain;
260-
}
261-
262-
if (previous.previousStdinMustNotContain === undefined) {
263-
delete process.env.T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN;
264-
} else {
265-
process.env.T3_FAKE_CODEX_STDIN_MUST_NOT_CONTAIN = previous.previousStdinMustNotContain;
266-
}
267-
}),
183+
({ serverSettings, previousBinaryPath }) =>
184+
serverSettings
185+
.updateSettings({
186+
providers: {
187+
codex: {
188+
binaryPath: previousBinaryPath,
189+
},
190+
},
191+
})
192+
.pipe(Effect.asVoid),
268193
);
269194
}
270195

apps/server/src/serverSettings.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,26 @@ export class ServerSettingsService extends ServiceMap.Service<
7777
ServerSettingsShape
7878
>()("t3/serverSettings/ServerSettingsService") {
7979
static readonly layerTest = (overrides: Partial<ServerSettings> = {}) =>
80-
Layer.succeed(ServerSettingsService, {
81-
start: Effect.void,
82-
ready: Effect.void,
83-
getSettings: Effect.succeed({ ...DEFAULT_SERVER_SETTINGS, ...overrides }),
84-
updateSettings: () => Effect.succeed({ ...DEFAULT_SERVER_SETTINGS, ...overrides }),
85-
streamChanges: Stream.empty,
86-
} satisfies ServerSettingsShape);
80+
Layer.effect(
81+
ServerSettingsService,
82+
Effect.gen(function* () {
83+
const currentSettingsRef = yield* Ref.make<ServerSettings>(
84+
deepMerge(DEFAULT_SERVER_SETTINGS, overrides),
85+
);
86+
87+
return {
88+
start: Effect.void,
89+
ready: Effect.void,
90+
getSettings: Ref.get(currentSettingsRef),
91+
updateSettings: (patch) =>
92+
Ref.get(currentSettingsRef).pipe(
93+
Effect.map((currentSettings) => deepMerge(currentSettings, patch)),
94+
Effect.tap((nextSettings) => Ref.set(currentSettingsRef, nextSettings)),
95+
),
96+
streamChanges: Stream.empty,
97+
} satisfies ServerSettingsShape;
98+
}),
99+
);
87100
}
88101

89102
const ServerSettingsJson = fromLenientJson(ServerSettings);

0 commit comments

Comments
 (0)