diff --git a/src/app/SyncGithub.test.ts b/src/app/SyncGithub.test.ts new file mode 100644 index 0000000..f4d2124 --- /dev/null +++ b/src/app/SyncGithub.test.ts @@ -0,0 +1,52 @@ +import { expect, test } from "bun:test"; + +import type { CommitMetadataGroup } from "./SyncGithub"; +import { _is_master_base } from "./SyncGithub"; + +function buildGroup(overrides: Partial = {}): CommitMetadataGroup { + return { + id: "group-1", + title: "title", + master_base: false, + base: "feature/base", + dirty: false, + commits: [], + pr: { + id: "pr-id", + number: 1, + state: "OPEN", + baseRefName: "master", + headRefName: "group-1", + commits: [] as any, + title: "t", + body: "", + url: "https://example.com/pr/1", + isDraft: false, + }, + ...overrides, + } as CommitMetadataGroup; +} + +test("treats master_base flag as master", () => { + const group = buildGroup({ master_base: true, base: "feature/base" }); + + const result = _is_master_base({ group, master_branch: "origin/master" }); + + expect(result).toBe(true); +}); + +test("treats group base matching master as master", () => { + const group = buildGroup({ base: "origin/master", master_base: false }); + + const result = _is_master_base({ group, master_branch: "origin/master" }); + + expect(result).toBe(true); +}); + +test("ignores pr base when group base differs", () => { + const group = buildGroup({ base: "feature/base", master_base: false }); + + const result = _is_master_base({ group, master_branch: "origin/master" }); + + expect(result).toBe(false); +}); diff --git a/src/app/SyncGithub.tsx b/src/app/SyncGithub.tsx index 9a0596b..3dec371 100644 --- a/src/app/SyncGithub.tsx +++ b/src/app/SyncGithub.tsx @@ -229,7 +229,7 @@ async function run() { // Unable to sync. // ``` // - if (!is_master_base(group)) { + if (!is_master_base({ group, master_branch })) { await github.pr_edit({ branch: group.id, base: master_branch, @@ -247,7 +247,7 @@ async function run() { invariant(group.base, "group.base must exist"); if (group.pr) { - if (!is_master_base(group)) { + if (!is_master_base({ group, master_branch })) { // ensure base matches pr in github await github.pr_edit({ branch: group.id, base: group.base }); } @@ -303,11 +303,7 @@ async function run() { } function is_master_base(group: CommitMetadataGroup) { - if (!group.pr) { - return false; - } - - return group.master_base || `origin/${group.pr.baseRefName}` === master_branch; + return _is_master_base({ group, master_branch }); } async function push_master_group(group: CommitMetadataGroup) { @@ -351,4 +347,23 @@ async function run() { } } -type CommitMetadataGroup = CommitMetadata.CommitRange["group_list"][number]; +export function _is_master_base(args: { + group: CommitMetadataGroup; + master_branch: string; +}) { + const { group } = args; + const master_branch = args.master_branch; + + if (!group.pr) { + return false; + } + + // Treat as master-based only if we expect this group to live on master. + // Do not rely on the current PR base (it might be wrong and we want to fix it). + const master_branch_name = master_branch.replace(/^origin\//, ""); + const group_base = group.base?.replace(/^origin\//, ""); + + return group.master_base || group_base === master_branch_name; +} + +export type CommitMetadataGroup = CommitMetadata.CommitRange["group_list"][number];