| ... | @@ -1514,6 +1514,54 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { | ... | @@ -1514,6 +1514,54 @@ it.layer(GitManagerTestLayer)("GitManager", (it) => { |
| 1514 | }), | 1514 | }), |
| 1515 | ); | 1515 | ); |
| 1516 | | 1516 | |
| | 1517 | it.effect("status keeps the last known PR when the current remote URL can't be resolved", () => |
| | 1518 | Effect.gen(function* () { |
| | 1519 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |
| | 1520 | yield* initRepo(repoDir); |
| | 1521 | yield* runGit(repoDir, ["checkout", "-b", "feature/pr-config-hiccup"]); |
| | 1522 | const remoteDir = yield* createBareRemote(); |
| | 1523 | yield* runGit(repoDir, ["remote", "add", "origin", remoteDir]); |
| | 1524 | yield* runGit(repoDir, ["push", "-u", "origin", "feature/pr-config-hiccup"]); |
| | 1525 | |
| | 1526 | const existingPr = { |
| | 1527 | number: 217, |
| | 1528 | title: "Config hiccup PR", |
| | 1529 | url: "https://github.com/pingdotgg/codething-mvp/pull/217", |
| | 1530 | baseRefName: "main", |
| | 1531 | headRefName: "feature/pr-config-hiccup", |
| | 1532 | }; |
| | 1533 | const { manager } = yield* makeManager({ |
| | 1534 | ghScenario: { |
| | 1535 | // @effect-diagnostics-next-line preferSchemaOverJson:off |
| | 1536 | prListSequence: [JSON.stringify([existingPr])], |
| | 1537 | failWith: new GitHubCli.GitHubCliUnavailableError({ |
| | 1538 | command: "gh", |
| | 1539 | cwd: repoDir, |
| | 1540 | cause: new Error("rate limited"), |
| | 1541 | }), |
| | 1542 | failAfterCalls: 1, |
| | 1543 | }, |
| | 1544 | }); |
| | 1545 | |
| | 1546 | const first = yield* manager.status({ cwd: repoDir }); |
| | 1547 | expect(first.pr?.number).toBe(217); |
| | 1548 | |
| | 1549 | // `remote.origin.url` reads go through readConfigValueNullable, which |
| | 1550 | // maps ANY failed read (a real "no remote configured" state or a |
| | 1551 | // transient git-config hiccup) to null the same way. Unsetting the |
| | 1552 | // key here reproduces that ambiguity without touching branch |
| | 1553 | // tracking (refs/remotes/origin/* and branch.<b>.remote are |
| | 1554 | // untouched) — the remote identity has not actually changed, so the |
| | 1555 | // sticky PR must survive even though the current lookup can no |
| | 1556 | // longer resolve a remote URL to compare against. |
| | 1557 | yield* runGit(repoDir, ["config", "--unset", "remote.origin.url"]); |
| | 1558 | yield* manager.invalidateStatus(repoDir); |
| | 1559 | |
| | 1560 | const second = yield* manager.status({ cwd: repoDir }); |
| | 1561 | expect(second.pr?.number).toBe(217); |
| | 1562 | }), |
| | 1563 | ); |
| | 1564 | |
| 1517 | it.effect("creates a commit when working tree is dirty", () => | 1565 | it.effect("creates a commit when working tree is dirty", () => |
| 1518 | Effect.gen(function* () { | 1566 | Effect.gen(function* () { |
| 1519 | const repoDir = yield* makeTempDir("t3code-git-manager-"); | 1567 | const repoDir = yield* makeTempDir("t3code-git-manager-"); |