| ... | ... | @@ -102,4 +102,120 @@ it.layer(testLayer)("CodexDriver", (it) => { |
| 102 | 102 | expect((yield* instance.snapshot.resolveMaintenance()).update).toBeNull(); |
| 103 | 103 | }).pipe(Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, noSpawn), Effect.scoped), |
| 104 | 104 | ); |
| 105 | |
| 106 | for (const fixture of [ |
| 107 | { |
| 108 | name: "leaves mise npm-backend installations manual-only", |
| 109 | installSegments: ["mise", "installs", "npm-openai-codex", "0.110.0"], |
| 110 | npmOwned: false, |
| 111 | }, |
| 112 | { |
| 113 | name: "leaves mise tool aliases backed by npm manual-only", |
| 114 | installSegments: ["mise", "installs", "codex", "0.110.0"], |
| 115 | npmOwned: false, |
| 116 | }, |
| 117 | { |
| 118 | name: "keeps npm updates for globals in a mise Node installation", |
| 119 | installSegments: ["mise", "installs", "node", "24.0.0"], |
| 120 | npmOwned: true, |
| 121 | }, |
| 122 | { |
| 123 | name: "keeps npm updates for ordinary global installations", |
| 124 | installSegments: ["npm-global"], |
| 125 | npmOwned: true, |
| 126 | }, |
| 127 | ] as const) { |
| 128 | it.effect.skipIf(windowsHost)(fixture.name, () => |
| 129 | Effect.gen(function* () { |
| 130 | const fs = yield* FileSystem.FileSystem; |
| 131 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-codex-installer-" }); |
| 132 | const installPath = NodePath.join(tempDir, ...fixture.installSegments); |
| 133 | const realBinaryPath = NodePath.join( |
| 134 | installPath, |
| 135 | "lib", |
| 136 | "node_modules", |
| 137 | "@openai", |
| 138 | "codex", |
| 139 | "bin", |
| 140 | "codex.js", |
| 141 | ); |
| 142 | const binaryPath = NodePath.join(tempDir, "bin", "codex"); |
| 143 | yield* fs.makeDirectory(NodePath.dirname(realBinaryPath), { recursive: true }); |
| 144 | yield* fs.makeDirectory(NodePath.dirname(binaryPath), { recursive: true }); |
| 145 | yield* fs.writeFileString(realBinaryPath, "#!/bin/sh\n"); |
| 146 | yield* fs.chmod(realBinaryPath, 0o755); |
| 147 | yield* fs.symlink(realBinaryPath, binaryPath); |
| 148 | |
| 149 | const instance = yield* CodexDriver.create({ |
| 150 | instanceId: ProviderInstanceId.make("codex-installer"), |
| 151 | displayName: "Codex installer test", |
| 152 | enabled: false, |
| 153 | environment: [], |
| 154 | config: { |
| 155 | ...CodexDriver.defaultConfig(), |
| 156 | binaryPath, |
| 157 | homePath: NodePath.join(tempDir, "codex-home"), |
| 158 | }, |
| 159 | }); |
| 160 | |
| 161 | const update = (yield* instance.snapshot.resolveMaintenance()).update; |
| 162 | if (fixture.npmOwned) { |
| 163 | expect(update).toMatchObject({ |
| 164 | executable: "npm", |
| 165 | args: [ |
| 166 | "install", |
| 167 | "-g", |
| 168 | "--prefix", |
| 169 | installPath, |
| 170 | "--allow-scripts=@openai/codex", |
| 171 | "@openai/codex@latest", |
| 172 | ], |
| 173 | }); |
| 174 | } else { |
| 175 | expect(update).toBeNull(); |
| 176 | } |
| 177 | }).pipe( |
| 178 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, noSpawn), |
| 179 | Effect.scoped, |
| 180 | ), |
| 181 | ); |
| 182 | } |
| 183 | |
| 184 | for (const layout of ["direct", "wrapper"] as const) { |
| 185 | it.effect.skipIf(windowsHost)(`leaves a mise ${layout} installation manual-only`, () => |
| 186 | Effect.gen(function* () { |
| 187 | const fs = yield* FileSystem.FileSystem; |
| 188 | const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: `t3-codex-mise-${layout}-` }); |
| 189 | const binaryPath = |
| 190 | layout === "direct" |
| 191 | ? NodePath.join(tempDir, "mise", "installs", "codex", "0.110.0", "codex") |
| 192 | : NodePath.join(tempDir, "omarchy", "bin", "codex"); |
| 193 | yield* fs.makeDirectory(NodePath.dirname(binaryPath), { recursive: true }); |
| 194 | yield* fs.writeFileString( |
| 195 | binaryPath, |
| 196 | layout === "direct" |
| 197 | ? "#!/bin/sh\n" |
| 198 | : '#!/bin/sh\nmise use -g --quiet "codex" || exit 1\nexec mise x "codex" -- "codex" "$@"\n', |
| 199 | ); |
| 200 | yield* fs.chmod(binaryPath, 0o755); |
| 201 | |
| 202 | const instance = yield* CodexDriver.create({ |
| 203 | instanceId: ProviderInstanceId.make(`codex-mise-${layout}`), |
| 204 | displayName: "Codex mise test", |
| 205 | enabled: false, |
| 206 | environment: [], |
| 207 | config: { |
| 208 | ...CodexDriver.defaultConfig(), |
| 209 | binaryPath, |
| 210 | homePath: NodePath.join(tempDir, "codex-home"), |
| 211 | }, |
| 212 | }); |
| 213 | |
| 214 | expect((yield* instance.snapshot.resolveMaintenance()).update).toBeNull(); |
| 215 | }).pipe( |
| 216 | Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, noSpawn), |
| 217 | Effect.scoped, |
| 218 | ), |
| 219 | ); |
| 220 | } |
| 105 | 221 | }); |