Skip to content

Commit

Permalink
feat(github): extract relation between pr and issue
Browse files Browse the repository at this point in the history
Closes #1257
  • Loading branch information
warren830 committed Feb 27, 2022
1 parent 40117ea commit a674f06
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 33 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ require (
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.1.4
github.com/emirpasic/gods v1.12.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions models/domainlayer/code/pull_request_issue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package code

type PullRequestIssue struct {
PullRequestId string `json:"id" gorm:"primaryKey;type:varchar(255);comment:This key is generated based on details from the original plugin"` // format: <Plugin>:<Entity>:<PK0>:<PK1>
IssueId string `gorm:"primaryKey"`
}
1 change: 1 addition & 0 deletions models/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func migrateDB() {
&devops.Build{},
&ticket.Worklog{},
&crossdomain.BoardRepo{},
&code.PullRequestIssue{},
&crossdomain.IssueCommit{},
)
if err != nil {
Expand Down
1 change: 0 additions & 1 deletion plugins/core/apiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ func RemoveStartingSlashFromPath(relativePath string) string {
}
func (apiClient *ApiClient) GetAsync(path string, queryParams *url.Values, handler func(*http.Response) error) error {
err := apiClient.scheduler.Submit(func() error {
fmt.Println(queryParams.Get("page"))
res, err := apiClient.Get(path, queryParams, nil)
if err != nil {
return err
Expand Down
89 changes: 58 additions & 31 deletions plugins/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (plugin Github) Init() {
&models.GithubIssueEvent{},
&models.GithubIssueLabel{},
&models.GithubUser{},
&models.GithubPullRequestIssue{},
)
if err != nil {
logger.Error("Error migrating github: ", err)
Expand Down Expand Up @@ -73,27 +74,29 @@ func (plugin Github) Execute(options map[string]interface{}, progress chan<- flo
tasksToRun := make(map[string]bool, len(op.Tasks))
if len(op.Tasks) == 0 {
tasksToRun = map[string]bool{
"collectRepo": true,
"collectCommits": true,
"collectCommitsStat": true,
"collectIssues": true,
"collectIssueEvents": true,
"collectIssueComments": true,
"collectPullRequests": true,
"collectPullRequestReviews": true,
"collectPullRequestCommits": true,
"collectPullRequestComments": true,
"enrichIssues": true,
"enrichPullRequests": true,
"convertRepos": true,
"convertIssues": true,
"convertIssueLabels": true,
"convertPullRequests": true,
"convertCommits": true,
"convertPullRequestCommits": true,
"convertPullRequestLabels": true,
"convertNotes": true,
"convertUsers": true,
"collectRepo": true,
"collectCommits": true,
"collectCommitsStat": true,
"collectIssues": true,
"collectIssueEvents": true,
"collectIssueComments": true,
"collectPullRequests": true,
"collectPullRequestReviews": true,
"collectPullRequestCommits": true,
"collectPullRequestComments": true,
"enrichIssues": true,
"enrichPullRequests": true,
"enrichGithubPullRequestIssues": true,
"convertRepos": true,
"convertIssues": true,
"convertIssueLabels": true,
"convertPullRequests": true,
"convertCommits": true,
"convertPullRequestCommits": true,
"convertPullRequestIssues": true,
"convertPullRequestLabels": true,
"convertNotes": true,
"convertUsers": true,
}
} else {
for _, task := range op.Tasks {
Expand Down Expand Up @@ -187,7 +190,6 @@ func (plugin Github) Execute(options map[string]interface{}, progress chan<- flo
}
}
}

if tasksToRun["collectPullRequests"] {
progress <- 0.4
fmt.Println("INFO >>> collecting PR collection")
Expand Down Expand Up @@ -258,6 +260,17 @@ func (plugin Github) Execute(options map[string]interface{}, progress chan<- flo
}
}
}
if tasksToRun["enrichGithubPullRequestIssues"] {
progress <- 0.92
fmt.Println("INFO >>> Enriching PullRequests")
err = tasks.EnrichGithubPullRequestIssue(repoId, ctx)
if err != nil {
return &errors.SubTaskError{
Message: fmt.Errorf("could not enrich PullRequests: %v", err).Error(),
SubTaskName: "enrichPullRequests",
}
}
}
if tasksToRun["convertRepos"] {
progress <- 0.93
err = tasks.ConvertRepos(ctx)
Expand Down Expand Up @@ -325,6 +338,17 @@ func (plugin Github) Execute(options map[string]interface{}, progress chan<- flo
}
}
}
if tasksToRun["convertPullRequestIssues"] {
progress <- 0.97
fmt.Println("INFO >>> starting Issue Comments collection")
err = tasks.ConvertPullRequestIssues()
if err != nil {
return &errors.SubTaskError{
Message: fmt.Errorf("Could not collect Issue Comments: %v", err).Error(),
SubTaskName: "collectIssueComments",
}
}
}
if tasksToRun["convertNotes"] {
progress <- 0.98
err = tasks.ConvertNotes(ctx)
Expand Down Expand Up @@ -377,8 +401,8 @@ var PluginEntry Github //nolint
// standalone mode for debugging
func main() {
args := os.Args[1:]
owner := "pingcap"
repo := "tidb"
owner := "tikv"
repo := "tikv"
if len(args) > 0 {
owner = args[0]
}
Expand Down Expand Up @@ -410,22 +434,25 @@ func main() {
"collectRepo",
//"collectCommits",
//"collectCommitsStat",
"collectIssues",
//"collectIssues",
"collectPullRequests",
//"collectIssueEvents",
"collectIssueEvents",
"collectIssueComments",
//"collectPullRequestReviews",
//"collectPullRequestCommits",
//"collectPullRequestComments",
"collectPullRequestReviews",
"collectPullRequestCommits",
"collectPullRequestComments",
"enrichIssues",
"enrichPullRequests",
//"convertRepos",
"convertRepos",
"convertIssues",
"convertIssueLabels",
"convertPullRequests",
"convertPullRequestLabels",
//"enrichGithubPullRequestIssues",
//"convertCommits",
//"convertPullRequestCommits",
"convertPullRequestCommits",
//"convertPullRequestIssues",

//"convertNotes",
//"convertUsers",
},
Expand Down
1 change: 1 addition & 0 deletions plugins/github/models/github_pull_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ type GithubPullRequest struct {
Type string
Component string
MergeCommitSha string `gorm:"type:char(40)"`
Body string
common.NoPKModel
}
6 changes: 6 additions & 0 deletions plugins/github/models/github_pull_request_issue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package models

type GithubPullRequestIssue struct {
PullRequestId int `gorm:"primaryKey"`
IssueId int `gorm:"primaryKey"`
}
2 changes: 1 addition & 1 deletion plugins/github/tasks/github_api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func NewGithubApiClient(endpoint string, tokens []string, ctx context.Context, s
githubApiClient.Setup(
endpoint,
map[string]string{},
10*time.Second,
30*time.Second,
3,
scheduler,
)
Expand Down
1 change: 1 addition & 0 deletions plugins/github/tasks/github_pull_request_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ func convertGithubPullRequest(pull *GithubApiPullRequest, repoId int) (*models.G
ClosedAt: core.Iso8601TimeToTime(pull.ClosedAt),
MergedAt: core.Iso8601TimeToTime(pull.MergedAt),
MergeCommitSha: pull.MergeCommitSha,
Body: pull.Body,
}
return githubPull, nil
}
91 changes: 91 additions & 0 deletions plugins/github/tasks/github_pull_request_issue_enricher.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package tasks

import (
"context"
"github.com/merico-dev/lake/errors"
"gorm.io/gorm/clause"
"strings"

re2 "github.com/dlclark/regexp2"
"github.com/merico-dev/lake/config"
lakeModels "github.com/merico-dev/lake/models"
githubModels "github.com/merico-dev/lake/plugins/github/models"
)

var prBodyCloseRegex *re2.Regexp

func init() {
var prBodyClose = config.V.GetString("GITHUB_PR_BODY_CLOSE")
if len(prBodyClose) > 0 {
prBodyCloseRegex = re2.MustCompile(prBodyClose, 0)
} else {
prBodyCloseRegex = re2.MustCompile(`(?mi)(fix|close|resolve|fixes|closes|resolves|fixed|closed|resolved)[\s]*(pingcap\/tidb)?(issue)?( )?((#\d+[ ]?)+)`, 0)

}
}

func EnrichGithubPullRequestIssue(repoId int, ctx context.Context) (err error) {
githubPullRequst := &githubModels.GithubPullRequest{}
cursor, err := lakeModels.Db.Model(&githubPullRequst).
Where("repo_id = ?", repoId).
Rows()
if err != nil {
return err
}
defer cursor.Close()
// iterate all rows
for cursor.Next() {
select {
case <-ctx.Done():
return errors.TaskCanceled
default:
}
err = lakeModels.Db.ScanRows(cursor, githubPullRequst)
if err != nil {
return err
}
issueNumberListStr := getCloseIssueId(githubPullRequst.Body)

if issueNumberListStr == "" {
continue
}

issueNumberListStr = strings.TrimPrefix(issueNumberListStr, "#")
issueNumberList := strings.Split(issueNumberListStr, "#")
issue := &githubModels.GithubIssue{}

for _, issueNumber := range issueNumberList {
issueNumber = strings.TrimSpace(issueNumber)
err = lakeModels.Db.Where("number = ?", issueNumber).Limit(1).Find(issue).Error
if err != nil {
return err
}
if issue == nil {
continue
}
githubPullRequstIssue := &githubModels.GithubPullRequestIssue{
PullRequestId: githubPullRequst.GithubId,
IssueId: issue.GithubId,
}

err = lakeModels.Db.Clauses(
clause.OnConflict{UpdateAll: true}).Create(githubPullRequstIssue).Error
if err != nil {
return err
}
}
}

return nil
}

func getCloseIssueId(body string) string {
if prBodyCloseRegex != nil {
if m, _ := prBodyCloseRegex.FindStringMatch(body); m != nil {
if len(m.Groups()) > 2 {
return m.Groups()[len(m.Groups())-2].String()
}
}
}
return ""
}
52 changes: 52 additions & 0 deletions plugins/github/tasks/github_pull_request_issues_convertor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package tasks

import (
lakeModels "github.com/merico-dev/lake/models"
"github.com/merico-dev/lake/models/domainlayer/code"
"github.com/merico-dev/lake/models/domainlayer/didgen"
githubModels "github.com/merico-dev/lake/plugins/github/models"
"gorm.io/gorm/clause"
)

func ConvertPullRequestIssues() error {
githubPullRequestIssue := &githubModels.GithubPullRequestIssue{}
cursor, err := lakeModels.Db.Model(githubPullRequestIssue).
Select("github_pull_request_issues.*").
Order("pull_request_id ASC").
Rows()
if err != nil {
return err
}
defer cursor.Close()
domainIdGeneratorPr := didgen.NewDomainIdGenerator(&githubModels.GithubPullRequest{})
domainIdGeneratorIssue := didgen.NewDomainIdGenerator(&githubModels.GithubIssue{})
lastPrId := 0
// iterate all rows
for cursor.Next() {
err = lakeModels.Db.ScanRows(cursor, githubPullRequestIssue)
if err != nil {
return err
}
pullRequestId := domainIdGeneratorPr.Generate(githubPullRequestIssue.PullRequestId)
issueId := domainIdGeneratorIssue.Generate(githubPullRequestIssue.IssueId)
if lastPrId != githubPullRequestIssue.PullRequestId {
// Clean up old data
err := lakeModels.Db.Where("pull_request_id = ?",
pullRequestId).Delete(&code.PullRequestLabel{}).Error
if err != nil {
return err
}
lastPrId = githubPullRequestIssue.PullRequestId
}

pullRequestIssue := &code.PullRequestIssue{
PullRequestId: pullRequestId,
IssueId: issueId,
}
err = lakeModels.Db.Clauses(clause.OnConflict{DoNothing: true}).Create(pullRequestIssue).Error
if err != nil {
return err
}
}
return nil
}

0 comments on commit a674f06

Please sign in to comment.