Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync issues, PRs, labels, milestones, comments from GitHub mirrors #20311

Open
wants to merge 136 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
6f51310
Define interfaces syncing new issues/PRs
harryzcy Jul 10, 2022
2bcb4c9
Support getting new issues from github
harryzcy Jul 10, 2022
c54aa4e
Put issue reactions code in a seperate function
harryzcy Jul 10, 2022
8532fa3
Rename function to getIssueReactions
harryzcy Jul 10, 2022
ad8eb2b
Support getting new PRs from github
harryzcy Jul 10, 2022
40c3b32
Fix issue that new PRs not returned
harryzcy Jul 10, 2022
039e505
Allow migration items with mirroring for GitHub
harryzcy Jul 11, 2022
a3ca5b0
Fix a comment
harryzcy Jul 11, 2022
176009e
Create relevant functions for uploader
harryzcy Jul 11, 2022
698d6be
Optimize topics creation and updates
harryzcy Jul 11, 2022
fb82294
Support updating labels
harryzcy Jul 12, 2022
22835e4
Fix error not returned error
harryzcy Jul 12, 2022
98a8e69
Update Uploader interface
harryzcy Jul 12, 2022
7b7b166
Support updating issues
harryzcy Jul 12, 2022
0932caa
Some cleanups
harryzcy Jul 12, 2022
5ffadeb
Support updating pull requests
harryzcy Jul 12, 2022
6d24299
Support updating milestones
harryzcy Jul 12, 2022
faa0d0b
Fix milestone migrations
harryzcy Jul 12, 2022
5895807
Fix: exec sql with session
harryzcy Jul 13, 2022
b96fe66
Fix test
harryzcy Jul 13, 2022
696f58f
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Jul 13, 2022
8127c25
Provide preliminary implementation for releases
harryzcy Jul 14, 2022
07ba080
Support updating comments
harryzcy Jul 14, 2022
9892ae1
Add closed date to milestones
harryzcy Jul 15, 2022
97d47b2
Fix xorm usage
harryzcy Jul 15, 2022
9f5721f
Revert previous change
harryzcy Jul 15, 2022
9ac5518
Fix issue updates
harryzcy Jul 15, 2022
2ae6e4c
Add sync repository function
harryzcy Jul 16, 2022
06cc290
Get new comments/reviews
harryzcy Jul 16, 2022
aa7f59e
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Jul 16, 2022
5b1c73e
Allow syncing with mirror option checked
harryzcy Jul 16, 2022
f627311
Display pull request for mirror repo
harryzcy Jul 16, 2022
9ee3ba5
Disable issue on mirror repo
harryzcy Jul 16, 2022
5a1dda4
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Jul 19, 2022
4f67c5d
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Jul 21, 2022
bbd4648
Add sync items to Mirror struct
harryzcy Jul 22, 2022
a0303a2
Support syncing reviews
harryzcy Jul 22, 2022
8874bf5
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jul 22, 2022
dd20d7d
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Aug 22, 2022
c733415
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 6, 2023
73a5a7c
Fix lint issue caused by merge
harryzcy Apr 6, 2023
12851f2
Avoid duplicate code
harryzcy Apr 6, 2023
e3a16ff
Fix SPDX-License-Identifier
harryzcy Apr 6, 2023
e7b9e02
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 6, 2023
1c8b8ef
Add comments
harryzcy Apr 6, 2023
9af6292
Fix error when syncing comments when PR is not synced
harryzcy Apr 6, 2023
acd0ad2
CheckAndEnsureSafePR was ignored when merging
harryzcy Apr 6, 2023
6b8300f
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 8, 2023
9887d8d
Fix download pr tests
harryzcy Apr 8, 2023
8481bcf
Correctly format ISO 8601 time
harryzcy Apr 8, 2023
448ccfd
Update comments
harryzcy Apr 8, 2023
8fb9956
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 8, 2023
786d15f
Fix a sql query
harryzcy Apr 9, 2023
a2df3f1
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 22, 2023
d9cfdb1
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 22, 2023
b5edfea
Merge branch 'main' into sync-issue-pr-and-more
harryzcy May 3, 2023
e50ab38
Fix lint
harryzcy May 4, 2023
d83b2ef
Merge branch 'main' into sync-issue-pr-and-more
harryzcy May 6, 2023
15d16a5
Identify the right place to do continuous sync
harryzcy May 6, 2023
ce51877
Sync mirror after migration
harryzcy May 6, 2023
78945eb
Enable github sync flag and fix panics
harryzcy May 6, 2023
a3a4015
Correctly store mirror setting in migration
harryzcy May 6, 2023
b8f8ab4
Fix: don't delete repo when sync failed
harryzcy May 7, 2023
de2f2a7
Fix error when syncing milestones
harryzcy May 7, 2023
3a72ed9
Update label identification method
harryzcy May 7, 2023
ef82e4e
Fix lint
harryzcy May 7, 2023
244c263
Merge branch 'main' into sync-issue-pr-and-more
harryzcy May 8, 2023
e52964c
Use correct last synced time
harryzcy May 15, 2023
82fe9d5
Correctly get issue id
harryzcy May 15, 2023
81cf9fc
Fix PR request sync issue
harryzcy May 16, 2023
994da85
Merge branch 'main' into sync-issue-pr-and-more
harryzcy May 16, 2023
6855c81
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jun 24, 2023
6e3b980
Add OriginalID for milestones
harryzcy Jun 24, 2023
186a9a9
Add OriginalID to comments
harryzcy Jun 24, 2023
837c09e
Update comment for label struct
harryzcy Jun 24, 2023
b094125
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jul 21, 2023
cbed118
Add OriginalID to Release
harryzcy Jul 21, 2023
2b31c33
Won't hit rate limit with github actions
harryzcy Jul 21, 2023
3d9b7ed
Fix: include originalID in getAllCommentsSince
harryzcy Jul 22, 2023
f7e9422
Identify comment by original_id only
harryzcy Jul 22, 2023
328fdaf
Add OriginalID to reviews and review comments
harryzcy Jul 22, 2023
78a00af
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jul 22, 2023
87c9238
Enable TestGiteaUploadRepo only when token
harryzcy Jul 22, 2023
a48b1f3
Fix: update all cols including false boolean value
harryzcy Jul 22, 2023
0fedce2
Comment out code that cause bug with releases
harryzcy Jul 22, 2023
d8c0634
Another place to comment out
harryzcy Jul 22, 2023
7406559
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jul 22, 2023
26b2fd9
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jul 24, 2023
0b50deb
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Aug 22, 2023
bcb8866
Temp disable fast tag syncing for mirrors
harryzcy Aug 22, 2023
80a9877
Refactor release syncing
harryzcy Aug 22, 2023
c535198
Refactor again
harryzcy Aug 23, 2023
6c99fbb
Fix bug
harryzcy Aug 23, 2023
e199b95
Flip bool and add comments
harryzcy Aug 23, 2023
7511099
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Aug 23, 2023
5169422
Make some error messages lowercased
harryzcy Aug 23, 2023
36c2378
Expose context
harryzcy Aug 24, 2023
35ab3bb
No magic literal
harryzcy Aug 24, 2023
4d2cb07
Add comments for OriginalID
harryzcy Aug 24, 2023
6962c14
Update log text
harryzcy Aug 24, 2023
4a33b2a
Revert sync wiki setting check
harryzcy Aug 24, 2023
884cb6d
Default sync items setting to false
harryzcy Aug 24, 2023
775af9e
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Aug 24, 2023
fa40aa7
Expose one more context
harryzcy Aug 24, 2023
2a66750
Update comment
harryzcy Aug 24, 2023
d2ef14c
Plural
harryzcy Aug 24, 2023
9bfd3e3
Expose more context
harryzcy Aug 24, 2023
e39d0ff
Fix a comment issue and early return for prs
harryzcy Aug 24, 2023
ee77675
Fix comment sync error
harryzcy Aug 25, 2023
eacc3ed
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Sep 15, 2023
197489b
Fix lint
harryzcy Sep 16, 2023
049faf8
Somehow git merge didn't delete this file
harryzcy Sep 16, 2023
e28fa78
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Sep 18, 2023
99f9102
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Sep 24, 2023
3b8291f
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Oct 29, 2023
065469c
Fix functions that gets moved in #26969
harryzcy Oct 29, 2023
4886e18
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Nov 4, 2023
218c8f5
Remove unnecessary variables
harryzcy Nov 8, 2023
3103563
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Nov 21, 2023
079814f
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Dec 8, 2023
71dfb67
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jan 3, 2024
a9247f9
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jan 14, 2024
079ea08
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Jan 18, 2024
323215f
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Feb 6, 2024
77fd657
Fix build issues from merge
harryzcy Feb 6, 2024
18fffc0
Apply suggestion
harryzcy Feb 26, 2024
a52447b
Merge remote-tracking branch 'upstream/main' into sync-issue-pr-and-more
harryzcy Feb 26, 2024
e677d96
Avoid jquery
harryzcy Feb 26, 2024
db4aa34
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Feb 27, 2024
b143f4a
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Mar 2, 2024
e8119df
Fix build errors
harryzcy Mar 2, 2024
df0a535
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Mar 9, 2024
e2aaa1a
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 26, 2024
cee300a
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 27, 2024
d706aa5
Change `interface{}` to `any`
harryzcy Apr 27, 2024
8211411
Merge branch 'main' into sync-issue-pr-and-more
harryzcy Apr 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/admin.go
Expand Up @@ -135,7 +135,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
}
log.Trace(" currentNumReleases is %d, running SyncReleasesWithTags", oldnum)

