From 9c6198a2af8a24efc4e0eb4ff33142beaeadd45a Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Fri, 30 Oct 2026 20:14:42 -0300 Subject: [PATCH 1/2] fix(server): stop matching GitHub fork pull requests to the repository's own branch on GitCafe --- .../GitCafeSourceControlProvider.test.ts | 36 +++++++++++++++++++ .../server/GitCafeSourceControlProvider.ts | 17 ++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.test.ts b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.test.ts index 111ffbd1537c3..588734b754f50 100644 --- a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.test.ts +++ b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.test.ts @@ -276,6 +276,42 @@ describe("GitCafeSourceControlProvider", () => { ); }); + it.effect("keeps a GitHub fork's pull request off the repository's own branch", () => { + const client = HttpClient.make((request) => + Effect.succeed( + HttpClientResponse.fromWeb( + request, + new Response( + encodeJson({ + number: 7, + title: "Change", + state: "open", + draft: false, + sourceBranch: "main", + targetBranch: "main", + headOid: null, + updatedAt: null, + sourceRepo: null, + isCrossFork: true, + closedAt: null, + mergedAt: null, + }), + ), + ), + ), + ); + return Effect.gen(function* () { + const provider = yield* GitCafeSourceControlProvider.make; + const pull = yield* provider.getChangeRequest({ + cwd: "/repo", + reference: "https://git.cafe/team/project/pulls/7", + }); + assert.strictEqual(pull.isCrossRepository, true); + assert.strictEqual(pull.headRepositoryNameWithOwner, undefined); + assert.strictEqual(pull.headRepositoryOwnerLogin, undefined); + }).pipe(Effect.provide(layerFor(client))); + }); + it.effect("opens a pull request from a fork over REST with the body file's text", () => { const sent: Array<{ method: string; url: string; body: unknown }> = []; const client = HttpClient.make((request) => { diff --git a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts index e02ebd0b45527..faf70413cf37e 100644 --- a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts +++ b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts @@ -139,6 +139,7 @@ const PullDetail = Schema.Struct({ sourceRepo: Schema.NullOr( Schema.Struct({ owner: TrimmedNonEmptyString, name: TrimmedNonEmptyString }), ), + isCrossFork: Schema.optional(Schema.Boolean), closedAt: Schema.NullOr(Schema.String), mergedAt: Schema.NullOr(Schema.String), }); @@ -265,6 +266,8 @@ export const make = Effect.gen(function* () { PullDetail, ); const owner = target.repository.split("/")[0] ?? null; + // Pulls synced from GitHub forks report isCrossFork without naming the fork. + const unnamedFork = pull.sourceRepo === null && pull.isCrossFork === true; return { provider: SourceControlProviderKind.make("gitcafe"), number: pull.number, @@ -278,11 +281,15 @@ export const make = Effect.gen(function* () { closedAt: pull.closedAt, mergedAt: pull.mergedAt, updatedAt: pull.updatedAt, - isCrossRepository: pull.sourceRepo !== null, - headRepositoryNameWithOwner: pull.sourceRepo - ? `${pull.sourceRepo.owner}/${pull.sourceRepo.name}` - : target.repository, - headRepositoryOwnerLogin: pull.sourceRepo?.owner ?? owner, + isCrossRepository: pull.sourceRepo !== null || unnamedFork, + ...(unnamedFork + ? {} + : { + headRepositoryNameWithOwner: pull.sourceRepo + ? `${pull.sourceRepo.owner}/${pull.sourceRepo.name}` + : target.repository, + headRepositoryOwnerLogin: pull.sourceRepo?.owner ?? owner, + }), } satisfies ChangeRequest; }); From 6c1a73549a63adca46924c372fbc5ddaabca42ca Mon Sep 17 00:00:00 2001 From: maria-rcks Date: Fri, 30 Oct 2026 20:42:50 -0300 Subject: [PATCH 2/2] fix(server): read past GitCafe fork pulls when finding a branch's open pull request --- .../src/server/GitCafeSourceControlProvider.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts index faf70413cf37e..8800622987f55 100644 --- a/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts +++ b/packages/source-control-gitcafe/src/server/GitCafeSourceControlProvider.ts @@ -295,6 +295,8 @@ export const make = Effect.gen(function* () { return SourceControlProvider.SourceControlProvider.of({ kind: SourceControlProviderKind.make("gitcafe"), + // Fork pulls share bare branch names; read past them to this repository's own pull. + headBranchProbe: ({ headSelectors }) => ({ headSelectors, limit: 20 }), repositoryNameFromRemoteUrl: (url) => GitCafeHosts.parseGitCafeRemote(url)?.repository ?? null, getChangeRequest: getPull, listChangeRequests: Effect.fn("GitCafeSourceControlProvider.listChangeRequests")(