]> source.dussan.org Git - gitea.git/commitdiff
Fix duplicate status check contexts (#30660) (#30779)
authorZettat123 <zettat123@gmail.com>
Wed, 1 May 2024 02:10:37 +0000 (10:10 +0800)
committerGitHub <noreply@github.com>
Wed, 1 May 2024 02:10:37 +0000 (02:10 +0000)
Backport #30660.

Caused by #30076.

There may be some duplicate status check contexts when setting status
checks for a branch protection rule. The duplicate contexts should be
removed.

Before:
<img

src="https://github.com/go-gitea/gitea/assets/15528715/97f4de2d-4868-47a3-8a99-5a180f9ac0a3"
width="600px" />

After:
<img

src="https://github.com/go-gitea/gitea/assets/15528715/ff7289c5-9793-4090-ba31-e8cb3c85f8a3"
width="600px" />

models/git/commit_status.go
models/git/commit_status_test.go

index c3cda7b73d0e8ba11f208b30b64c42fdc8a9bb34..d12afc42c557d8a0d665725409cf384b2895a57d 100644 (file)
@@ -397,36 +397,16 @@ func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, co
 
 // FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
 func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) {
-       type result struct {
-               Index int64
-               SHA   string
-       }
-       getBase := func() *xorm.Session {
-               return db.GetEngine(ctx).Table(&CommitStatus{}).Where("repo_id = ?", repoID)
-       }
-
        start := timeutil.TimeStampNow().AddDuration(-before)
-       results := make([]result, 0, 10)
 
-       sess := getBase().And("updated_unix >= ?", start).
-               Select("max( `index` ) as `index`, sha").
-               GroupBy("context_hash, sha").OrderBy("max( `index` ) desc")
-
-       err := sess.Find(&results)
-       if err != nil {
+       var contexts []string
+       if err := db.GetEngine(ctx).Table("commit_status").
+               Where("repo_id = ?", repoID).And("updated_unix >= ?", start).
+               Cols("context").Distinct().Find(&contexts); err != nil {
                return nil, err
        }
 
-       contexts := make([]string, 0, len(results))
-       if len(results) == 0 {
-               return contexts, nil
-       }
-
-       conds := make([]builder.Cond, 0, len(results))
-       for _, result := range results {
-               conds = append(conds, builder.Eq{"`index`": result.Index, "sha": result.SHA})
-       }
-       return contexts, getBase().And(builder.Or(conds...)).Select("context").Find(&contexts)
+       return contexts, nil
 }
 
 // NewCommitStatusOptions holds options for creating a CommitStatus
index 74ba4a10069d82e98c2088560663002b30723dbb..08eba6e2933230fc09ce51c318983415e7a3eb1c 100644 (file)
@@ -5,11 +5,15 @@ package git_test
 
 import (
        "testing"
+       "time"
 
        "code.gitea.io/gitea/models/db"
        git_model "code.gitea.io/gitea/models/git"
        repo_model "code.gitea.io/gitea/models/repo"
        "code.gitea.io/gitea/models/unittest"
+       user_model "code.gitea.io/gitea/models/user"
+       "code.gitea.io/gitea/modules/git"
+       "code.gitea.io/gitea/modules/gitrepo"
        "code.gitea.io/gitea/modules/structs"
 
        "github.com/stretchr/testify/assert"
@@ -175,3 +179,55 @@ func Test_CalcCommitStatus(t *testing.T) {
                assert.Equal(t, kase.expected, git_model.CalcCommitStatus(kase.statuses))
        }
 }
+
+func TestFindRepoRecentCommitStatusContexts(t *testing.T) {
+       assert.NoError(t, unittest.PrepareTestDatabase())
+
+       repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
+       user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
+       gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo2)
+       assert.NoError(t, err)
+       defer gitRepo.Close()
+
+       commit, err := gitRepo.GetBranchCommit(repo2.DefaultBranch)
+       assert.NoError(t, err)
+
+       defer func() {
+               _, err := db.DeleteByBean(db.DefaultContext, &git_model.CommitStatus{
+                       RepoID:    repo2.ID,
+                       CreatorID: user2.ID,
+                       SHA:       commit.ID.String(),
+               })
+               assert.NoError(t, err)
+       }()
+
+       err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{
+               Repo:    repo2,
+               Creator: user2,
+               SHA:     commit.ID,
+               CommitStatus: &git_model.CommitStatus{
+                       State:     structs.CommitStatusFailure,
+                       TargetURL: "https://example.com/tests/",
+                       Context:   "compliance/lint-backend",
+               },
+       })
+       assert.NoError(t, err)
+
+       err = git_model.NewCommitStatus(db.DefaultContext, git_model.NewCommitStatusOptions{
+               Repo:    repo2,
+               Creator: user2,
+               SHA:     commit.ID,
+               CommitStatus: &git_model.CommitStatus{
+                       State:     structs.CommitStatusSuccess,
+                       TargetURL: "https://example.com/tests/",
+                       Context:   "compliance/lint-backend",
+               },
+       })
+       assert.NoError(t, err)
+
+       contexts, err := git_model.FindRepoRecentCommitStatusContexts(db.DefaultContext, repo2.ID, time.Hour)
+       assert.NoError(t, err)
+       if assert.Len(t, contexts, 1) {
+               assert.Equal(t, "compliance/lint-backend", contexts[0])
+       }
+}