authorgravatar for snorteman@gmail.comScott Norteman <snorteman@gmail.com> 2026-10-12 19:20:50-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-12 18:20:50-05:00
loga3c4e9e9360d65225fb726ebfe460427a6874741
tree68f9b5d7e719b3d42715faa5155a4abe5bcee3dd
parent511d20c6f20c2ed6ff787aba068d7d673e2949b9
signature Signed by PGP key B5690EEEBB952194

fix(gitlab): merge request details report their head commit (#18608)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

2 files changed, 20 insertions(+), 0 deletions(-)

packages/source-control-gitlab/src/server/gitLabMergeRequestJson.test.ts+14
...@@ -181,6 +181,20 @@ describe("decodeMergeRequestDetailJson", () => {...@@ -181,6 +181,20 @@ describe("decodeMergeRequestDetailJson", () => {
181 expect(detail.changedFiles).toBe(0);181 expect(detail.changedFiles).toBe(0);
182 });182 });
183183
184 it("reads the head commit, and says nothing where GitLab omitted it", () => {
185 const headSha = (entry: Record<string, unknown>) =>
186 expectSuccess(decodeMergeRequestDetailJson(detailJson(entry))).headSha;
187 const sha = "afce4da4d5fe7d2fd0647b5b864526ea0a2827cb";
188
189 expect(headSha({ sha })).toBe(sha);
190 // A new merge request can report its head before GitLab has computed `diff_refs`.
191 expect(headSha({ sha, diff_refs: null })).toBe(sha);
192 expect(headSha({ sha, merge_commit_sha: "0".repeat(40) })).toBe(sha);
193 expect(headSha({})).toBeUndefined();
194 expect(headSha({ sha: null })).toBeUndefined();
195 expect(headSha({ sha: " " })).toBeUndefined();
196 });
197
184 it("reads either auto-merge field, and says nothing where GitLab named neither", () => {198 it("reads either auto-merge field, and says nothing where GitLab named neither", () => {
185 const armed = (entry: Record<string, unknown>) =>199 const armed = (entry: Record<string, unknown>) =>
186 expectSuccess(decodeMergeRequestDetailJson(detailJson(entry))).autoMergeEnabled;200 expectSuccess(decodeMergeRequestDetailJson(detailJson(entry))).autoMergeEnabled;
packages/source-control-gitlab/src/server/gitLabMergeRequestJson.ts+6
...@@ -51,6 +51,8 @@ const RawMergeRequestSchema = Schema.Struct({...@@ -51,6 +51,8 @@ const RawMergeRequestSchema = Schema.Struct({
51 author: Schema.optional(Schema.NullOr(RawUserSchema)),51 author: Schema.optional(Schema.NullOr(RawUserSchema)),
52 source_branch: Schema.String,52 source_branch: Schema.String,
53 target_branch: Schema.String,53 target_branch: Schema.String,
54 /** The source branch's head commit. */
55 sha: Schema.optional(Schema.NullOr(Schema.String)),
54 state: Schema.optional(Schema.NullOr(Schema.String)),56 state: Schema.optional(Schema.NullOr(Schema.String)),
55 draft: Schema.optional(Schema.Boolean),57 draft: Schema.optional(Schema.Boolean),
56 work_in_progress: Schema.optional(Schema.Boolean),58 work_in_progress: Schema.optional(Schema.Boolean),
...@@ -240,6 +242,8 @@ export interface GitLabMergeRequestDetail extends GitLabMergeRequestListItem {...@@ -240,6 +242,8 @@ export interface GitLabMergeRequestDetail extends GitLabMergeRequestListItem {
240 * it: an install too old to answer must not be read as saying the branch is current.242 * it: an install too old to answer must not be read as saying the branch is current.
241 */243 */
242 readonly divergedCommits?: number;244 readonly divergedCommits?: number;
245 /** Absent where GitLab did not report the head commit. */
246 readonly headSha?: string;
243}247}
244248
245function trimmed(value: string | null | undefined): string | null {249function trimmed(value: string | null | undefined): string | null {
...@@ -365,6 +369,7 @@ function toListItem(...@@ -365,6 +369,7 @@ function toListItem(
365369
366function toDetail(raw: Schema.Schema.Type<typeof RawMergeRequestSchema>): GitLabMergeRequestDetail {370function toDetail(raw: Schema.Schema.Type<typeof RawMergeRequestSchema>): GitLabMergeRequestDetail {
367 const listItem = toListItem(raw);371 const listItem = toListItem(raw);
372 const headSha = trimmed(raw.sha);
368 const autoMerge =373 const autoMerge =
369 raw.merge_when_pipeline_succeeds == null && raw.auto_merge_enabled == null374 raw.merge_when_pipeline_succeeds == null && raw.auto_merge_enabled == null
370 ? undefined375 ? undefined
...@@ -390,6 +395,7 @@ function toDetail(raw: Schema.Schema.Type<typeof RawMergeRequestSchema>): GitLab...@@ -390,6 +395,7 @@ function toDetail(raw: Schema.Schema.Type<typeof RawMergeRequestSchema>): GitLab
390 ? { autoMergeMethod: "squash" as const }395 ? { autoMergeMethod: "squash" as const }
391 : {}),396 : {}),
392 ...(raw.diverged_commits_count == null ? {} : { divergedCommits: raw.diverged_commits_count }),397 ...(raw.diverged_commits_count == null ? {} : { divergedCommits: raw.diverged_commits_count }),
398 ...(headSha === null ? {} : { headSha }),
393 };399 };
394}400}
395401