@@ -17,14 +17,14 @@ use gitea_client::types::Event;
1717use std:: sync:: Arc ;
1818use uuid:: Uuid ;
1919
20- use tracing:: { error, info} ;
20+ use tracing:: { debug , error, info} ;
2121
2222use crate :: {
2323 context:: Context ,
2424 errors:: { ApiError , Result } ,
2525 repository:: CourseRepository ,
2626 request:: event:: PipelineEvent ,
27- service:: { RepoService , StageService } ,
27+ service:: { PipelineService , RepoService , StageService } ,
2828 utils:: crypto,
2929} ;
3030
@@ -52,51 +52,54 @@ pub async fn handle_tekton_webhook(
5252 State ( ctx) : State < Arc < Context > > ,
5353 Json ( event) : Json < PipelineEvent > ,
5454) -> Result < impl IntoResponse > {
55- info ! ( "Received pipeline event: {:?}" , event) ;
55+ debug ! ( "Received pipeline event: {:?}" , event) ;
56+ let PipelineEvent { name, status, repo, course, stage, secret, tasks } = & event;
5657
5758 // Verify HMAC signature to prevent request forgery
5859 let auth_secret = & ctx. config . auth_secret ;
59- let payload = format ! ( "{}{}{}" , event. repo, event. course, event. stage) ;
60- let is_valid = crypto:: hmac_sha256_verify ( & payload, auth_secret, & event. secret )
61- . map_err ( |e| ApiError :: InternalError ( format ! ( "Signature verification failed: {}" , e) ) ) ?;
62-
63- if !is_valid {
60+ let payload = format ! ( "{}{}{}" , repo, course, stage) ;
61+ if crypto:: hmac_sha256_verify ( & payload, auth_secret, secret) ? {
62+ error ! ( "Received pipeline event with invalid signature" ) ;
6463 return Err ( ApiError :: Unauthorized ( "Invalid signature" . into ( ) ) ) ;
6564 }
6665
6766 // Check overall pipeline status first
68- if event . status != "Succeeded" {
69- error ! ( "Pipeline run failed, please check it. Aggregate status: {}" , event . status ) ;
67+ if status != "Succeeded" {
68+ error ! ( "Pipeline run failed, please check it." ) ;
7069 return Ok ( StatusCode :: OK ) ;
7170 }
7271
7372 // Process the pipeline event based on test task status:
7473 // - If succeeded: mark the stage as complete for the user
7574 // - If failed: log error (TODO: collect error details from Tekton and save to database)
7675 // - Other states: log and ignore non-terminal states
77- match event . tasks . test . status . as_str ( ) {
76+ match tasks. test . status . as_str ( ) {
7877 "Succeeded" => {
7978 // Look up the course to get the user_id
80- let id = Uuid :: parse_str ( & event . repo ) ?;
81- let course = CourseRepository :: get_user_course_by_id ( & ctx. database , & id) . await ?;
79+ let id = Uuid :: parse_str ( repo) ?;
80+ let user_course = CourseRepository :: get_user_course_by_id ( & ctx. database , & id) . await ?;
8281
8382 // Mark the stage as complete
84- StageService :: complete ( ctx, & course. user_id , & event. course , & event. stage ) . await ?;
85-
86- info ! ( "Stage {} completed successfully for course {}" , event. stage, event. course) ;
83+ StageService :: complete ( ctx. clone ( ) , & user_course. user_id , course, stage) . await ?;
84+ info ! ( "Stage {} completed successfully for course {}" , stage, course) ;
8785 }
8886 "Failed" => {
89- info ! ( "Test task failed: reason={}, stage={}" , event . tasks. test. reason, event . stage) ;
87+ info ! ( "Test task failed: reason={}, stage={}" , tasks. test. reason, stage) ;
9088 return Ok ( StatusCode :: OK ) ;
9189 }
9290 _ => {
9391 error ! (
9492 "Test task in non-terminal state: status={}, reason={}" ,
95- event . tasks. test. status, event . tasks. test. reason
93+ tasks. test. status, tasks. test. reason
9694 ) ;
9795 return Ok ( StatusCode :: OK ) ;
9896 }
9997 }
10098
99+ // Delete the PipelineRun after successful processing
100+ if let Err ( e) = PipelineService :: new ( ctx. clone ( ) ) . delete ( name) . await {
101+ error ! ( "Failed to delete PipelineRun {}: {}" , name, e) ;
102+ }
103+
101104 Ok ( StatusCode :: OK )
102105}
0 commit comments