Explorar el Código

delete github repo webhook when environment is deleted

Mohammed Nafees hace 3 años
padre
commit
4ac17412a8

+ 20 - 10
api/server/handlers/environment/create.go

@@ -63,7 +63,7 @@ func (c *CreateEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
-	env, err := c.Repo().Environment().CreateEnvironment(&models.Environment{
+	env := &models.Environment{
 		ProjectID:         project.ID,
 		ClusterID:         cluster.ID,
 		GitInstallationID: uint(ga.InstallationID),
@@ -72,25 +72,20 @@ func (c *CreateEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		GitRepoName:       name,
 		Mode:              request.Mode,
 		WebhookID:         string(webhookUID),
-	})
-
-	if err != nil {
-		c.deleteEnvAndReportError(w, r, env, err)
-		return
 	}
 
 	// write Github actions files to the repo
 	client, err := getGithubClientFromEnvironment(c.Config(), env)
 
 	if err != nil {
-		c.deleteEnvAndReportError(w, r, env, err)
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
 		return
 	}
 
-	webhookURL := fmt.Sprintf("%s/api/github/incoming_webhook/%s", c.Config().ServerConf.ServerURL, string(webhookUID))
+	webhookURL := getGithubWebhookURLFromUID(c.Config().ServerConf.ServerURL, string(webhookUID))
 
 	// create incoming webhook
-	_, _, err = client.Repositories.CreateHook(
+	hook, _, err := client.Repositories.CreateHook(
 		r.Context(), owner, name, &github.Hook{
 			Config: map[string]interface{}{
 				"url":          webhookURL,
@@ -103,7 +98,18 @@ func (c *CreateEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 	)
 
 	if err != nil && !strings.Contains(err.Error(), "already exists on this repository") {
-		c.deleteEnvAndReportError(w, r, env, err)
+		c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
+			fmt.Errorf("error trying to create a new github repository webhook: %w", err), http.StatusConflict),
+		)
+		return
+	}
+
+	env.GithubWebhookID = hook.GetID()
+
+	env, err = c.Repo().Environment().CreateEnvironment(env)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
 		return
 	}
 
@@ -187,3 +193,7 @@ func getGithubClientFromEnvironment(config *config.Config, env *models.Environme
 
 	return github.NewClient(&http.Client{Transport: itr}), nil
 }
+
+func getGithubWebhookURLFromUID(serverURL, webhookUID string) string {
+	return fmt.Sprintf("%s/api/github/incoming_webhook/%s", serverURL, string(webhookUID))
+}

+ 24 - 0
api/server/handlers/environment/delete.go

@@ -1,10 +1,12 @@
 package environment
 
 import (
+	"context"
 	"errors"
 	"fmt"
 	"net/http"
 
+	"github.com/google/go-github/v41/github"
 	"github.com/porter-dev/porter/api/server/authz"
 	"github.com/porter-dev/porter/api/server/handlers"
 	"github.com/porter-dev/porter/api/server/shared"
@@ -79,6 +81,9 @@ func (c *DeleteEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		agent.DeleteNamespace(depl.Namespace)
 	}
 
+	ghWebhookID := env.GithubWebhookID
+	webhookUID := env.WebhookID
+
 	// delete the environment
 	env, err = c.Repo().Environment().DeleteEnvironment(env)
 
@@ -87,6 +92,25 @@ func (c *DeleteEnvironmentHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
+	// FIXME: ignore the return status codes for now, should be fixed when we start returning all non-fatal errors
+	if ghWebhookID != 0 {
+		client.Repositories.DeleteHook(context.Background(), owner, name, ghWebhookID)
+	} else {
+		webhookURL := getGithubWebhookURLFromUID(c.Config().ServerConf.ServerURL, string(webhookUID))
+
+		// FIXME: should be cycling through all webhooks if pagination is needed
+		hooks, _, err := client.Repositories.ListHooks(context.Background(), owner, name, &github.ListOptions{})
+
+		if err == nil {
+			for _, hook := range hooks {
+				if hook.GetURL() == webhookURL {
+					client.Repositories.DeleteHook(context.Background(), owner, name, hook.GetID())
+					break
+				}
+			}
+		}
+	}
+
 	err = actions.DeleteEnv(&actions.EnvOpts{
 		Client:            client,
 		ServerURL:         c.Config().ServerConf.ServerURL,

+ 3 - 1
api/server/handlers/webhook/github_incoming.go

@@ -2,6 +2,7 @@ package webhook
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"net/http"
 	"strconv"
@@ -18,6 +19,7 @@ import (
 	"github.com/porter-dev/porter/api/server/shared/requestutils"
 	"github.com/porter-dev/porter/api/types"
 	"github.com/porter-dev/porter/internal/models"
+	"gorm.io/gorm"
 )
 
 type GithubIncomingWebhookHandler struct {
@@ -74,7 +76,7 @@ func (c *GithubIncomingWebhookHandler) processPullRequestEvent(event *github.Pul
 
 	env, err := c.Repo().Environment().ReadEnvironmentByWebhookIDOwnerRepoName(webhookID, owner, repo)
 
-	if err != nil {
+	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
 		return fmt.Errorf("[webhookID: %s, owner: %s, repo: %s] error reading environment: %w", webhookID, owner, repo, err)
 	}
 

+ 2 - 0
internal/models/environment.go

@@ -22,6 +22,8 @@ type Environment struct {
 	// WebhookID uniquely identifies the environment when other fields (project, cluster)
 	// aren't present
 	WebhookID string `gorm:"unique"`
+
+	GithubWebhookID int64
 }
 
 func (e *Environment) ToEnvironmentType() *types.Environment {