Kaynağa Gözat

Merge pull request #2176 from porter-dev/nafees/preview-env-improvements

[POR-553] [POR-567] Cancel active workflow runs for a preview env deployment when required
abelanger5 3 yıl önce
ebeveyn
işleme
1203b282fb
1 değiştirilmiş dosya ile 67 ekleme ve 2 silme
  1. 67 2
      api/server/handlers/webhook/github_incoming.go

+ 67 - 2
api/server/handlers/webhook/github_incoming.go

@@ -6,6 +6,8 @@ import (
 	"net/http"
 	"strconv"
 	"strings"
+	"sync"
+	"time"
 
 	"github.com/bradleyfalzon/ghinstallation/v2"
 	"github.com/google/go-github/v41/github"
@@ -185,12 +187,75 @@ func (c *GithubIncomingWebhookHandler) processPullRequestEvent(event *github.Pul
 					event.GetPullRequest().GetNumber(), err)
 			}
 		} else {
+			// check for already running workflows we should be cancelling
+			var wg sync.WaitGroup
+			statuses := []string{"in_progress", "queued", "requested", "waiting"}
+
+			wg.Add(len(statuses))
+
+			errChan := make(chan error)
+
+			for _, status := range statuses {
+				go func(status string) {
+					defer wg.Done()
+
+					reqCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+					defer cancel()
+
+					runs, _, err := client.Actions.ListWorkflowRunsByFileName(
+						reqCtx, owner, repo, fmt.Sprintf("porter_%s_env.yml", env.Name),
+						&github.ListWorkflowRunsOptions{
+							Branch: event.GetPullRequest().GetHead().GetRef(),
+							Status: status,
+						},
+					)
+
+					if err == nil && runs.GetTotalCount() > 0 {
+						wg.Add(runs.GetTotalCount())
+
+						for _, run := range runs.WorkflowRuns {
+							go func(id int64, url string) {
+								defer wg.Done()
+
+								reqCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
+								defer cancel()
+
+								_, err := client.Actions.CancelWorkflowRunByID(reqCtx, owner, repo, id)
+
+								if err != nil {
+									errChan <- fmt.Errorf("error cancelling %s: %w", url, err)
+								}
+							}(run.GetID(), run.GetHTMLURL())
+						}
+					} else if err != nil {
+						errChan <- fmt.Errorf("error listing workflows for status %s: %w", status, err)
+					}
+				}(status)
+			}
+
+			wg.Wait()
+
+			chanErr := fmt.Errorf("")
+
+			for err := range errChan {
+				chanErr = fmt.Errorf("%s: %w", chanErr.Error(), err)
+			}
+
 			err = c.deleteDeployment(r, depl, env, client)
 
 			if err != nil {
+				deleteErr := fmt.Errorf("[webhookID: %s, owner: %s, repo: %s, environmentID: %d, deploymentID: %d, prNumber: %d] "+
+					"error deleting deployment: %w", webhookID, owner, repo, env.ID, depl.ID, event.GetPullRequest().GetNumber(), err)
+
+				if chanErr.Error() != "" {
+					deleteErr = fmt.Errorf("%s. errors found while trying to cancel active workflow runs %w", deleteErr.Error(), chanErr)
+				}
+
+				return deleteErr
+			} else if chanErr.Error() != "" {
 				return fmt.Errorf("[webhookID: %s, owner: %s, repo: %s, environmentID: %d, deploymentID: %d, prNumber: %d] "+
-					"error deleting deployment: %w", webhookID, owner, repo, env.ID, depl.ID,
-					event.GetPullRequest().GetNumber(), err)
+					"deployment deleted but errors found while trying to cancel active workflow runs %w", webhookID, owner, repo, env.ID, depl.ID,
+					event.GetPullRequest().GetNumber(), chanErr)
 			}
 		}
 	}