Skip to content

Commit c3eb81c

Browse files
CopilotMalcolmnixon
andcommitted
Support squash merges by parsing all commits for PR references
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
1 parent 48556ba commit c3eb81c

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/DemaConsulting.BuildMark/RepoConnectors/GitHubRepoConnector.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,20 +160,23 @@ public override async Task<List<string>> GetPullRequestsBetweenTagsAsync(Version
160160
range = $"{fromTag}..{toRef}";
161161
}
162162

163-
// Get merge commits in range using git log
164-
// Arguments: --oneline (one line per commit), --merges (only merge commits)
165-
// Output format: "<short-hash> Merge pull request #<number> from <branch>"
166-
var output = await RunCommandAsync("git", $"log --oneline --merges {range}");
163+
// Get commits in range using git log
164+
// Arguments: --oneline (one line per commit)
165+
// Output format: "<short-hash> <commit message>"
166+
// Parses both merge commits ("Merge pull request #<number>") and squash commits ("... (#<number>)")
167+
var output = await RunCommandAsync("git", $"log --oneline {range}");
167168

168-
// Extract pull request numbers from merge commit messages
169+
// Extract pull request numbers from commit messages
169170
// Each line is parsed for "#<number>" pattern to identify the PR
171+
// This works for both traditional merge commits and squash/rebase commits
170172
var regex = NumberReferenceRegex();
171173

172174
var pullRequests = output
173175
.Split('\n', StringSplitOptions.RemoveEmptyEntries)
174176
.Select(line => regex.Match(line))
175177
.Where(match => match.Success)
176178
.Select(match => match.Groups[1].Value)
179+
.Distinct() // Remove duplicates in case a PR number appears in multiple commits
177180
.ToList();
178181

179182
return pullRequests;

test/DemaConsulting.BuildMark.Tests/GitHubRepoConnectorTests.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_ReturnsExp
135135

136136
connector.AddCommandResult(
137137
"git",
138-
"log --oneline --merges v1.0.0..v2.0.0",
138+
"log --oneline v1.0.0..v2.0.0",
139139
"abc123 Merge pull request #10 from feature/x\ndef456 Merge pull request #11 from bugfix/y");
140140

141141
// Act
@@ -163,7 +163,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesNul
163163

164164
connector.AddCommandResult(
165165
"git",
166-
"log --oneline --merges v1.0.0",
166+
"log --oneline v1.0.0",
167167
"abc123 Merge pull request #10 from feature/x");
168168

169169
// Act
@@ -184,7 +184,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesNul
184184
var connector = new TestableGitHubRepoConnector();
185185
connector.AddCommandResult(
186186
"git",
187-
"log --oneline --merges v1.0.0..HEAD",
187+
"log --oneline v1.0.0..HEAD",
188188
"abc123 Merge pull request #11 from feature/y");
189189

190190
// Act
@@ -205,7 +205,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesBot
205205
var connector = new TestableGitHubRepoConnector();
206206
connector.AddCommandResult(
207207
"git",
208-
"log --oneline --merges HEAD",
208+
"log --oneline HEAD",
209209
"abc123 Merge pull request #12 from feature/z");
210210

211211
// Act
@@ -231,7 +231,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_UsesHeadWh
231231
// Mock git log with HEAD instead of non-existent tag
232232
connector.AddCommandResult(
233233
"git",
234-
"log --oneline --merges v1.0.0..HEAD",
234+
"log --oneline v1.0.0..HEAD",
235235
"abc123 Merge pull request #15 from feature/new");
236236

237237
// Act - using a version that doesn't exist as a tag
@@ -244,6 +244,31 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_UsesHeadWh
244244
Assert.AreEqual("15", prs[0]);
245245
}
246246

247+
/// <summary>
248+
/// Test that GetPullRequestsBetweenTagsAsync handles squash merge commits.
249+
/// </summary>
250+
[TestMethod]
251+
public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesSquashMerges()
252+
{
253+
// Arrange
254+
var connector = new TestableGitHubRepoConnector();
255+
256+
// Mock git log with squash merge commits (PR number in parentheses)
257+
connector.AddCommandResult(
258+
"git",
259+
"log --oneline HEAD",
260+
"abc123 Fix bug with validation (#18)\ndef456 Add new feature (#19)\nghi789 Update documentation (#20)");
261+
262+
// Act
263+
var prs = await connector.GetPullRequestsBetweenTagsAsync(null, null);
264+
265+
// Assert
266+
Assert.HasCount(3, prs);
267+
Assert.AreEqual("18", prs[0]);
268+
Assert.AreEqual("19", prs[1]);
269+
Assert.AreEqual("20", prs[2]);
270+
}
271+
247272
/// <summary>
248273
/// Test that GetIssuesForPullRequestAsync returns expected issues.
249274
/// </summary>

0 commit comments

Comments
 (0)