Skip to content

Commit fcc685b

Browse files
committed
introduce AAM webhook
1 parent 7d05530 commit fcc685b

File tree

8 files changed

+310
-50
lines changed

8 files changed

+310
-50
lines changed

backend/controllers/github.go

+32-14
Original file line numberDiff line numberDiff line change
@@ -425,9 +425,9 @@ func handlePullRequestEvent(gh utils.GithubClientProvider, payload *github.PullR
425425
cloneURL := *payload.Repo.CloneURL
426426
prNumber := *payload.PullRequest.Number
427427

428-
diggerYmlStr, ghService, config, projectsGraph, branch, err := getDiggerConfig(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, prNumber)
428+
diggerYmlStr, ghService, config, projectsGraph, branch, err := getDiggerConfigForPR(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, prNumber)
429429
if err != nil {
430-
log.Printf("getDiggerConfig error: %v", err)
430+
log.Printf("getDiggerConfigForPR error: %v", err)
431431
return fmt.Errorf("error getting digger config")
432432
}
433433

@@ -502,23 +502,17 @@ func handlePullRequestEvent(gh utils.GithubClientProvider, payload *github.PullR
502502
return nil
503503
}
504504

505-
func getDiggerConfig(gh utils.GithubClientProvider, installationId int64, repoFullName string, repoOwner string, repoName string, cloneUrl string, prNumber int) (string, *dg_github.GithubService, *dg_configuration.DiggerConfig, graph.Graph[string, dg_configuration.Project], *string, error) {
505+
func getDiggerConfigForBranch(gh utils.GithubClientProvider, installationId int64, repoFullName string, repoOwner string, repoName string, cloneUrl string, branch string) (string, *dg_github.GithubService, *dg_configuration.DiggerConfig, graph.Graph[string, dg_configuration.Project], error) {
506506
ghService, token, err := utils.GetGithubService(gh, installationId, repoFullName, repoOwner, repoName)
507507
if err != nil {
508508
log.Printf("Error getting github service: %v", err)
509-
return "", nil, nil, nil, nil, fmt.Errorf("error getting github service")
510-
}
511-
var prBranch string
512-
prBranch, err = ghService.GetBranchName(prNumber)
513-
if err != nil {
514-
log.Printf("Error getting branch name: %v", err)
515-
return "", nil, nil, nil, nil, fmt.Errorf("error getting branch name")
509+
return "", nil, nil, nil, fmt.Errorf("error getting github service")
516510
}
517511

518512
var config *dg_configuration.DiggerConfig
519513
var diggerYmlStr string
520514
var dependencyGraph graph.Graph[string, dg_configuration.Project]
521-
err = utils.CloneGitRepoAndDoAction(cloneUrl, prBranch, *token, func(dir string) error {
515+
err = utils.CloneGitRepoAndDoAction(cloneUrl, branch, *token, func(dir string) error {
522516
diggerYmlBytes, err := os.ReadFile(path.Join(dir, "digger.yml"))
523517
diggerYmlStr = string(diggerYmlBytes)
524518
config, _, dependencyGraph, err = dg_configuration.LoadDiggerConfig(dir)
@@ -530,7 +524,31 @@ func getDiggerConfig(gh utils.GithubClientProvider, installationId int64, repoFu
530524
})
531525
if err != nil {
532526
log.Printf("Error generating projects: %v", err)
533-
return "", nil, nil, nil, nil, fmt.Errorf("error generating projects")
527+
return "", nil, nil, nil, fmt.Errorf("error generating projects")
528+
}
529+
530+
log.Printf("Digger config loadded successfully\n")
531+
return diggerYmlStr, ghService, config, dependencyGraph, nil
532+
}
533+
534+
func getDiggerConfigForPR(gh utils.GithubClientProvider, installationId int64, repoFullName string, repoOwner string, repoName string, cloneUrl string, prNumber int) (string, *dg_github.GithubService, *dg_configuration.DiggerConfig, graph.Graph[string, dg_configuration.Project], *string, error) {
535+
ghService, _, err := utils.GetGithubService(gh, installationId, repoFullName, repoOwner, repoName)
536+
if err != nil {
537+
log.Printf("Error getting github service: %v", err)
538+
return "", nil, nil, nil, nil, fmt.Errorf("error getting github service")
539+
}
540+
541+
var prBranch string
542+
prBranch, err = ghService.GetBranchName(prNumber)
543+
if err != nil {
544+
log.Printf("Error getting branch name: %v", err)
545+
return "", nil, nil, nil, nil, fmt.Errorf("error getting branch name")
546+
}
547+
548+
diggerYmlStr, ghService, config, dependencyGraph, err := getDiggerConfigForBranch(gh, installationId, repoFullName, repoOwner, repoName, cloneUrl, prBranch)
549+
if err != nil {
550+
log.Printf("Error loading digger.yml: %v", err)
551+
return "", nil, nil, nil, nil, fmt.Errorf("error loading digger.yml")
534552
}
535553

536554
log.Printf("Digger config loadded successfully\n")
@@ -583,9 +601,9 @@ func handleIssueCommentEvent(gh utils.GithubClientProvider, payload *github.Issu
583601
return nil
584602
}
585603

586-
diggerYmlStr, ghService, config, projectsGraph, branch, err := getDiggerConfig(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, issueNumber)
604+
diggerYmlStr, ghService, config, projectsGraph, branch, err := getDiggerConfigForPR(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, issueNumber)
587605
if err != nil {
588-
log.Printf("getDiggerConfig error: %v", err)
606+
log.Printf("getDiggerConfigForPR error: %v", err)
589607
return fmt.Errorf("error getting digger config")
590608
}
591609

+181
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package controllers
2+
3+
import (
4+
"fmt"
5+
"github.com/diggerhq/digger/backend/models"
6+
"github.com/diggerhq/digger/backend/utils"
7+
dg_github "github.com/diggerhq/digger/libs/orchestrator/github"
8+
"github.com/gin-gonic/gin"
9+
"github.com/google/go-github/v58/github"
10+
"log"
11+
"net/http"
12+
"os"
13+
"path"
14+
"reflect"
15+
"strings"
16+
)
17+
18+
func GithubAppWebHookAfterMerge(c *gin.Context) {
19+
c.Header("Content-Type", "application/json")
20+
gh := &utils.DiggerGithubRealClientProvider{}
21+
log.Printf("GithubAppWebHook")
22+
23+
payload, err := github.ValidatePayload(c.Request, []byte(os.Getenv("GITHUB_WEBHOOK_SECRET")))
24+
if err != nil {
25+
log.Printf("Error validating github app webhook's payload: %v", err)
26+
c.String(http.StatusBadRequest, "Error validating github app webhook's payload")
27+
return
28+
}
29+
30+
webhookType := github.WebHookType(c.Request)
31+
event, err := github.ParseWebHook(webhookType, payload)
32+
if err != nil {
33+
log.Printf("Failed to parse Github Event. :%v\n", err)
34+
c.String(http.StatusInternalServerError, "Failed to parse Github Event")
35+
return
36+
}
37+
38+
log.Printf("github event type: %v\n", reflect.TypeOf(event))
39+
40+
switch event := event.(type) {
41+
case *github.InstallationEvent:
42+
log.Printf("InstallationEvent, action: %v\n", *event.Action)
43+
if *event.Action == "created" {
44+
err := handleInstallationCreatedEvent(event)
45+
if err != nil {
46+
c.String(http.StatusInternalServerError, "Failed to handle webhook event.")
47+
return
48+
}
49+
}
50+
51+
if *event.Action == "deleted" {
52+
err := handleInstallationDeletedEvent(event)
53+
if err != nil {
54+
c.String(http.StatusInternalServerError, "Failed to handle webhook event.")
55+
return
56+
}
57+
}
58+
case *github.InstallationRepositoriesEvent:
59+
log.Printf("InstallationRepositoriesEvent, action: %v\n", *event.Action)
60+
if *event.Action == "added" {
61+
err := handleInstallationRepositoriesAddedEvent(gh, event)
62+
if err != nil {
63+
c.String(http.StatusInternalServerError, "Failed to handle installation repo added event.")
64+
}
65+
}
66+
if *event.Action == "removed" {
67+
err := handleInstallationRepositoriesDeletedEvent(event)
68+
if err != nil {
69+
c.String(http.StatusInternalServerError, "Failed to handle installation repo deleted event.")
70+
}
71+
}
72+
73+
case *github.IssueCommentEvent:
74+
log.Printf("IssueCommentEvent, action: %v IN APPLY AFTER MERGE\n", *event.Action)
75+
if event.Sender.Type != nil && *event.Sender.Type == "Bot" {
76+
c.String(http.StatusOK, "OK")
77+
return
78+
}
79+
err := handleIssueCommentEvent(gh, event)
80+
if err != nil {
81+
log.Printf("handleIssueCommentEvent error: %v", err)
82+
c.String(http.StatusInternalServerError, err.Error())
83+
return
84+
}
85+
case *github.PullRequestEvent:
86+
log.Printf("Got pull request event for %d IN APPLY AFTER MERGE", *event.PullRequest.ID)
87+
err := handlePullRequestEvent(gh, event)
88+
if err != nil {
89+
log.Printf("handlePullRequestEvent error: %v", err)
90+
c.String(http.StatusInternalServerError, err.Error())
91+
return
92+
}
93+
case *github.PushEvent:
94+
log.Printf("Got push event for %d", event.Repo.URL)
95+
err := handlePushEventApplyAfterMerge(gh, event)
96+
if err != nil {
97+
log.Printf("handlePushEvent error: %v", err)
98+
c.String(http.StatusInternalServerError, err.Error())
99+
return
100+
}
101+
default:
102+
log.Printf("Unhandled event, event type %v", reflect.TypeOf(event))
103+
}
104+
105+
c.JSON(200, "ok")
106+
}
107+
108+
func handlePushEventApplyAfterMerge(gh utils.GithubClientProvider, payload *github.PushEvent) error {
109+
installationId := *payload.Installation.ID
110+
repoName := *payload.Repo.Name
111+
repoFullName := *payload.Repo.FullName
112+
repoOwner := *payload.Repo.Owner.Login
113+
cloneURL := *payload.Repo.CloneURL
114+
commitId := *payload.After
115+
ref := *payload.Ref
116+
defaultBranch := *payload.Repo.DefaultBranch
117+
118+
if strings.HasSuffix(ref, defaultBranch) {
119+
link, err := models.DB.GetGithubAppInstallationLink(installationId)
120+
if err != nil {
121+
log.Printf("Error getting GetGithubAppInstallationLink: %v", err)
122+
return fmt.Errorf("error getting github app link")
123+
}
124+
125+
orgId := link.OrganisationId
126+
diggerRepoName := strings.ReplaceAll(repoFullName, "/", "-")
127+
repo, err := models.DB.GetRepo(orgId, diggerRepoName)
128+
if err != nil {
129+
log.Printf("Error getting Repo: %v", err)
130+
return fmt.Errorf("error getting github app link")
131+
}
132+
if repo == nil {
133+
log.Printf("Repo not found: Org: %v | repo: %v", orgId, diggerRepoName)
134+
return fmt.Errorf("Repo not found: Org: %v | repo: %v", orgId, diggerRepoName)
135+
}
136+
137+
service, token, err := utils.GetGithubService(gh, installationId, repoFullName, repoOwner, repoName)
138+
if err != nil {
139+
log.Printf("Error getting github service: %v", err)
140+
return fmt.Errorf("error getting github service")
141+
}
142+
utils.CloneGitRepoAndDoAction(cloneURL, defaultBranch, *token, func(dir string) error {
143+
dat, err := os.ReadFile(path.Join(dir, "digger.yml"))
144+
//TODO: fail here and return failure to main fn (need to refactor CloneGitRepoAndDoAction for that
145+
if err != nil {
146+
log.Printf("ERROR fetching digger.yml file: %v", err)
147+
}
148+
models.DB.UpdateRepoDiggerConfig(link.OrganisationId, string(dat), repo)
149+
return nil
150+
})
151+
152+
// ==== starting apply after merge part =======
153+
diggerYmlStr, ghService, config, projectsGraph, err := getDiggerConfigForBranch(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, commitId)
154+
if err != nil {
155+
log.Printf("getDiggerConfigForPR error: %v", err)
156+
return fmt.Errorf("error getting digger config")
157+
}
158+
159+
impactedProjects, requestedProject, _, err := dg_github.ProcessGitHubPushEvent(payload, config, projectsGraph, ghService)
160+
if err != nil {
161+
log.Printf("Error processing event: %v", err)
162+
return fmt.Errorf("error processing event")
163+
}
164+
log.Printf("GitHub IssueComment event processed successfully\n")
165+
166+
// create 2 jobspecs (digger plan, digger apply) using commitID
167+
168+
// create job for the jobSpecs
169+
170+
// create batch for each job
171+
172+
// create Run
173+
174+
// create RunStage for each batch attached to run
175+
176+
// queue a RunQueueItem for the created Run
177+
178+
}
179+
180+
return nil
181+
}

backend/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func main() {
7474
r.GET("/", web.RedirectToLoginOrProjects)
7575

7676
r.POST("/github-app-webhook", controllers.GithubAppWebHook)
77+
r.POST("/github-app-webhook/aam", controllers.GithubAppWebHookAfterMerge)
7778

7879
tenantActionsGroup := r.Group("/tenants")
7980
tenantActionsGroup.Use(middleware.CORSMiddleware())

libs/digger_config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package digger_config
22

33
type DiggerConfig struct {
4+
ApplyAfterMerge bool
45
DependencyConfiguration DependencyConfiguration
56
Projects []Project
67
AutoMerge bool

libs/digger_config/converters.go

+6
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ func ConvertDiggerYamlToConfig(diggerYaml *DiggerConfigYaml) (*DiggerConfig, gra
157157
diggerConfig.AutoMerge = false
158158
}
159159

160+
if diggerYaml.ApplyAfterMerge != nil {
161+
diggerConfig.ApplyAfterMerge = *diggerYaml.ApplyAfterMerge
162+
} else {
163+
diggerConfig.ApplyAfterMerge = false
164+
}
165+
160166
if diggerYaml.MentionDriftedProjectsInPR != nil {
161167
diggerConfig.MentionDriftedProjectsInPR = *diggerYaml.MentionDriftedProjectsInPR
162168
} else {

libs/digger_config/yaml.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
)
88

99
type DiggerConfigYaml struct {
10+
ApplyAfterMerge *bool `yaml:"apply_after_merge"`
1011
DependencyConfiguration *DependencyConfigurationYaml `yaml:"dependency_configuration"`
1112
Projects []*ProjectYaml `yaml:"projects"`
1213
AutoMerge *bool `yaml:"auto_merge"`

0 commit comments

Comments
 (0)