Skip to content

Commit c407377

Browse files
committed
Improve mapping of check_suite to PR
1 parent f4ca7c3 commit c407377

2 files changed

Lines changed: 77 additions & 12 deletions

File tree

pkg/webhook/handler.go

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"io"
1111
"log"
1212
"net/http"
13+
"strconv"
1314
"strings"
1415
"time"
1516

@@ -219,25 +220,53 @@ func ExtractPRURL(eventType string, payload map[string]any) string {
219220
case "check_run", "check_suite":
220221
// Extract PR URLs from check events if available
221222
if checkRun, ok := payload["check_run"].(map[string]any); ok {
222-
if prs, ok := checkRun["pull_requests"].([]any); ok && len(prs) > 0 {
223-
if pr, ok := prs[0].(map[string]any); ok {
224-
if htmlURL, ok := pr["html_url"].(string); ok {
225-
return htmlURL
226-
}
227-
}
223+
if url := extractPRFromCheckEvent(checkRun, payload); url != "" {
224+
return url
228225
}
229226
}
230227
if checkSuite, ok := payload["check_suite"].(map[string]any); ok {
231-
if prs, ok := checkSuite["pull_requests"].([]any); ok && len(prs) > 0 {
232-
if pr, ok := prs[0].(map[string]any); ok {
233-
if htmlURL, ok := pr["html_url"].(string); ok {
234-
return htmlURL
235-
}
236-
}
228+
if url := extractPRFromCheckEvent(checkSuite, payload); url != "" {
229+
return url
237230
}
238231
}
239232
default:
240233
// For other event types, no PR URL can be extracted
241234
}
242235
return ""
243236
}
237+
238+
// extractPRFromCheckEvent extracts PR URL from check_run or check_suite events.
239+
func extractPRFromCheckEvent(checkEvent map[string]any, payload map[string]any) string {
240+
prs, ok := checkEvent["pull_requests"].([]any)
241+
if !ok || len(prs) == 0 {
242+
return ""
243+
}
244+
245+
pr, ok := prs[0].(map[string]any)
246+
if !ok {
247+
return ""
248+
}
249+
250+
// Try html_url first
251+
if htmlURL, ok := pr["html_url"].(string); ok {
252+
return htmlURL
253+
}
254+
255+
// Fallback: construct from number
256+
num, ok := pr["number"].(float64)
257+
if !ok {
258+
return ""
259+
}
260+
261+
repo, ok := payload["repository"].(map[string]any)
262+
if !ok {
263+
return ""
264+
}
265+
266+
repoURL, ok := repo["html_url"].(string)
267+
if !ok {
268+
return ""
269+
}
270+
271+
return repoURL + "/pull/" + strconv.Itoa(int(num))
272+
}

pkg/webhook/handler_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,40 @@ func TestWebhookHandler(t *testing.T) {
7474
if w.Code != http.StatusUnauthorized {
7575
t.Errorf("expected status %d, got %d", http.StatusUnauthorized, w.Code)
7676
}
77+
78+
// Test check_suite event with PR number (no html_url)
79+
checkSuitePayload := map[string]any{
80+
"action": "completed",
81+
"check_suite": map[string]any{
82+
"pull_requests": []any{
83+
map[string]any{
84+
"number": float64(16),
85+
},
86+
},
87+
},
88+
"repository": map[string]any{
89+
"html_url": "https://github.com/codeGROOVE-dev/slacker",
90+
},
91+
}
92+
93+
body, err = json.Marshal(checkSuitePayload)
94+
if err != nil {
95+
t.Fatalf("failed to marshal check_suite payload: %v", err)
96+
}
97+
98+
req = httptest.NewRequest(http.MethodPost, "/webhook", bytes.NewReader(body))
99+
req.Header.Set("Content-Type", "application/json")
100+
req.Header.Set("X-GitHub-Event", "check_suite") //nolint:canonicalheader // GitHub webhook header
101+
102+
// Add valid signature
103+
mac = hmac.New(sha256.New, []byte(secret))
104+
mac.Write(body)
105+
signature = "sha256=" + hex.EncodeToString(mac.Sum(nil))
106+
req.Header.Set("X-Hub-Signature-256", signature)
107+
108+
w = httptest.NewRecorder()
109+
handler.ServeHTTP(w, req)
110+
if w.Code != http.StatusOK {
111+
t.Errorf("expected status %d for check_suite, got %d", http.StatusOK, w.Code)
112+
}
77113
}

0 commit comments

Comments
 (0)