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
56 changes: 17 additions & 39 deletions apps/server/src/git/GitManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,8 @@ function runGitSyncForFakeGh(cwd: string, args: readonly string[]): void {
if (result.status === 0) {
return;
}
throw new GitHubCli.GitHubCliError({
operation: "execute",
command: "gh",
cwd,
detail: `Failed to simulate gh checkout with git ${args.join(" ")}: ${result.stderr?.trim() || "unknown error"}`,
});
}

function isGitHubCliError(error: unknown): error is GitHubCli.GitHubCliError {
return (
typeof error === "object" &&
error !== null &&
"_tag" in error &&
(error as { _tag?: unknown })._tag === "GitHubCliError"
throw new Error(
`Failed to simulate gh checkout with git ${args.join(" ")}: ${result.stderr?.trim() || "unknown error"}`,
);
}

Expand Down Expand Up @@ -478,16 +466,12 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): {
return fakeGhOutput("");
},
catch: (error) =>
isGitHubCliError(error)
GitHubCli.isGitHubCliError(error)
? error
: new GitHubCli.GitHubCliError({
operation: "execute",
: new GitHubCli.GitHubCliCommandError({
command: "gh",
cwd: input.cwd,
detail:
error instanceof Error
? `Failed to simulate gh checkout: ${error.message}`
: "Failed to simulate gh checkout.",
cause: error,
}),
});
}
Expand All @@ -498,11 +482,10 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): {
const cloneUrls = scenario.repositoryCloneUrls?.[repository];
if (!cloneUrls) {
return Effect.fail(
new GitHubCli.GitHubCliError({
operation: "execute",
new GitHubCli.GitHubCliCommandError({
command: "gh",
cwd: input.cwd,
detail: `Unexpected repository lookup: ${repository}`,
cause: new Error(`Unexpected repository lookup: ${repository}`),
}),
);
}
Expand All @@ -520,11 +503,10 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): {
}

return Effect.fail(
new GitHubCli.GitHubCliError({
operation: "execute",
new GitHubCli.GitHubCliCommandError({
command: "gh",
cwd: input.cwd,
detail: `Unexpected gh command: ${args.join(" ")}`,
cause: new Error(`Unexpected gh command: ${args.join(" ")}`),
}),
);
};
Expand Down Expand Up @@ -601,11 +583,10 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): {
}).pipe(Effect.map((result) => JSON.parse(result.stdout))),
createRepository: (input) =>
Effect.fail(
new GitHubCli.GitHubCliError({
operation: "createRepository",
new GitHubCli.GitHubCliCommandError({
command: "gh",
cwd: input.cwd,
detail: `Unexpected repository create: ${input.repository}`,
cause: new Error(`Unexpected repository create: ${input.repository}`),
}),
),
checkoutPullRequest: (input) =>
Expand Down Expand Up @@ -1341,11 +1322,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => {

const { manager } = yield* makeManager({
ghScenario: {
failWith: new GitHubCli.GitHubCliError({
operation: "execute",
failWith: new GitHubCli.GitHubCliUnavailableError({
command: "gh",
cwd: repoDir,
detail: "GitHub CLI (`gh`) is required but not available on PATH.",
cause: new Error("gh is not available on PATH"),
}),
},
});
Expand Down Expand Up @@ -2483,11 +2463,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => {

const { manager } = yield* makeManager({
ghScenario: {
failWith: new GitHubCli.GitHubCliError({
operation: "execute",
failWith: new GitHubCli.GitHubCliUnavailableError({
command: "gh",
cwd: repoDir,
detail: "GitHub CLI (`gh`) is required but not available on PATH.",
cause: new Error("gh is not available on PATH"),
}),
},
});
Expand All @@ -2514,11 +2493,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => {

const { manager } = yield* makeManager({
ghScenario: {
failWith: new GitHubCli.GitHubCliError({
operation: "execute",
failWith: new GitHubCli.GitHubCliAuthenticationError({
command: "gh",
cwd: repoDir,
detail: "GitHub CLI is not authenticated. Run `gh auth login` and retry.",
cause: new Error("gh is not authenticated"),
}),
},
});
Expand Down
26 changes: 25 additions & 1 deletion apps/server/src/sourceControl/GitHubCli.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { assert, it, afterEach, describe, expect, vi } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as Layer from "effect/Layer";
import * as PlatformError from "effect/PlatformError";
import { ChildProcessSpawner } from "effect/unstable/process";
import { VcsProcessExitError } from "@t3tools/contracts";
import { VcsProcessExitError, VcsProcessSpawnError } from "@t3tools/contracts";

import * as VcsProcess from "../vcs/VcsProcess.ts";
import * as GitHubCli from "./GitHubCli.ts";
Expand Down Expand Up @@ -30,6 +31,27 @@ afterEach(() => {
});

describe("GitHubCli.layer", () => {
it("does not classify a missing cwd as an unavailable gh executable", () => {
const context = { command: "gh", cwd: "/repo" } as const;
const missingCwd = new VcsProcessSpawnError({
operation: "GitHubCli.execute",
command: "gh",
cwd: context.cwd,
cause: PlatformError.systemError({
_tag: "NotFound",
module: "FileSystem",
method: "access",
pathOrDescriptor: context.cwd,
}),
});

const commandFailure = GitHubCli.fromVcsError(context, missingCwd);

assert.equal(commandFailure._tag, "GitHubCliCommandError");
assert.strictEqual(commandFailure.cause, missingCwd);
assert.notProperty(commandFailure, "operation");
});

it.effect("parses pull request view output", () =>
Effect.gen(function* () {
mockRun.mockReturnValueOnce(
Expand Down Expand Up @@ -274,6 +296,7 @@ describe("GitHubCli.layer", () => {
command: "gh pr view",
cwd: "/repo",
exitCode: 1,
failureKind: "not-found",
detail:
"GraphQL: Could not resolve to a PullRequest with the number of 4888. (repository.pullRequest)",
});
Expand All @@ -288,6 +311,7 @@ describe("GitHubCli.layer", () => {
.pipe(Effect.flip);

assert.equal(error.message.includes("Pull request not found"), true);
assert.strictEqual(error._tag, "GitHubPullRequestNotFoundError");
assert.strictEqual(error.command, "gh");
assert.strictEqual(error.cwd, "/repo");
assert.strictEqual(error.cause, cause);
Expand Down
Loading
Loading