Skip to content

Commit 180494e

Browse files
fix(grok): run grok update with the instance's environment
`grok update` installs under `GROK_HOME`, so an instance configured with a custom home updated the default install and left its own binary outdated. Pass the instance environment to the updater, like Codex does for `CODEX_HOME`, and drop the node-builtin diagnostic suppression in the test. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
1 parent eed0dd9 commit 180494e

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

‎apps/server/src/provider/Drivers/GrokDriver.test.ts‎

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
// @effect-diagnostics nodeBuiltinImport:off
21
import * as NodeServices from "@effect/platform-node/NodeServices";
3-
import * as NodeOS from "node:os";
4-
import * as NodePath from "node:path";
52
import { expect, it } from "@effect/vitest";
63
import { ProviderInstanceId } from "@t3tools/contracts";
74
import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
85
import * as Effect from "effect/Effect";
96
import * as FileSystem from "effect/FileSystem";
107
import * as Layer from "effect/Layer";
8+
import * as Path from "effect/Path";
119
import { HttpClient } from "effect/unstable/http";
1210
import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner";
1311

@@ -47,17 +45,19 @@ it.layer(testLayer)("GrokDriver", (it) => {
4745
it.effect.skipIf(windowsHost)("updates through the configured executable's own updater", () =>
4846
Effect.gen(function* () {
4947
const fs = yield* FileSystem.FileSystem;
48+
const path = yield* Path.Path;
5049
const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-grok-driver-" });
51-
const binaryPath = NodePath.join(tempDir, "Grok Tools", "bin", "grok");
52-
yield* fs.makeDirectory(NodePath.dirname(binaryPath), { recursive: true });
50+
const grokHome = path.join(tempDir, "Grok Home");
51+
const binaryPath = path.join(grokHome, "bin", "grok");
52+
yield* fs.makeDirectory(path.dirname(binaryPath), { recursive: true });
5353
yield* fs.writeFileString(binaryPath, "#!/bin/sh\n");
5454
yield* fs.chmod(binaryPath, 0o755);
5555

5656
const instance = yield* GrokDriver.create({
5757
instanceId: ProviderInstanceId.make("grok-update"),
5858
displayName: "Grok test",
5959
enabled: false,
60-
environment: [],
60+
environment: [{ name: "GROK_HOME", value: grokHome, sensitive: false }],
6161
config: { ...GrokDriver.defaultConfig(), binaryPath },
6262
});
6363

@@ -68,6 +68,8 @@ it.layer(testLayer)("GrokDriver", (it) => {
6868
executable: binaryPath,
6969
args: ["update"],
7070
});
71+
// `grok update` installs under GROK_HOME, so it must target this instance's home.
72+
expect(capabilities.update?.env?.GROK_HOME).toBe(grokHome);
7173
}).pipe(
7274
Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, noSpawner),
7375
Effect.scoped,
@@ -76,15 +78,15 @@ it.layer(testLayer)("GrokDriver", (it) => {
7678

7779
it.effect("stays manual-only when the configured executable does not exist", () =>
7880
Effect.gen(function* () {
81+
const fs = yield* FileSystem.FileSystem;
82+
const path = yield* Path.Path;
83+
const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-grok-missing-" });
7984
const instance = yield* GrokDriver.create({
8085
instanceId: ProviderInstanceId.make("grok-missing"),
8186
displayName: "Grok test",
8287
enabled: false,
8388
environment: [],
84-
config: {
85-
...GrokDriver.defaultConfig(),
86-
binaryPath: NodePath.join(NodeOS.tmpdir(), "t3-grok-missing", "grok"),
87-
},
89+
config: { ...GrokDriver.defaultConfig(), binaryPath: path.join(tempDir, "grok") },
8890
});
8991
expect((yield* instance.snapshot.resolveMaintenance()).update).toBeNull();
9092
}).pipe(

‎apps/server/src/provider/Drivers/GrokDriver.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ const DRIVER_KIND = ProviderDriverKind.make("grok");
4848
// by default, so the registry stays the source for "latest".
4949
const GROK_NPM_PACKAGE = "@xai-official/grok";
5050
// `grok update` finds the installer that owns the binary itself, so the
51-
// resolved executable is its own updater. No executable means nothing to
52-
// update, not "whatever is on PATH".
51+
// resolved executable is its own updater. It installs under `GROK_HOME`, so it
52+
// runs with the instance's environment. No executable means nothing to update,
53+
// not "whatever is on PATH".
5354
const UPDATE: ProviderMaintenanceCapabilitiesResolver = {
5455
resolve: (context) =>
5556
Effect.succeed(
@@ -61,6 +62,7 @@ const UPDATE: ProviderMaintenanceCapabilitiesResolver = {
6162
updateArgs: ["update"],
6263
updateLockKey: "grok",
6364
platform: context.platform,
65+
env: context.env,
6466
})
6567
: makeManualOnlyProviderMaintenanceCapabilities({
6668
provider: DRIVER_KIND,

0 commit comments

Comments
 (0)