From f1175458d415eb5b6141703e8c137ea7a9933ddf Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 11 Apr 2026 02:11:32 +0000
Subject: [PATCH] Fix ADO PR mapping: use lastMergeCommit nested object instead
of flat mergeCommitId
The Azure DevOps GitPullRequest API returns lastMergeCommit as a nested
GitCommitRef object (with commitId), not as a flat mergeCommitId string.
The previous code deserialized a non-existent mergeCommitId field, which
always returned null from real API calls, breaking commit-to-PR mapping
for all merge strategies (including squash merges).
- Add AzureDevOpsGitCommitRef record to model the nested commit reference
- Change AzureDevOpsPullRequest to deserialize LastMergeCommit (nested object)
- Add convenience MergeCommitId property to minimize downstream changes
- Update mock handler to emit lastMergeCommit: { commitId: ... } format
Agent-Logs-Url: https://github.com/demaconsulting/BuildMark/sessions/18090e6e-03fe-4772-8b1e-8e8c33c87fdb
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
---
.../AzureDevOps/AzureDevOpsApiTypes.cs | 22 ++++++++++++++++---
.../MockAzureDevOpsHttpMessageHandler.cs | 2 +-
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsApiTypes.cs b/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsApiTypes.cs
index 5d1ae90..9e94cee 100644
--- a/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsApiTypes.cs
+++ b/src/DemaConsulting.BuildMark/RepoConnectors/AzureDevOps/AzureDevOpsApiTypes.cs
@@ -40,6 +40,13 @@ internal sealed record AzureDevOpsCommit(
string CommitId,
string Comment);
+///
+/// Minimal Git commit reference containing only the commit SHA.
+///
+/// Full commit SHA hash.
+internal sealed record AzureDevOpsGitCommitRef(
+ string CommitId);
+
///
/// Pull request data returned by the Azure DevOps pull requests endpoint.
///
@@ -47,7 +54,10 @@ internal sealed record AzureDevOpsCommit(
/// Pull request title.
/// Pull request web URL.
/// Pull request status (active, completed, abandoned).
-/// Merge commit SHA when completed, null otherwise.
+///
+/// The commit of the most recent pull request merge. Null when the merge is in progress or was unsuccessful.
+/// This field is populated for all merge strategies (no-fast-forward, squash, rebase, rebase-merge).
+///
/// Source branch reference name.
/// Pull request description body.
internal sealed record AzureDevOpsPullRequest(
@@ -55,9 +65,15 @@ internal sealed record AzureDevOpsPullRequest(
string Title,
string? Url,
string Status,
- string? MergeCommitId,
+ AzureDevOpsGitCommitRef? LastMergeCommit,
string? SourceRefName,
- string? Description);
+ string? Description)
+{
+ ///
+ /// Gets the merge commit SHA from the last merge commit reference, or null if not available.
+ ///
+ public string? MergeCommitId => LastMergeCommit?.CommitId;
+}
///
/// Work item data returned by the Azure DevOps work items endpoint with all fields expanded.
diff --git a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/MockAzureDevOpsHttpMessageHandler.cs b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/MockAzureDevOpsHttpMessageHandler.cs
index 6473111..ae0b11a 100644
--- a/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/MockAzureDevOpsHttpMessageHandler.cs
+++ b/test/DemaConsulting.BuildMark.Tests/RepoConnectors/AzureDevOps/MockAzureDevOpsHttpMessageHandler.cs
@@ -172,7 +172,7 @@ public MockAzureDevOpsHttpMessageHandler AddPullRequestsResponse(params MockAdoP
title = pr.Title,
url = $"https://dev.azure.com/org/project/_git/repo/pullrequest/{pr.PullRequestId}",
status = pr.Status,
- mergeCommitId = pr.MergeCommitId,
+ lastMergeCommit = pr.MergeCommitId != null ? new { commitId = pr.MergeCommitId } : null,
sourceRefName = "refs/heads/feature",
description = pr.Description
});