@@ -105,7 +105,7 @@ func RunJobs(jobs []orchestrator.Job, prService ci.PullRequestService, orgServic
105105
106106 if ! allowedToPerformCommand {
107107 msg := reportPolicyError (job .ProjectName , command , job .RequestedBy , reporter )
108- slog .Warn ("Skipping command ... %v for project %v" , command , job .ProjectName )
108+ slog .Warn ("Skipping command ..." , "command" , command , "projectName" , job .ProjectName )
109109 slog .Warn ("Received policy error" , "message" , msg )
110110 appliesPerProject [job .ProjectName ] = false
111111 continue
@@ -429,6 +429,71 @@ func run(command string, job orchestrator.Job, policyChecker policy.Checker, org
429429 return nil , msg , errors .New (msg )
430430 }
431431
432+ // Check apply policy before apply
433+ // Try to retrieve the terraform plan JSON if plan storage is configured
434+ var terraformPlanJson string
435+ if os .Getenv ("PLAN_UPLOAD_DESTINATION" ) != "" {
436+ slog .Debug ("Plan storage configured, attempting to retrieve plan for apply policy check" )
437+ retrievedPlanJson , err := executor .RetrievePlanJson ()
438+ if err != nil {
439+ slog .Warn ("Failed to retrieve plan JSON for apply policy check, proceeding without plan data" , "error" , err )
440+ } else {
441+ terraformPlanJson = retrievedPlanJson
442+ slog .Debug ("Successfully retrieved plan JSON for apply policy check" , "planLength" , len (terraformPlanJson ))
443+ }
444+ } else {
445+ slog .Debug ("Plan storage not configured, apply policy will not have terraform plan data" )
446+ }
447+
448+ slog .Debug ("Calling CheckApplyPolicy" ,
449+ "organisation" , SCMOrganisation ,
450+ "repository" , SCMrepository ,
451+ "projectName" , job .ProjectName ,
452+ "projectDir" , job .ProjectDir ,
453+ "command" , command ,
454+ "requestedBy" , requestedBy ,
455+ "hasTerraformPlan" , terraformPlanJson != "" )
456+ allowedToApplyByApplyPolicy , applyPolicyViolations , err := policyChecker .CheckApplyPolicy (SCMOrganisation , SCMrepository , job .ProjectName , job .ProjectDir , command , job .PullRequestNumber , requestedBy , teams , approvals , approvalTeams , planPolicyViolations , terraformPlanJson )
457+ slog .Debug ("CheckApplyPolicy result" ,
458+ "allowed" , allowedToApplyByApplyPolicy ,
459+ "violationsCount" , len (applyPolicyViolations ),
460+ "violations" , applyPolicyViolations ,
461+ "error" , err )
462+ if err != nil {
463+ msg := fmt .Sprintf ("Failed to run apply policy check before apply. %v" , err )
464+ slog .Error ("Failed to run apply policy check before apply" , "error" , err )
465+ return nil , msg , fmt .Errorf ("%s" , msg )
466+ }
467+ if ! allowedToApplyByApplyPolicy {
468+ slog .Info ("Apply policy check denied" ,
469+ "violationsCount" , len (applyPolicyViolations ),
470+ "violations" , applyPolicyViolations )
471+ var applyPolicyFormatter func (report string ) string
472+ summary := fmt .Sprintf ("Policy violation for <b>%v - %v</b>" , job .ProjectName , command )
473+ if reporter .SupportsMarkdown () {
474+ applyPolicyFormatter = reporting .AsCollapsibleComment (summary , false )
475+ } else {
476+ applyPolicyFormatter = reporting .AsComment (summary )
477+ }
478+
479+ applyPolicyReportMessage := "Terraform apply failed validation checks :x:<br>"
480+ if len (applyPolicyViolations ) > 0 {
481+ preformattedMessages := make ([]string , 0 )
482+ for _ , message := range applyPolicyViolations {
483+ preformattedMessages = append (preformattedMessages , fmt .Sprintf (" %v" , message ))
484+ }
485+ applyPolicyReportMessage = applyPolicyReportMessage + strings .Join (preformattedMessages , "<br>" )
486+ }
487+ _ , _ , err = reporter .Report (applyPolicyReportMessage , applyPolicyFormatter )
488+ if err != nil {
489+ slog .Error ("Failed to report apply policy violation." , "error" , err )
490+ }
491+
492+ msg := fmt .Sprintf ("Apply is not allowed due to policy violations" )
493+ slog .Error (msg )
494+ return nil , msg , errors .New (msg )
495+ }
496+
432497 // Running apply
433498
434499 applySummary , applyPerformed , output , err := diggerExecutor .Apply ()
0 commit comments