@@ -17,6 +17,7 @@ package controllers
1717import (
1818 "encoding/json"
1919 "fmt"
20+ "time"
2021
2122 "github.com/casbin/casbin-oa/object"
2223 "github.com/casbin/casbin-oa/util"
@@ -26,9 +27,26 @@ import (
2627func (c * ApiController ) WebhookOpen () {
2728 var issueEvent github.IssuesEvent
2829 var pullRequestEvent github.PullRequestEvent
30+ var checkRunEvent github.CheckRunEvent
31+
32+ // Try to parse as different event types.
33+ eventType := c .Ctx .Request .Header .Get ("X-GitHub-Event" )
34+
35+ result := false
36+ switch eventType {
37+ case "check_run" :
38+ err := json .Unmarshal (c .Ctx .Input .RequestBody , & checkRunEvent )
39+ if err == nil && checkRunEvent .CheckRun != nil {
40+ result = HandleCheckRunEvent (checkRunEvent )
41+ c .Data ["json" ] = result
42+ c .ServeJSON ()
43+ return
44+ }
45+ }
46+
47+ // Legacy handling for issues and pull requests.
2948 json .Unmarshal (c .Ctx .Input .RequestBody , & pullRequestEvent )
3049
31- var result bool
3250 if pullRequestEvent .PullRequest != nil {
3351 result = PullRequestOpen (pullRequestEvent )
3452 } else {
@@ -106,6 +124,89 @@ func PullRequestOpen(pullRequestEvent github.PullRequestEvent) bool {
106124 go util .Comment (commentStr , owner , repo , pullRequestEvent .GetNumber ())
107125 }
108126 }
127+ // Request automatic code review from copilot for human-created PRs.
128+ go util .RequestCopilotReview (owner , repo , pullRequestEvent .GetNumber ())
129+ }
130+ return true
131+ }
132+
133+ // HandleCheckRunEvent handles check_run webhook events.
134+ func HandleCheckRunEvent (event github.CheckRunEvent ) bool {
135+ if event .GetAction () != "completed" {
136+ return false
137+ }
138+
139+ checkRun := event .GetCheckRun ()
140+ if checkRun == nil {
141+ return false
142+ }
143+
144+ // Only process failed checks.
145+ if checkRun .GetConclusion () != "failure" && checkRun .GetConclusion () != "cancelled" {
146+ return false
147+ }
148+
149+ // Get PR information.
150+ prs := checkRun .PullRequests
151+ if len (prs ) == 0 {
152+ return false
153+ }
154+
155+ owner , repo := util .GetOwnerAndNameFromId (event .Repo .GetFullName ())
156+ //issueWebhook := object.GetIssueIfExist(owner, repo)
157+ //if issueWebhook == nil {
158+ // return false
159+ //}
160+
161+ for _ , pr := range prs {
162+ prNumber := pr .GetNumber ()
163+ checkName := checkRun .GetName ()
164+
165+ // Check if this is a linter check.
166+ if ! util .IsLinterCheck (checkName ) {
167+ continue
168+ }
169+
170+ // Check if we should attempt to fix (max 3 attempts).
171+ if ! object .ShouldAttemptFix (owner , repo , prNumber , checkName ) {
172+ continue
173+ }
174+
175+ // Get or create PR check record.
176+ prCheck := object .GetPrCheck (owner , repo , prNumber , checkName )
177+ if prCheck == nil {
178+ // Create new record.
179+ prCheck = & object.PrCheck {
180+ Org : owner ,
181+ Repo : repo ,
182+ PrNumber : prNumber ,
183+ CheckRunId : checkRun .GetID (),
184+ CheckName : checkName ,
185+ Status : checkRun .GetStatus (),
186+ Conclusion : checkRun .GetConclusion (),
187+ FailureReason : util .GetCheckFailureDetails (checkRun ),
188+ FixAttempts : 0 ,
189+ LastAttemptAt : time .Now (),
190+ IsFixed : false ,
191+ CreatedAt : time .Now (),
192+ }
193+ object .AddPrCheck (prCheck )
194+ } else {
195+ // Update existing record.
196+ prCheck .CheckRunId = checkRun .GetID ()
197+ prCheck .Status = checkRun .GetStatus ()
198+ prCheck .Conclusion = checkRun .GetConclusion ()
199+ prCheck .FailureReason = util .GetCheckFailureDetails (checkRun )
200+ object .UpdatePrCheck (prCheck .Id , prCheck )
201+ }
202+
203+ // Increment fix attempts and get updated record.
204+ prCheck = object .IncrementFixAttempts (owner , repo , prNumber , checkName )
205+ if prCheck != nil {
206+ // Comment on PR with failure details and tag copilot.
207+ go util .CommentOnPRWithCopilotTag (owner , repo , prNumber , prCheck .FailureReason , prCheck .FixAttempts )
208+ }
109209 }
210+
110211 return true
111212}
0 commit comments