mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-03 21:08:25 +00:00 
			
		
		
		
	Fix duplicate status check contexts (#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" />
This commit is contained in:
		@@ -397,36 +397,16 @@ func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, co
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
 | 
					// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
 | 
				
			||||||
func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) {
 | 
					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)
 | 
						start := timeutil.TimeStampNow().AddDuration(-before)
 | 
				
			||||||
	results := make([]result, 0, 10)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sess := getBase().And("updated_unix >= ?", start).
 | 
						var contexts []string
 | 
				
			||||||
		Select("max( `index` ) as `index`, sha").
 | 
						if err := db.GetEngine(ctx).Table("commit_status").
 | 
				
			||||||
		GroupBy("context_hash, sha").OrderBy("max( `index` ) desc")
 | 
							Where("repo_id = ?", repoID).And("updated_unix >= ?", start).
 | 
				
			||||||
 | 
							Cols("context").Distinct().Find(&contexts); err != nil {
 | 
				
			||||||
	err := sess.Find(&results)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	contexts := make([]string, 0, len(results))
 | 
						return contexts, nil
 | 
				
			||||||
	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)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewCommitStatusOptions holds options for creating a CommitStatus
 | 
					// NewCommitStatusOptions holds options for creating a CommitStatus
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,15 @@ package git_test
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
	git_model "code.gitea.io/gitea/models/git"
 | 
						git_model "code.gitea.io/gitea/models/git"
 | 
				
			||||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
						repo_model "code.gitea.io/gitea/models/repo"
 | 
				
			||||||
	"code.gitea.io/gitea/models/unittest"
 | 
						"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"
 | 
						"code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"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))
 | 
							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])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user