diff --git a/backend/bootstrap/main.go b/backend/bootstrap/main.go index af9de0bfa..79eda2139 100644 --- a/backend/bootstrap/main.go +++ b/backend/bootstrap/main.go @@ -80,7 +80,6 @@ func Bootstrap(templates embed.FS, diggerController controllers.DiggerController } r.POST("/github-app-webhook", diggerController.GithubAppWebHook) - r.POST("/github-app-webhook/aam", diggerController.GithubAppWebHookAfterMerge) tenantActionsGroup := r.Group("/api/tenants") tenantActionsGroup.Use(middleware.CORSMiddleware()) diff --git a/backend/controllers/github.go b/backend/controllers/github.go index c4d0195a8..06b9dedea 100644 --- a/backend/controllers/github.go +++ b/backend/controllers/github.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "github.com/diggerhq/digger/backend/ci_backends" "github.com/diggerhq/digger/backend/locking" @@ -15,6 +16,7 @@ import ( dg_locking "github.com/diggerhq/digger/libs/locking" orchestrator_scheduler "github.com/diggerhq/digger/libs/scheduler" "github.com/google/uuid" + "gorm.io/gorm" "log" "math/rand" "net/http" @@ -67,13 +69,6 @@ func (d DiggerController) GithubAppWebHook(c *gin.Context) { switch event := event.(type) { case *github.InstallationEvent: log.Printf("InstallationEvent, action: %v\n", *event.Action) - if *event.Action == "created" { - err := handleInstallationCreatedEvent(event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle webhook event.") - return - } - } if *event.Action == "deleted" { err := handleInstallationDeletedEvent(event) @@ -82,20 +77,6 @@ func (d DiggerController) GithubAppWebHook(c *gin.Context) { return } } - case *github.InstallationRepositoriesEvent: - log.Printf("InstallationRepositoriesEvent, action: %v\n", *event.Action) - if *event.Action == "added" { - err := handleInstallationRepositoriesAddedEvent(gh, event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle installation repo added event.") - } - } - if *event.Action == "removed" { - err := handleInstallationRepositoriesDeletedEvent(event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle installation repo deleted event.") - } - } case *github.IssueCommentEvent: log.Printf("IssueCommentEvent, action: %v\n", *event.Action) if event.Sender.Type != nil && *event.Sender.Type == "Bot" { @@ -288,19 +269,27 @@ func createOrGetDiggerRepoForGithubRepo(ghRepoFullName string, ghRepoOrganisatio diggerRepoName := strings.ReplaceAll(ghRepoFullName, "/", "-") - repo, err := models.DB.GetRepo(orgId, diggerRepoName) + // using Unscoped because we also need to include deleted repos (and undelete them if they exist) + var existingRepo models.Repo + r := models.DB.GormDB.Unscoped().Where("organisation_id=? AND repos.name=?", orgId, diggerRepoName).Find(&existingRepo) - if err != nil { - log.Printf("Error fetching repo: %v", err) - return nil, nil, err + if r.Error != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + log.Printf("repo not found, will proceed with repo creation") + } else { + log.Printf("Error fetching repo: %v", err) + return nil, nil, err + } } - if repo != nil { - log.Printf("Digger repo already exists: %v", repo) - return repo, org, nil + if r.RowsAffected > 0 { + existingRepo.DeletedAt = gorm.DeletedAt{} + models.DB.GormDB.Save(&existingRepo) + log.Printf("Digger repo already exists: %v", existingRepo) + return &existingRepo, org, nil } - repo, err = models.DB.CreateRepo(diggerRepoName, ghRepoFullName, ghRepoOrganisation, ghRepoName, ghRepoUrl, org, ` + repo, err := models.DB.CreateRepo(diggerRepoName, ghRepoFullName, ghRepoOrganisation, ghRepoName, ghRepoUrl, org, ` generate_projects: include: "." `) @@ -312,72 +301,6 @@ generate_projects: return repo, org, nil } -func handleInstallationRepositoriesAddedEvent(ghClientProvider utils.GithubClientProvider, payload *github.InstallationRepositoriesEvent) error { - installationId := *payload.Installation.ID - login := *payload.Installation.Account.Login - accountId := *payload.Installation.Account.ID - appId := *payload.Installation.AppID - - for _, repo := range payload.RepositoriesAdded { - repoFullName := *repo.FullName - repoOwner := strings.Split(*repo.FullName, "/")[0] - repoName := *repo.Name - repoUrl := fmt.Sprintf("https://github.com/%v", repoFullName) - _, err := models.DB.GithubRepoAdded(installationId, appId, login, accountId, repoFullName) - if err != nil { - log.Printf("GithubRepoAdded failed, error: %v\n", err) - return err - } - - _, _, err = createOrGetDiggerRepoForGithubRepo(repoFullName, repoOwner, repoName, repoUrl, installationId) - if err != nil { - log.Printf("createOrGetDiggerRepoForGithubRepo failed, error: %v\n", err) - return err - } - } - return nil -} - -func handleInstallationRepositoriesDeletedEvent(payload *github.InstallationRepositoriesEvent) error { - installationId := *payload.Installation.ID - appId := *payload.Installation.AppID - for _, repo := range payload.RepositoriesRemoved { - repoFullName := *repo.FullName - _, err := models.DB.GithubRepoRemoved(installationId, appId, repoFullName) - if err != nil { - return err - } - - // todo: change the status of DiggerRepo to InActive - } - return nil -} - -func handleInstallationCreatedEvent(installation *github.InstallationEvent) error { - installationId := *installation.Installation.ID - login := *installation.Installation.Account.Login - accountId := *installation.Installation.Account.ID - appId := *installation.Installation.AppID - - for _, repo := range installation.Repositories { - repoFullName := *repo.FullName - repoOwner := strings.Split(*repo.FullName, "/")[0] - repoName := *repo.Name - repoUrl := fmt.Sprintf("https://github.com/%v", repoFullName) - - log.Printf("Adding a new installation %d for repo: %s", installationId, repoFullName) - _, err := models.DB.GithubRepoAdded(installationId, appId, login, accountId, repoFullName) - if err != nil { - return err - } - _, _, err = createOrGetDiggerRepoForGithubRepo(repoFullName, repoOwner, repoName, repoUrl, installationId) - if err != nil { - return err - } - } - return nil -} - func handleInstallationDeletedEvent(installation *github.InstallationEvent) error { installationId := *installation.Installation.ID appId := *installation.Installation.AppID @@ -1127,12 +1050,6 @@ func (d DiggerController) GithubAppCallbackPage(c *gin.Context) { clientId := os.Getenv("GITHUB_APP_CLIENT_ID") clientSecret := os.Getenv("GITHUB_APP_CLIENT_SECRET") - orgId, exists := c.Get(middleware.ORGANISATION_ID_KEY) - if !exists { - c.String(http.StatusForbidden, "Not allowed to access this resource") - return - } - installationId64, err := strconv.ParseInt(installationId, 10, 64) if err != nil { log.Printf("err: %v", err) @@ -1140,13 +1057,22 @@ func (d DiggerController) GithubAppCallbackPage(c *gin.Context) { return } - result, err := validateGithubCallback(d.GithubClientProvider, clientId, clientSecret, code, installationId64) + result, installation, err := validateGithubCallback(d.GithubClientProvider, clientId, clientSecret, code, installationId64) if !result { log.Printf("Failed to validated installation id, %v\n", err) c.String(http.StatusInternalServerError, "Failed to validate installation_id.") return } + // TODO: Lookup org in GithubAppInstallation by installationID if found use that installationID otherwise + // create a new org for this installationID + // retrive org for current orgID + orgId, exists := c.Get(middleware.ORGANISATION_ID_KEY) + if !exists { + log.Printf("Unable to retrive orgId: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Unable to retrive orgId"}) + return + } org, err := models.DB.GetOrganisationById(orgId) if err != nil { log.Printf("Error fetching organisation: %v", err) @@ -1154,12 +1080,70 @@ func (d DiggerController) GithubAppCallbackPage(c *gin.Context) { return } + // create a github installation link (org ID matched to installation ID) _, err = models.DB.CreateGithubInstallationLink(org, installationId64) if err != nil { log.Printf("Error saving CreateGithubInstallationLink to database: %v", err) c.JSON(http.StatusInternalServerError, gin.H{"error": "Error updating GitHub installation"}) return } + + client, _, err := d.GithubClientProvider.Get(*installation.AppID, installationId64) + if err != nil { + log.Printf("Error retriving github client: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Error fetching organisation"}) + return + + } + + // we get repos accessible to this installation + listRepos, _, err := client.Apps.ListRepos(context.Background(), nil) + if err != nil { + log.Printf("Failed to validated list existing repos, %v\n", err) + c.String(http.StatusInternalServerError, "Failed to list existing repos: %v", err) + return + } + repos := listRepos.Repositories + + // resets all existing installations (soft delete) + var AppInstallation models.GithubAppInstallation + err = models.DB.GormDB.Model(&AppInstallation).Where("github_installation_id=?", installationId).Update("status", models.GithubAppInstallDeleted).Error + if err != nil { + log.Printf("Failed to update github installations: %v", err) + c.String(http.StatusInternalServerError, "Failed to update github installations: %v", err) + return + } + + // reset all existing repos (soft delete) + var ExistingRepos []models.Repo + err = models.DB.GormDB.Delete(ExistingRepos, "organisation_id=?", orgId).Error + if err != nil { + log.Printf("could not delete repos: %v", err) + c.String(http.StatusInternalServerError, "could not delete repos: %v", err) + return + } + + // here we mark repos that are available one by one + for _, repo := range repos { + repoFullName := *repo.FullName + repoOwner := strings.Split(*repo.FullName, "/")[0] + repoName := *repo.Name + repoUrl := fmt.Sprintf("https://github.com/%v", repoFullName) + _, err := models.DB.GithubRepoAdded(installationId64, *installation.AppID, *installation.Account.Login, *installation.Account.ID, repoFullName) + if err != nil { + log.Printf("github repos added error: %v", err) + c.String(http.StatusInternalServerError, "github repos added error: %v", err) + return + } + + _, _, err = createOrGetDiggerRepoForGithubRepo(repoFullName, repoOwner, repoName, repoUrl, installationId64) + if err != nil { + log.Printf("createOrGetDiggerRepoForGithubRepo error: %v", err) + c.String(http.StatusInternalServerError, "createOrGetDiggerRepoForGithubRepo error: %v", err) + return + } + } + c.HTML(http.StatusOK, "github_success.tmpl", gin.H{}) } @@ -1210,7 +1194,7 @@ func (d DiggerController) GithubReposPage(c *gin.Context) { // why this validation is needed: https://roadie.io/blog/avoid-leaking-github-org-data/ // validation based on https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app , step 3 -func validateGithubCallback(githubClientProvider utils.GithubClientProvider, clientId string, clientSecret string, code string, installationId int64) (bool, error) { +func validateGithubCallback(githubClientProvider utils.GithubClientProvider, clientId string, clientSecret string, code string, installationId int64) (bool, *github.Installation, error) { ctx := context.Background() type OAuthAccessResponse struct { AccessToken string `json:"access_token"` @@ -1221,22 +1205,22 @@ func validateGithubCallback(githubClientProvider utils.GithubClientProvider, cli reqURL := fmt.Sprintf("https://%v/login/oauth/access_token?client_id=%s&client_secret=%s&code=%s", githubHostname, clientId, clientSecret, code) req, err := http.NewRequest(http.MethodPost, reqURL, nil) if err != nil { - return false, fmt.Errorf("could not create HTTP request: %v\n", err) + return false, nil, fmt.Errorf("could not create HTTP request: %v\n", err) } req.Header.Set("accept", "application/json") res, err := httpClient.Do(req) if err != nil { - return false, fmt.Errorf("request to login/oauth/access_token failed: %v\n", err) + return false, nil, fmt.Errorf("request to login/oauth/access_token failed: %v\n", err) } if err != nil { - return false, fmt.Errorf("Failed to read response's body: %v\n", err) + return false, nil, fmt.Errorf("Failed to read response's body: %v\n", err) } var t OAuthAccessResponse if err := json.NewDecoder(res.Body).Decode(&t); err != nil { - return false, fmt.Errorf("could not parse JSON response: %v\n", err) + return false, nil, fmt.Errorf("could not parse JSON response: %v\n", err) } ts := oauth2.StaticTokenSource( @@ -1253,25 +1237,28 @@ func validateGithubCallback(githubClientProvider utils.GithubClientProvider, cli client, err := githubClientProvider.NewClient(tc) if err != nil { log.Printf("could create github client: %v", err) - return false, fmt.Errorf("could not create github client: %v", err) + return false, nil, fmt.Errorf("could not create github client: %v", err) } installationIdMatch := false // list all installations for the user + var matchedInstallation *github.Installation installations, _, err := client.Apps.ListUserInstallations(ctx, nil) if err != nil { log.Printf("could not retrieve installations: %v", err) - return false, fmt.Errorf("could not retrieve installations: %v", installationId) + return false, nil, fmt.Errorf("could not retrieve installations: %v", installationId) } log.Printf("installations %v", installations) for _, v := range installations { log.Printf("installation id: %v\n", *v.ID) if *v.ID == installationId { + matchedInstallation = v installationIdMatch = true } } if !installationIdMatch { - return false, fmt.Errorf("InstallationId %v doesn't match any id for specified user\n", installationId) + return false, nil, fmt.Errorf("InstallationId %v doesn't match any id for specified user\n", installationId) } - return true, nil + + return true, matchedInstallation, nil } diff --git a/backend/controllers/github_after_merge.go b/backend/controllers/github_after_merge.go deleted file mode 100644 index 4917585fa..000000000 --- a/backend/controllers/github_after_merge.go +++ /dev/null @@ -1,297 +0,0 @@ -package controllers - -import ( - "encoding/json" - "fmt" - "github.com/diggerhq/digger/backend/models" - "github.com/diggerhq/digger/backend/utils" - "github.com/diggerhq/digger/libs/ci/generic" - dg_github "github.com/diggerhq/digger/libs/ci/github" - dg_configuration "github.com/diggerhq/digger/libs/digger_config" - "github.com/diggerhq/digger/libs/scheduler" - "github.com/gin-gonic/gin" - "github.com/google/go-github/v61/github" - "log" - "net/http" - "os" - "reflect" - "strings" -) - -func (d DiggerController) GithubAppWebHookAfterMerge(c *gin.Context) { - c.Header("Content-Type", "application/json") - gh := d.GithubClientProvider - log.Printf("GithubAppWebHook") - - payload, err := github.ValidatePayload(c.Request, []byte(os.Getenv("GITHUB_WEBHOOK_SECRET"))) - if err != nil { - log.Printf("Error validating github app webhook's payload: %v", err) - c.String(http.StatusBadRequest, "Error validating github app webhook's payload") - return - } - - webhookType := github.WebHookType(c.Request) - event, err := github.ParseWebHook(webhookType, payload) - if err != nil { - log.Printf("Failed to parse Github Event. :%v\n", err) - c.String(http.StatusInternalServerError, "Failed to parse Github Event") - return - } - - log.Printf("github event type: %v\n", reflect.TypeOf(event)) - - switch event := event.(type) { - case *github.InstallationEvent: - log.Printf("InstallationEvent, action: %v\n", *event.Action) - if *event.Action == "created" { - err := handleInstallationCreatedEvent(event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle webhook event.") - return - } - } - - if *event.Action == "deleted" { - err := handleInstallationDeletedEvent(event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle webhook event.") - return - } - } - case *github.InstallationRepositoriesEvent: - log.Printf("InstallationRepositoriesEvent, action: %v\n", *event.Action) - if *event.Action == "added" { - err := handleInstallationRepositoriesAddedEvent(gh, event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle installation repo added event.") - } - } - if *event.Action == "removed" { - err := handleInstallationRepositoriesDeletedEvent(event) - if err != nil { - c.String(http.StatusInternalServerError, "Failed to handle installation repo deleted event.") - } - } - - //case *github.IssueCommentEvent: - // log.Printf("IssueCommentEvent, action: %v IN APPLY AFTER MERGE\n", *event.Action) - // if event.Sender.Type != nil && *event.Sender.Type == "Bot" { - // c.String(http.StatusOK, "OK") - // return - // } - // err := handleIssueCommentEvent(gh, event) - // if err != nil { - // log.Printf("handleIssueCommentEvent error: %v", err) - // c.String(http.StatusInternalServerError, err.Error()) - // return - // } - case *github.PullRequestEvent: - log.Printf("Got pull request event for %d IN APPLY AFTER MERGE", *event.PullRequest.ID) - err := handlePullRequestEvent(gh, event, nil) - if err != nil { - log.Printf("handlePullRequestEvent error: %v", err) - c.String(http.StatusInternalServerError, err.Error()) - return - } - case *github.PushEvent: - log.Printf("Got push event for %d", event.Repo.URL) - err := handlePushEventApplyAfterMerge(gh, event) - if err != nil { - log.Printf("handlePushEvent error: %v", err) - c.String(http.StatusInternalServerError, err.Error()) - return - } - default: - log.Printf("Unhandled event, event type %v", reflect.TypeOf(event)) - } - - c.JSON(200, "ok") -} - -func handlePushEventApplyAfterMerge(gh utils.GithubClientProvider, payload *github.PushEvent) error { - print("*** HANDLING PUSH EVENT *****") - installationId := *payload.Installation.ID - repoName := *payload.Repo.Name - repoFullName := *payload.Repo.FullName - repoOwner := *payload.Repo.Owner.Login - cloneURL := *payload.Repo.CloneURL - commitId := *payload.After - requestedBy := *payload.Sender.Login - ref := *payload.Ref - defaultBranch := *payload.Repo.DefaultBranch - backendHostName := os.Getenv("HOSTNAME") - - if strings.HasSuffix(ref, defaultBranch) { - link, err := models.DB.GetGithubAppInstallationLink(installationId) - if err != nil { - log.Printf("Error getting GetGithubAppInstallationLink: %v", err) - return fmt.Errorf("error getting github app link") - } - - orgId := link.OrganisationId - orgName := link.Organisation.Name - diggerRepoName := strings.ReplaceAll(repoFullName, "/", "-") - repo, err := models.DB.GetRepo(orgId, diggerRepoName) - if err != nil { - log.Printf("Error getting Repo: %v", err) - return fmt.Errorf("error getting github app link") - } - if repo == nil { - log.Printf("Repo not found: Org: %v | repo: %v", orgId, diggerRepoName) - return fmt.Errorf("Repo not found: Org: %v | repo: %v", orgId, diggerRepoName) - } - - service, token, err := utils.GetGithubService(gh, installationId, repoFullName, repoOwner, repoName) - if err != nil { - log.Printf("Error getting github service: %v", err) - return fmt.Errorf("error getting github service") - } - err = utils.CloneGitRepoAndDoAction(cloneURL, defaultBranch, *token, func(dir string) error { - config, err := dg_configuration.LoadDiggerConfigYaml(dir, true, nil) - if err != nil { - log.Printf("ERROR load digger.yml: %v", err) - return fmt.Errorf("error loading digger.yml %v", err) - } - models.DB.UpdateRepoDiggerConfig(link.OrganisationId, *config, repo, true) - return nil - }) - - // ==== starting apply after merge part ======= - // TODO: Replace branch with actual commitID - diggerYmlStr, ghService, config, projectsGraph, err := getDiggerConfigForBranch(gh, installationId, repoFullName, repoOwner, repoName, cloneURL, defaultBranch, 0) - if err != nil { - log.Printf("getDiggerConfigForPR error: %v", err) - return fmt.Errorf("error getting digger config") - } - - impactedProjects, _, requestedProject, _, err := dg_github.ProcessGitHubPushEvent(payload, config, projectsGraph, ghService) - if err != nil { - log.Printf("Error processing event: %v", err) - return fmt.Errorf("error processing event") - } - log.Printf("GitHub IssueComment event processed successfully\n") - - // TODO: delete this line - fmt.Sprintf(diggerYmlStr, impactedProjects, requestedProject, service) - - // create 2 jobspecs (digger plan, digger apply) using commitID - // TODO: find a way to get issue number from github api PushEvent - // TODO: find a way to set the right PR branch - issueNumber := 14 - - planJobs, err := generic.CreateJobsForProjects(impactedProjects, "digger plan", "push", repoFullName, requestedBy, config.Workflows, &issueNumber, &commitId, defaultBranch, defaultBranch) - if err != nil { - log.Printf("Error creating jobs: %v", err) - return fmt.Errorf("error creating jobs") - } - - applyJobs, err := generic.CreateJobsForProjects(impactedProjects, "digger apply", "push", repoFullName, requestedBy, config.Workflows, &issueNumber, &commitId, defaultBranch, defaultBranch) - if err != nil { - log.Printf("Error creating jobs: %v", err) - return fmt.Errorf("error creating jobs") - } - - if len(planJobs) == 0 || len(applyJobs) == 0 { - log.Printf("no projects impacated, succeeding") - return nil - } - - impactedProjectsMap := make(map[string]dg_configuration.Project) - for _, p := range impactedProjects { - impactedProjectsMap[p.Name] = p - } - - impactedProjectsJobMap := make(map[string]scheduler.Job) - for _, j := range planJobs { - impactedProjectsJobMap[j.ProjectName] = j - } - - for i, _ := range planJobs { - planJob := planJobs[i] - applyJob := applyJobs[i] - projectName := planJob.ProjectName - - planJobToken, err := models.DB.CreateDiggerJobToken(orgId) - if err != nil { - log.Printf("Error creating job token: %v %v", projectName, err) - return fmt.Errorf("error creating job token") - } - - planJobSpec, err := json.Marshal(scheduler.JobToJson(planJob, scheduler.DiggerCommandPlan, orgName, "", "", planJobToken.Value, backendHostName, impactedProjects[i])) - if err != nil { - log.Printf("Error creating jobspec: %v %v", projectName, err) - return fmt.Errorf("error creating jobspec") - - } - - applyJobToken, err := models.DB.CreateDiggerJobToken(orgId) - if err != nil { - log.Printf("Error creating job token: %v %v", projectName, err) - return fmt.Errorf("error creating job token") - } - - applyJobSpec, err := json.Marshal(scheduler.JobToJson(applyJob, scheduler.DiggerCommandApply, orgName, "", "", applyJobToken.Value, backendHostName, impactedProjects[i])) - if err != nil { - log.Printf("Error creating jobs: %v %v", projectName, err) - return fmt.Errorf("error creating jobs") - } - - // create batches - planBatch, err := models.DB.CreateDiggerBatch(models.DiggerVCSGithub, installationId, repoOwner, repoName, repoFullName, issueNumber, diggerYmlStr, defaultBranch, scheduler.DiggerCommandPlan, nil, 0) - if err != nil { - log.Printf("Error creating batch: %v", err) - return fmt.Errorf("error creating batch") - } - - applyBatch, err := models.DB.CreateDiggerBatch(models.DiggerVCSGithub, installationId, repoOwner, repoName, repoFullName, issueNumber, diggerYmlStr, defaultBranch, scheduler.DiggerCommandApply, nil, 0) - if err != nil { - log.Printf("Error creating batch: %v", err) - return fmt.Errorf("error creating batch") - } - - // create jobs - _, err = models.DB.CreateDiggerJob(planBatch.ID, planJobSpec, impactedProjects[i].WorkflowFile) - if err != nil { - log.Printf("Error creating digger job: %v", err) - return fmt.Errorf("error creating digger job") - } - - _, err = models.DB.CreateDiggerJob(applyBatch.ID, applyJobSpec, impactedProjects[i].WorkflowFile) - if err != nil { - log.Printf("Error creating digger job: %v", err) - return fmt.Errorf("error creating digger job") - } - - // creating run stages - planStage, err := models.DB.CreateDiggerRunStage(planBatch.ID.String()) - if err != nil { - log.Printf("Error creating digger run stage: %v", err) - return fmt.Errorf("error creating digger run stage") - } - - applyStage, err := models.DB.CreateDiggerRunStage(applyBatch.ID.String()) - if err != nil { - log.Printf("Error creating digger run stage: %v", err) - return fmt.Errorf("error creating digger run stage") - } - - diggerRun, err := models.DB.CreateDiggerRun("push", 0, models.RunQueued, commitId, diggerYmlStr, installationId, repo.ID, projectName, models.PlanAndApply, &planStage.ID, &applyStage.ID) - if err != nil { - log.Printf("Error creating digger run: %v", err) - return fmt.Errorf("error creating digger run") - } - - project, err := models.DB.GetProjectByName(orgId, repo, projectName) - if err != nil { - log.Printf("Error getting project: %v", err) - return fmt.Errorf("error getting project") - } - - models.DB.CreateDiggerRunQueueItem(diggerRun.ID, project.ID) - - } - - } - - return nil -} diff --git a/backend/controllers/github_test.go b/backend/controllers/github_test.go index 01def47fc..c5cebd691 100644 --- a/backend/controllers/github_test.go +++ b/backend/controllers/github_test.go @@ -865,203 +865,3 @@ func TestJobsTreeWithThreeLevels(t *testing.T) { assert.NoError(t, err) assert.Equal(t, result["333"].DiggerJobID, parentLinks[0].ParentDiggerJobId) } - -func TestGithubInstallationRepoAddedEvent(t *testing.T) { - teardownSuite, _ := setupSuite(t) - defer teardownSuite(t) - - githubAppId := int64(360162) - login := "test" - accountId := 1 - installationId := int64(41584295) - repoFullName := "diggerhq/test-github-action" - _, err := models.DB.CreateGithubAppInstallation(installationId, githubAppId, login, accountId, repoFullName) - if err != nil { - log.Fatal(err) - } - - mockedHTTPClient := mock.NewMockedHTTPClient( - mock.WithRequestMatch( - mock.GetReposByOwnerByRepo, - github.Repository{ - Name: github.String("testRepo"), - DefaultBranch: github.String("main"), - }), - mock.WithRequestMatch( - mock.GetReposGitRefByOwnerByRepoByRef, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}, Ref: github.String("test_ref")}, - ), - mock.WithRequestMatch( - mock.PostReposGitRefsByOwnerByRepo, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}}, - ), - mock.WithRequestMatch( - mock.GetReposContentsByOwnerByRepoByPath, - github.RepositoryContent{}, - ), - ) - - gh := &utils.DiggerGithubClientMockProvider{} - gh.MockedHTTPClient = mockedHTTPClient - - var payload github.InstallationRepositoriesEvent - err = json.Unmarshal([]byte(installationRepositoriesAddedPayload), &payload) - assert.NoError(t, err) - err = handleInstallationRepositoriesAddedEvent(gh, &payload) - assert.NoError(t, err) - - orgId := 1 - appInstall, err := models.DB.GetGithubAppInstallationByOrgAndRepo(orgId, *payload.RepositoriesAdded[0].FullName, models.GithubAppInstallActive) - assert.NoError(t, err) - assert.NotNil(t, appInstall) -} - -func TestGithubInstallationRepoDeletedEvent(t *testing.T) { - teardownSuite, _ := setupSuite(t) - defer teardownSuite(t) - - githubAppId := int64(360162) - login := "test" - accountId := 1 - installationId := int64(41584295) - repoFullName := "diggerhq/test-github-action" - _, err := models.DB.CreateGithubAppInstallation(installationId, githubAppId, login, accountId, repoFullName) - if err != nil { - log.Fatal(err) - } - - mockedHTTPClient := mock.NewMockedHTTPClient() - - gh := &utils.DiggerGithubClientMockProvider{} - gh.MockedHTTPClient = mockedHTTPClient - - var payload github.InstallationRepositoriesEvent - err = json.Unmarshal([]byte(installationRepositoriesDeletedPayload), &payload) - assert.NoError(t, err) - err = handleInstallationRepositoriesDeletedEvent(&payload) - assert.NoError(t, err) - - orgId := 1 - appInstall, err := models.DB.GetGithubAppInstallationByOrgAndRepo(orgId, *payload.RepositoriesRemoved[0].FullName, models.GithubAppInstallDeleted) - assert.NoError(t, err) - assert.NotNil(t, appInstall) -} - -func TestGithubInstallationRepoAddedDiggerWorkflowDoesntExistEvent(t *testing.T) { - teardownSuite, _ := setupSuite(t) - defer teardownSuite(t) - - githubAppId := int64(360162) - login := "test" - accountId := 1 - installationId := int64(41584295) - repoFullName := "diggerhq/test-github-action" - _, err := models.DB.CreateGithubAppInstallation(installationId, githubAppId, login, accountId, repoFullName) - if err != nil { - log.Fatal(err) - } - - mockedHTTPClient := mock.NewMockedHTTPClient( - mock.WithRequestMatch( - mock.GetReposByOwnerByRepo, - github.Repository{ - Name: github.String("testRepo"), - DefaultBranch: github.String("main"), - }), - mock.WithRequestMatch( - mock.GetReposGitRefByOwnerByRepoByRef, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}, Ref: github.String("test_ref")}, - ), - mock.WithRequestMatch( - mock.PostReposGitRefsByOwnerByRepo, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}}, - ), - mock.WithRequestMatch( - mock.GetReposContentsByOwnerByRepoByPath, - nil, - ), - mock.WithRequestMatch( - mock.PutReposContentsByOwnerByRepoByPath, - nil, - ), - mock.WithRequestMatch( - mock.PostReposPullsByOwnerByRepo, - nil, - ), - ) - - gh := &utils.DiggerGithubClientMockProvider{} - gh.MockedHTTPClient = mockedHTTPClient - - var payload github.InstallationRepositoriesEvent - err = json.Unmarshal([]byte(installationRepositoriesAddedPayload), &payload) - assert.NoError(t, err) - err = handleInstallationRepositoriesAddedEvent(gh, &payload) - assert.NoError(t, err) - - orgId := 1 - appInstall, err := models.DB.GetGithubAppInstallationByOrgAndRepo(orgId, *payload.RepositoriesAdded[0].FullName, models.GithubAppInstallActive) - assert.NoError(t, err) - assert.NotNil(t, appInstall) -} - -func TestGithubInstallationRepoAddedDiggerWorkflowExistEvent(t *testing.T) { - teardownSuite, _ := setupSuite(t) - defer teardownSuite(t) - - githubAppId := int64(360162) - login := "test" - accountId := 1 - installationId := int64(41584295) - repoFullName := "diggerhq/test-github-action" - _, err := models.DB.CreateGithubAppInstallation(installationId, githubAppId, login, accountId, repoFullName) - if err != nil { - log.Fatal(err) - } - - mockedHTTPClient := mock.NewMockedHTTPClient( - mock.WithRequestMatch( - mock.GetReposByOwnerByRepo, - github.Repository{ - Name: github.String("testRepo"), - DefaultBranch: github.String("main"), - }), - mock.WithRequestMatch( - mock.GetReposGitRefByOwnerByRepoByRef, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}, Ref: github.String("test_ref")}, - ), - mock.WithRequestMatch( - mock.PostReposGitRefsByOwnerByRepo, - github.Reference{Object: &github.GitObject{SHA: github.String("test")}}, - ), - mock.WithRequestMatch( - mock.GetReposContentsByOwnerByRepoByPath, - github.RepositoryContent{Content: github.String("workflow file")}, - ), - ) - - gh := &utils.DiggerGithubClientMockProvider{} - gh.MockedHTTPClient = mockedHTTPClient - - var payload github.InstallationRepositoriesEvent - err = json.Unmarshal([]byte(installationRepositoriesAddedPayload), &payload) - assert.NoError(t, err) - err = handleInstallationRepositoriesAddedEvent(gh, &payload) - assert.NoError(t, err) - - orgId := 1 - appInstall, err := models.DB.GetGithubAppInstallationByOrgAndRepo(orgId, *payload.RepositoriesAdded[0].FullName, models.GithubAppInstallActive) - assert.NoError(t, err) - assert.NotNil(t, appInstall) -} - -func TestGithubHandleInstallationCreatedEvent(t *testing.T) { - teardownSuite, _ := setupSuite(t) - defer teardownSuite(t) - - var event github.InstallationEvent - err := json.Unmarshal([]byte(installationCreatedEvent), &event) - assert.NoError(t, err) - err = handleInstallationCreatedEvent(&event) - assert.NoError(t, err) -}