diff --git a/src/Abstractions/Compendium.Abstractions.Git/Webhooks/IGitWebhookIngestor.cs b/src/Abstractions/Compendium.Abstractions.Git/Webhooks/IGitWebhookIngestor.cs
index 35ee182..7de1684 100644
--- a/src/Abstractions/Compendium.Abstractions.Git/Webhooks/IGitWebhookIngestor.cs
+++ b/src/Abstractions/Compendium.Abstractions.Git/Webhooks/IGitWebhookIngestor.cs
@@ -85,11 +85,16 @@ public sealed record TagPushed(string Tag, string CommitSha) : GitWebhookEvent;
/// The pull request number.
/// The source branch.
/// The target branch.
+ ///
+ /// The head commit SHA of the source branch, when the provider reports it —
+ /// CI/CD consumers need it to build or deploy the exact proposed revision.
+ ///
public sealed record PullRequestChanged(
string Action,
int Number,
string SourceReference,
- string TargetReference) : GitWebhookEvent;
+ string TargetReference,
+ string? SourceHeadSha = null) : GitWebhookEvent;
///
/// A pipeline run reached a terminal state.
diff --git a/src/Adapters/Compendium.Adapters.GitHub/Webhooks/GitHubWebhookIngestor.cs b/src/Adapters/Compendium.Adapters.GitHub/Webhooks/GitHubWebhookIngestor.cs
index 2f276d1..af95ba3 100644
--- a/src/Adapters/Compendium.Adapters.GitHub/Webhooks/GitHubWebhookIngestor.cs
+++ b/src/Adapters/Compendium.Adapters.GitHub/Webhooks/GitHubWebhookIngestor.cs
@@ -101,10 +101,12 @@ private static GitWebhookEvent TranslatePullRequest(JsonElement root, string del
var pr = GetProperty(root, "pull_request");
var action = GetString(root, "action") ?? string.Empty;
var number = GetInt(root, "number") ?? GetInt(pr, "number") ?? 0;
- var source = GetString(GetProperty(pr, "head"), "ref") ?? string.Empty;
+ var head = GetProperty(pr, "head");
+ var source = GetString(head, "ref") ?? string.Empty;
var targetRef = GetString(GetProperty(pr, "base"), "ref") ?? string.Empty;
+ var headSha = GetString(head, "sha");
- return new GitWebhookEvent.PullRequestChanged(action, number, source, targetRef)
+ return new GitWebhookEvent.PullRequestChanged(action, number, source, targetRef, headSha)
{
DeliveryId = deliveryId,
Repository = repository,
diff --git a/tests/Unit/Compendium.Adapters.GitHub.Tests/GitHubWebhookIngestorTests.cs b/tests/Unit/Compendium.Adapters.GitHub.Tests/GitHubWebhookIngestorTests.cs
index 7e4975c..a957f88 100644
--- a/tests/Unit/Compendium.Adapters.GitHub.Tests/GitHubWebhookIngestorTests.cs
+++ b/tests/Unit/Compendium.Adapters.GitHub.Tests/GitHubWebhookIngestorTests.cs
@@ -95,7 +95,7 @@ public void Parse_TagPush_ProducesATagPushedEvent()
public void Parse_PullRequest_ProducesAPullRequestChangedEvent()
{
var body = """
- {"action":"opened","number":42,"pull_request":{"head":{"ref":"feature"},"base":{"ref":"main"}},
+ {"action":"opened","number":42,"pull_request":{"head":{"ref":"feature","sha":"headsha42"},"base":{"ref":"main"}},
"repository":{"full_name":"acme/billing"}}
""";
@@ -106,6 +106,21 @@ public void Parse_PullRequest_ProducesAPullRequestChangedEvent()
pr.Number.Should().Be(42);
pr.SourceReference.Should().Be("feature");
pr.TargetReference.Should().Be("main");
+ pr.SourceHeadSha.Should().Be("headsha42");
+ }
+
+ [Fact]
+ public void Parse_PullRequestWithoutHeadSha_LeavesSourceHeadShaNull()
+ {
+ var body = """
+ {"action":"opened","number":7,"pull_request":{"head":{"ref":"feature"},"base":{"ref":"main"}},
+ "repository":{"full_name":"acme/billing"}}
+ """;
+
+ var result = _ingestor.Parse(Delivery("pull_request", body), Secret);
+
+ var pr = result.Value.Should().BeOfType().Subject;
+ pr.SourceHeadSha.Should().BeNull();
}
[Fact]