Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions packages/evals/__tests__/check-codex-marketplace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,52 @@ describe("Codex marketplace smoke lifecycle", () => {
assert.isFalse(yield* fs.exists(path.dirname(codexHome)));
}),
);
it.effect("does not run Codex cleanup when repository credential removal fails", () =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const commands: MarketplaceCommandInput[] = [];
let removalAttempts = 0;
const result = yield* Effect.result(
runCodexMarketplaceSmoke({
...OPTIONS,
runner: makeFakeRunner(commands),
parentEnvironment: {
PATH: "/usr/bin:/bin",
CODEX_MARKETPLACE_REPOSITORY_TOKEN: "repository-secret",
},
removeRepositoryCredentialFile: () => {
removalAttempts += 1;
return Effect.fail(
new CodexMarketplaceSmokeError({
stage: "environment",
reason: "io-failed",
detail: "synthetic credential removal failure",
}),
);
},
}),
);

assert.strictEqual(result._tag, "Failure");
if (result._tag === "Failure") {
assert.strictEqual(result.failure.stage, "environment");
assert.strictEqual(result.failure.reason, "io-failed");
assert.strictEqual(
result.failure.detail,
"cannot remove isolated repository credentials",
);
}
assert.strictEqual(removalAttempts, 2);
assert.deepStrictEqual(
commands.map((command) => command.stage),
["marketplace-add"],
);
const codexHome = commands[0]?.environment.CODEX_HOME;
if (codexHome === undefined) return yield* Effect.die("fake runner did not capture home");
assert.isFalse(yield* fs.exists(path.dirname(codexHome)));
}),
);

it.effect("rejects the legacy gina MCP alias during deterministic inspection", () =>
Effect.gen(function* () {
Expand Down
14 changes: 12 additions & 2 deletions packages/evals/src/bin/check-codex-marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ export interface MarketplaceCommandRunner {
}
export interface CodexMarketplaceSmokeRunOptions extends CodexMarketplaceSmokeOptions {
readonly runner?: MarketplaceCommandRunner;
readonly removeRepositoryCredentialFile?: (
file: string,
) => Effect.Effect<void, CodexMarketplaceSmokeError, never>;
readonly parentEnvironment?: Readonly<Record<string, string | undefined>>;
}

Expand Down Expand Up @@ -681,8 +684,10 @@ esac
? Effect.void
: Effect.gen(function* () {
const credentialFiles = [repositoryTokenFile, gitAskpassFile] as const;
const removeCredentialFile =
options.removeRepositoryCredentialFile ?? ((file: string) => fs.remove(file));
for (const file of credentialFiles) {
if (yield* fs.exists(file)) yield* fs.remove(file);
if (yield* fs.exists(file)) yield* removeCredentialFile(file);
}
for (const file of credentialFiles) {
if (yield* fs.exists(file)) {
Expand All @@ -702,6 +707,7 @@ esac
detail: "cannot remove isolated repository credentials",
}),
),
Effect.asVoid,
);
const runCommand = (
stage: MarketplaceCommandInput["stage"],
Expand All @@ -720,7 +726,7 @@ esac
environment: commandEnvironment,
timeoutMs: options.timeoutMs,
});
const cleanup = Effect.gen(function* () {
const cleanupCommands = Effect.gen(function* () {
yield* runCommand("plugin-remove", ["plugin", "remove", PLUGIN_ID, "--json"]).pipe(
Effect.ignore,
);
Expand All @@ -732,6 +738,10 @@ esac
"--json",
]).pipe(Effect.ignore);
});
const cleanup = removeRepositoryCredentials.pipe(
Effect.flatMap(() => cleanupCommands),
Effect.ignore,
);

return yield* Effect.gen(function* () {
const marketplaceAttempt = yield* Effect.result(
Expand Down
Loading