From 94c2ec914f183a9138a98bb0a714593b5294d716 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:11:10 +0000 Subject: [PATCH 1/3] fix: guard against IndexOutOfRangeException when Branches list is empty in GithubStatusNotificationHandler Guard BuildStatusMessage and AddBranchEmbed in GithubStatusNotificationHandler against an empty Branches list. Previously, message.Branches[^1] threw IndexOutOfRangeException when no branches were present in the payload. Now uses a null-conditional accessor with string.Empty fallback for the embed title and "(unknown)" for the branch field value (Discord rejects empty field values). Adds parameterised test cases covering the empty-branches path for success, failure, and error states. Prompt: Fix the IndexOutOfRangeException in GithubStatusNotificationHandler when Branches is empty (issue #365) --- .../GithubStatusNotificationHandlerTests.cs | 28 ++++++++++++++++++- .../GithubStatusNotificationHandler.cs | 6 ++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/BuildBot.GitHub.Tests/Publishers/GithubStatusNotificationHandlerTests.cs b/src/BuildBot.GitHub.Tests/Publishers/GithubStatusNotificationHandlerTests.cs index 4e6d3ea4a..c77067951 100644 --- a/src/BuildBot.GitHub.Tests/Publishers/GithubStatusNotificationHandlerTests.cs +++ b/src/BuildBot.GitHub.Tests/Publishers/GithubStatusNotificationHandlerTests.cs @@ -19,6 +19,16 @@ public sealed class GithubStatusNotificationHandlerTests : TestBase .UtcDateTime; private static Status MakeStatus(string state) + { + return MakeStatusWithBranches(state: state, branches: [new Branch(name: "main")]); + } + + private static Status MakeStatusWithNoBranches(string state) + { + return MakeStatusWithBranches(state: state, branches: []); + } + + private static Status MakeStatusWithBranches(string state, Branch[] branches) { Repository repository = new( id: 1, @@ -49,7 +59,7 @@ private static Status MakeStatus(string state) repository: repository, context: "ci/build", state: state, - branches: [new Branch(name: "main")], + branches: branches, description: "Build finished", statusCommit: statusCommit ); @@ -92,4 +102,20 @@ public async Task NonPendingStateShouldPublishAsync(string state) await mediator.Received(1).Publish(Arg.Any(), Arg.Any()); } + + [Theory] + [InlineData("success")] + [InlineData("failure")] + [InlineData("error")] + public async Task NonPendingStateWithNoBranchesShouldPublishAsync(string state) + { + (IMediator mediator, GithubStatusNotificationHandler handler) = this.CreateHandler(); + + Status status = MakeStatusWithNoBranches(state: state); + GithubStatus notification = new(status); + + await handler.Handle(notification: notification, cancellationToken: this.CancellationToken()); + + await mediator.Received(1).Publish(Arg.Any(), Arg.Any()); + } } diff --git a/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs b/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs index b93b962cf..cfecb8df0 100644 --- a/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs +++ b/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs @@ -53,11 +53,11 @@ private static bool IsPendingBuild(in Status message) private static EmbedBuilder BuildStatusMessage(in Status message) { - Branch lastBranch = message.Branches[^1]; + Branch? lastBranch = message.Branches.Count > 0 ? message.Branches[^1] : null; return new EmbedBuilder() .WithTitle( - $"{message.Description} for {message.Context} from {message.Repository.Name} ({lastBranch.Name})" + $"{message.Description} for {message.Context} from {message.Repository.Name} ({lastBranch?.Name ?? string.Empty})" ) .WithUrl(message.TargetUrl) .WithDescription($"Built at {message.StatusCommit.Sha}") @@ -74,7 +74,7 @@ private static EmbedFieldBuilder AddBranchEmbed(in Status message) { return new EmbedFieldBuilder() .WithName("Branch") - .WithValue(message.Branches.Select(static b => b.Name).FirstOrDefault()); + .WithValue(message.Branches.Select(static b => b.Name).FirstOrDefault() ?? "(unknown)"); } private static EmbedFieldBuilder AddHeadCommitEmbed(in StatusCommit statusCommit) From 7bb1117c54fa2beb7c951befb0c2201f63482cbc Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:15:02 +0000 Subject: [PATCH 2/3] changelog: guard against IndexOutOfRangeException when Branches list is empty in GithubStatusNotificationHandler --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85482a806..204ca3a7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ Please ADD ALL Changes to the UNRELEASED SECTION and not a specific release - Added null guards for botMessageChannel and botReleaseMessageChannel parameters in BotService constructor - Pass ILogger to HealthCheckClient.ExecuteAsync to match new API in Credfeto.Docker.HealthCheck.Http.Client 0.0.72.928 - Made DiscordChannelAdapter testable by accepting ITextChannel instead of the sealed SocketTextChannel, and added unit tests +- Guard against IndexOutOfRangeException when Branches list is empty in GithubStatusNotificationHandler ### Changed - Dependencies - Updated NSubstitute.Analyzers.CSharp to 1.0.17 - Switched to use minimal APIs From 0725ace62292e71eef7a5e2512497754c5118d50 Mon Sep 17 00:00:00 2001 From: Mark Ridgwell <273118822+dnyw4l3n13@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:47:45 +0000 Subject: [PATCH 3/3] fix: use consistent '(unknown)' fallback for branch name in status message title Replaces string.Empty with "(unknown)" in the title embed to match the fallback text already used in the Branch embed field, avoiding a confusing empty-parentheses display when Branches list is empty. --- .../Publishers/GithubStatusNotificationHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs b/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs index cfecb8df0..ccf038b8f 100644 --- a/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs +++ b/src/BuildBot.GitHub/Publishers/GithubStatusNotificationHandler.cs @@ -57,7 +57,7 @@ private static EmbedBuilder BuildStatusMessage(in Status message) return new EmbedBuilder() .WithTitle( - $"{message.Description} for {message.Context} from {message.Repository.Name} ({lastBranch?.Name ?? string.Empty})" + $"{message.Description} for {message.Context} from {message.Repository.Name} ({lastBranch?.Name ?? "(unknown)"})" ) .WithUrl(message.TargetUrl) .WithDescription($"Built at {message.StatusCommit.Sha}")