if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo); err != nil {
if err = repo_module.SyncReleasesWithTags(ctx, repo, gitRepo, false); err != nil {
log.Warn(" SyncReleasesWithTags: %v", err)
gitRepo.Close()
continue
Expand Down
75 changes: 75 additions & 0 deletions models/issues/comment.go
Expand Up @@ -228,6 +228,7 @@ type Comment struct {
Poster *user_model.User `xorm:"-"`
OriginalAuthor string
OriginalAuthorID int64
OriginalID int64 // Only used in synced comments
IssueID int64 `xorm:"INDEX"`
Issue *Issue `xorm:"-"`
LabelID int64
Expand Down Expand Up @@ -1305,3 +1306,77 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error {
}
return committer.Commit()
}

// UpsertIssueComments inserts many comments of issues.
func UpsertIssueComments(ctx context.Context, comments []*Comment) error {
if len(comments) == 0 {
return nil
}

issueIDs := make(map[int64]bool)
for _, comment := range comments {
issueIDs[comment.IssueID] = true
}

return db.WithTx(ctx, func(ctx context.Context) error {
sess := db.GetEngine(ctx)
for _, comment := range comments {
exists, err := sess.Exist(&Comment{
IssueID: comment.IssueID,
OriginalID: comment.OriginalID,
})
if err != nil {
return err
}
if !exists {
if _, err := sess.NoAutoTime().Insert(comment); err != nil {
return err
}
} else {
if _, err := sess.NoAutoTime().Where(
"issue_id = ? AND original_id = ?", comment.IssueID, comment.OriginalID,
).AllCols().Update(comment); err != nil {
return err
}
}

for _, reaction := range comment.Reactions {
reaction.IssueID = comment.IssueID
reaction.CommentID = comment.ID
}
if len(comment.Reactions) > 0 {
for _, reaction := range comment.Reactions {
// issue comment reaction is uniquely identified by issue_id, comment_id and type
exists, err := sess.Exist(&Reaction{
IssueID: reaction.IssueID,
CommentID: reaction.CommentID,
Type: reaction.Type,
})
if err != nil {
return err
}
if exists {
if _, err := sess.Where(
"issue_id = ? AND comment_id = ? AND type = ?",
reaction.IssueID, reaction.CommentID, reaction.Type,
).AllCols().Update(&reaction); err != nil {
return err
}
} else {
if _, err := sess.Insert(&reaction); err != nil {
return err
}
}
}
}
}

for issueID := range issueIDs {
if _, err := db.Exec(ctx, "UPDATE issue SET num_comments = (SELECT count(*) FROM comment WHERE issue_id = ? AND `type`=?) WHERE id = ?",
issueID, CommentTypeComment, issueID); err != nil {
return err
}
}
return nil
})
}
78 changes: 78 additions & 0 deletions models/issues/issue.go
Expand Up @@ -909,3 +909,81 @@ func insertIssue(ctx context.Context, issue *Issue) error {

return nil
}

// UpsertIssues creates new issues and updates existing issues in database
func UpsertIssues(ctx context.Context, issues ...*Issue) error {
return db.WithTx(ctx, func(ctx context.Context) error {
for _, issue := range issues {
if _, err := upsertIssue(ctx, issue); err != nil {
return err
}
}
return nil
})
}

func upsertIssue(ctx context.Context, issue *Issue) (isInsert bool, err error) {
sess := db.GetEngine(ctx)
has, err := sess.Table("issue").Where("repo_id = ? AND `index` = ?", issue.RepoID, issue.Index).Cols("id").Get(&issue.ID)
if err != nil {
return false, err
}
if !has {
return true, insertIssue(ctx, issue)
}
return false, updateIssue(ctx, issue)
}

func updateIssue(ctx context.Context, issue *Issue) error {
sess := db.GetEngine(ctx)
if _, err := sess.NoAutoTime().ID(issue.ID).AllCols().Update(issue); err != nil {
return err
}
issueLabels := resolveIssueLabels(issue.ID, issue.Labels)
if len(issueLabels) > 0 {
// delete old labels
if _, err := sess.Table("issue_label").Where("issue_id = ?", issue.ID).Delete(); err != nil {
return err
}
// insert new labels
if _, err := sess.Insert(issueLabels); err != nil {
return err
}
}

for _, reaction := range issue.Reactions {
reaction.IssueID = issue.ID
}

if len(issue.Reactions) > 0 {
// update existing reactions and insert new ones
for _, reaction := range issue.Reactions {
exists, err := sess.Exist(&Reaction{ID: reaction.ID})
if err != nil {
return err
}
if exists {
if _, err := sess.ID(reaction.ID).AllCols().Update(&reaction); err != nil {
return err
}
} else {
if _, err := sess.Insert(&reaction); err != nil {
return err
}
}
}
}

return nil
}

func resolveIssueLabels(issueID int64, labels []*Label) []IssueLabel {
issueLabels := make([]IssueLabel, 0, len(labels))
for _, label := range labels {
issueLabels = append(issueLabels, IssueLabel{
IssueID: issueID,
LabelID: label.ID,
})
}
return issueLabels
}
65 changes: 65 additions & 0 deletions models/issues/label.go
Expand Up @@ -92,6 +92,8 @@ type Label struct {
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

OriginalID int64 // Only for migrating data from other system, used for syncing

NumOpenIssues int `xorm:"-"`
NumOpenRepoIssues int64 `xorm:"-"`
IsChecked bool `xorm:"-"`
Expand Down Expand Up @@ -390,6 +392,69 @@ func GetLabelsByRepoID(ctx context.Context, repoID int64, sortType string, listO
return labels, sess.Find(&labels)
}

// UpdateLabelsByRepoID adds, updates, and deletes relevant labels for the given repository.
func UpdateLabelsByRepoID(ctx context.Context, repoID int64, labels ...*Label) error {
return db.WithTx(ctx, func(ctx context.Context) error {
existingLabels, err := GetLabelsByRepoID(ctx, repoID, "", db.ListOptions{})
if err != nil {
return err
}
labelsToAdd := make([]*Label, 0)
labelsToUpdate := make([]*Label, 0)
labelsToDelete := make([]*Label, 0)

for _, l := range labels {
var foundLabel *Label
for _, existingLabel := range existingLabels {
if existingLabel.OriginalID == l.OriginalID {
foundLabel = existingLabel
break
}
}

if foundLabel == nil {
labelsToAdd = append(labelsToAdd, l)
} else if foundLabel.Name != l.Name || foundLabel.Description != l.Description ||
foundLabel.Color != l.Color {
l.RepoID = repoID
labelsToUpdate = append(labelsToUpdate, l)
}
}

for _, existingLabel := range existingLabels {
found := false
for _, label := range labels {
if label.OriginalID == existingLabel.OriginalID {
found = true
break
}
}
if !found {
labelsToDelete = append(labelsToDelete, existingLabel)
}
}

for _, l := range labelsToAdd {
if err = NewLabel(ctx, l); err != nil {
return err
}
}

for _, l := range labelsToUpdate {
if err = UpdateLabel(ctx, l); err != nil {
return err
}
}

for _, l := range labelsToDelete {
if err = DeleteLabel(ctx, repoID, l.ID); err != nil {
return err
}
}
return nil
})
}

// CountLabelsByRepoID count number of all labels that belong to given repository by ID.
func CountLabelsByRepoID(ctx context.Context, repoID int64) (int64, error) {
return db.GetEngine(ctx).Where("repo_id = ?", repoID).Count(&Label{})
Expand Down
84 changes: 84 additions & 0 deletions models/issues/milestone.go
Expand Up @@ -65,6 +65,8 @@ type Milestone struct {
DeadlineString string `xorm:"-"`

TotalTrackedTime int64 `xorm:"-"`

OriginalID int64 // ID from the upstream syncing source
}

func init() {
Expand Down Expand Up @@ -380,3 +382,85 @@ func InsertMilestones(ctx context.Context, ms ...*Milestone) (err error) {
}
return committer.Commit()
}

// UpdateMilestones updates milestones of repository.
func UpdateMilestones(ctx context.Context, ms ...*Milestone) (err error) {
if len(ms) == 0 {
return nil
}

return db.WithTx(ctx, func(ctx context.Context) error {
sess := db.GetEngine(ctx)

// get existing milestones
existingMilestones := make([]*Milestone, 0)
if err = sess.Where("repo_id = ?", ms[0].RepoID).Find(&existingMilestones); err != nil {
return err
}

milestonesToAdd := make([]*Milestone, 0)
milestonesToUpdate := make([]*Milestone, 0)
milestonesToDelete := make([]*Milestone, 0)
foundMap := make(map[int64]bool)

openCount := 0
closedCount := 0

for _, m := range ms {
var foundMilestone *Milestone
for _, existingMilestone := range existingMilestones {
if existingMilestone.OriginalID == m.OriginalID {
foundMilestone = existingMilestone
foundMap[existingMilestone.ID] = true
break
}
}

if foundMilestone == nil {
milestonesToAdd = append(milestonesToAdd, m)
} else if foundMilestone.OriginalID != m.OriginalID {
m.ID = foundMilestone.ID
milestonesToUpdate = append(milestonesToUpdate, m)
}

if m.IsClosed {
closedCount++
} else {
openCount++
}
}

for _, existingMilestone := range existingMilestones {
if _, exist := foundMap[existingMilestone.ID]; !exist {
milestonesToDelete = append(milestonesToDelete, existingMilestone)
}
}

if len(milestonesToAdd) > 0 {
if _, err = sess.Insert(milestonesToAdd); err != nil {
return err
}
}

for _, m := range milestonesToUpdate {
if _, err = sess.ID(m.ID).AllCols().Update(m); err != nil {
return err
}
}

for _, m := range milestonesToDelete {
if _, err = sess.ID(m.ID).Delete(m); err != nil {
return err
}
}

if _, err = sess.ID(ms[0].RepoID).Update(&repo_model.Repository{
NumMilestones: len(ms),
NumOpenMilestones: openCount,
NumClosedMilestones: closedCount,
}); err != nil {
return err
}
return nil
})
}
29 changes: 29 additions & 0 deletions models/issues/pull.go
Expand Up @@ -1046,6 +1046,35 @@ func InsertPullRequests(ctx context.Context, prs ...*PullRequest) error {
return committer.Commit()
}

// UpsertPullRequests inserts new pull requests and updates existing pull requests in database
func UpsertPullRequests(ctx context.Context, prs ...*PullRequest) error {
if len(prs) == 0 {
return nil
}

return db.WithTx(ctx, func(ctx context.Context) error {
sess := db.GetEngine(ctx)
for _, pr := range prs {
isInsert, err := upsertIssue(ctx, pr.Issue)
if err != nil {
return err
}
pr.IssueID = pr.Issue.ID

if isInsert {
if _, err := sess.NoAutoTime().Insert(pr); err != nil {
return err
}
} else {
if _, err := sess.NoAutoTime().ID(pr.ID).AllCols().Update(pr); err != nil {
return err
}
}
}
return nil
})
}

// GetPullRequestByMergedCommit returns a merged pull request by the given commit
func GetPullRequestByMergedCommit(ctx context.Context, repoID int64, sha string) (*PullRequest, error) {
pr := new(PullRequest)
Expand Down