| ... | ... | @@ -3,7 +3,7 @@ import path from "node:path"; |
| 3 | 3 | |
| 4 | 4 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 5 | 5 | import { it } from "@effect/vitest"; |
| 6 | | import { Effect, FileSystem, Layer, PlatformError, Schema, Scope } from "effect"; |
| 6 | import { Effect, FileSystem, Layer, PlatformError, Scope } from "effect"; |
| 7 | 7 | import { expect } from "vitest"; |
| 8 | 8 | |
| 9 | 9 | import { GitCommandError, GitHubCliError, TextGenerationError } from "../Errors.ts"; |
| ... | ... | @@ -19,16 +19,11 @@ import { GitService } from "../Services/GitService.ts"; |
| 19 | 19 | import { GitCoreLive } from "./GitCore.ts"; |
| 20 | 20 | import { makeGitManager } from "./GitManager.ts"; |
| 21 | 21 | |
| 22 | | class GitFixtureError extends Schema.TaggedErrorClass<GitFixtureError>()("GitFixtureError", { |
| 23 | | message: Schema.String, |
| 24 | | cause: Schema.optional(Schema.Defect), |
| 25 | | }) {} |
| 26 | | |
| 27 | 22 | interface FakeGhScenario { |
| 28 | 23 | prListSequence?: string[]; |
| 29 | 24 | createdPrUrl?: string; |
| 30 | 25 | defaultBranch?: string; |
| 31 | | failWith?: GitFixtureError; |
| 26 | failWith?: GitHubCliError; |
| 32 | 27 | } |
| 33 | 28 | |
| 34 | 29 | interface FakeGitTextGeneration { |
| ... | ... | @@ -37,7 +32,7 @@ interface FakeGitTextGeneration { |
| 37 | 32 | branch: string | null; |
| 38 | 33 | stagedSummary: string; |
| 39 | 34 | stagedPatch: string; |
| 40 | | }) => Effect.Effect<{ subject: string; body: string }, GitFixtureError>; |
| 35 | }) => Effect.Effect<{ subject: string; body: string }, TextGenerationError>; |
| 41 | 36 | generatePrContent: (input: { |
| 42 | 37 | cwd: string; |
| 43 | 38 | baseBranch: string; |
| ... | ... | @@ -45,7 +40,7 @@ interface FakeGitTextGeneration { |
| 45 | 40 | commitSummary: string; |
| 46 | 41 | diffSummary: string; |
| 47 | 42 | diffPatch: string; |
| 48 | | }) => Effect.Effect<{ title: string; body: string }, GitFixtureError>; |
| 43 | }) => Effect.Effect<{ title: string; body: string }, TextGenerationError>; |
| 49 | 44 | } |
| 50 | 45 | |
| 51 | 46 | function makeTempDir( |
| ... | ... | @@ -144,34 +139,6 @@ function createTextGeneration(overrides: Partial<FakeGitTextGeneration> = {}): T |
| 144 | 139 | }; |
| 145 | 140 | } |
| 146 | 141 | |
| 147 | | const normalizeGhError = (error: GitFixtureError): GitHubCliError => { |
| 148 | | if (error.message.includes("Command not found: gh")) { |
| 149 | | return new GitHubCliError({ |
| 150 | | operation: "execute", |
| 151 | | detail: "GitHub CLI (`gh`) is required but not available on PATH.", |
| 152 | | cause: error, |
| 153 | | }); |
| 154 | | } |
| 155 | | const lower = error.message.toLowerCase(); |
| 156 | | if ( |
| 157 | | lower.includes("authentication failed") || |
| 158 | | lower.includes("not logged in") || |
| 159 | | lower.includes("gh auth login") || |
| 160 | | lower.includes("no oauth token") |
| 161 | | ) { |
| 162 | | return new GitHubCliError({ |
| 163 | | operation: "execute", |
| 164 | | detail: "GitHub CLI is not authenticated. Run `gh auth login` and retry.", |
| 165 | | cause: error, |
| 166 | | }); |
| 167 | | } |
| 168 | | return new GitHubCliError({ |
| 169 | | operation: "execute", |
| 170 | | detail: error.message, |
| 171 | | cause: error, |
| 172 | | }); |
| 173 | | }; |
| 174 | | |
| 175 | 142 | function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): { |
| 176 | 143 | service: GitHubCliShape; |
| 177 | 144 | ghCalls: string[]; |
| ... | ... | @@ -184,7 +151,7 @@ function createGitHubCliWithFakeGh(scenario: FakeGhScenario = {}): { |
| 184 | 151 | ghCalls.push(args.join(" ")); |
| 185 | 152 | |
| 186 | 153 | if (scenario.failWith) { |
| 187 | | return Effect.fail(normalizeGhError(scenario.failWith)); |
| 154 | return Effect.fail(scenario.failWith); |
| 188 | 155 | } |
| 189 | 156 | |
| 190 | 157 | if (args[0] === "pr" && args[1] === "list") { |
| ... | ... | @@ -378,7 +345,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 378 | 345 | |
| 379 | 346 | const { manager } = yield* makeManager({ |
| 380 | 347 | ghScenario: { |
| 381 | | failWith: new GitFixtureError({ message: "Command not found: gh" }), |
| 348 | failWith: new GitHubCliError({ |
| 349 | operation: "execute", |
| 350 | detail: "GitHub CLI (`gh`) is required but not available on PATH.", |
| 351 | }), |
| 382 | 352 | }, |
| 383 | 353 | }); |
| 384 | 354 | |
| ... | ... | @@ -622,7 +592,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 622 | 592 | |
| 623 | 593 | const { manager } = yield* makeManager({ |
| 624 | 594 | ghScenario: { |
| 625 | | failWith: new GitFixtureError({ message: "Command not found: gh" }), |
| 595 | failWith: new GitHubCliError({ |
| 596 | operation: "execute", |
| 597 | detail: "GitHub CLI (`gh`) is required but not available on PATH.", |
| 598 | }), |
| 626 | 599 | }, |
| 627 | 600 | }); |
| 628 | 601 | |
| ... | ... | @@ -648,7 +621,10 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 648 | 621 | |
| 649 | 622 | const { manager } = yield* makeManager({ |
| 650 | 623 | ghScenario: { |
| 651 | | failWith: new GitFixtureError({ message: "authentication failed" }), |
| 624 | failWith: new GitHubCliError({ |
| 625 | operation: "execute", |
| 626 | detail: "GitHub CLI is not authenticated. Run `gh auth login` and retry.", |
| 627 | }), |
| 652 | 628 | }, |
| 653 | 629 | }); |
| 654 | 630 | |