diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 81783bbf858..381f35b2e8a 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -15,8 +15,12 @@ import ( asymkey_model "gitea.dev/models/asymkey" "gitea.dev/models/db" + access_model "gitea.dev/models/perm/access" repo_model "gitea.dev/models/repo" + "gitea.dev/models/unit" user_model "gitea.dev/models/user" + "gitea.dev/modules/cache" + "gitea.dev/modules/cachegroup" "gitea.dev/modules/commitstatus" "gitea.dev/modules/git" "gitea.dev/modules/log" @@ -213,8 +217,8 @@ func (status *CommitStatus) LocaleString(lang translation.Locale) string { return lang.TrString("repo.commitstatus." + status.State.String()) } -// HideActionsURL set `TargetURL` to an empty string if the status comes from Gitea Actions -func (status *CommitStatus) HideActionsURL(ctx context.Context) { +// hideActionsURL set `TargetURL` to an empty string if the status comes from Gitea Actions +func (status *CommitStatus) hideActionsURL(ctx context.Context) { if _, ok := status.cutTargetURLGiteaActionsPrefix(ctx); ok { status.TargetURL = "" } @@ -544,18 +548,38 @@ func HashCommitStatusContext(context string) string { return fmt.Sprintf("%x", sha1.Sum([]byte(context))) } -// CommitStatusesHideActionsURL hide Gitea Actions urls -func CommitStatusesHideActionsURL(ctx context.Context, statuses []*CommitStatus) { - idToRepos := make(map[int64]*repo_model.Repository) +// CommitStatusesApplyDoerPermission hides the Gitea Actions url of every status whose repository +// the doer cannot read the Actions unit of, so the "Details" link does not lead to a 404. +func CommitStatusesApplyDoerPermission(ctx context.Context, doer *user_model.User, statuses []*CommitStatus) { for _, status := range statuses { - if status == nil { - continue + if status != nil && !statusRepoCanReadActions(ctx, doer, status) { + status.hideActionsURL(ctx) } - - if status.Repo == nil { - status.Repo = idToRepos[status.RepoID] - } - status.HideActionsURL(ctx) - idToRepos[status.RepoID] = status.Repo } } + +// SignCommitsApplyDoerPermission is CommitStatusesApplyDoerPermission for a list of commits. +func SignCommitsApplyDoerPermission(ctx context.Context, doer *user_model.User, commits []*SignCommitWithStatuses) { + var statuses []*CommitStatus + for _, commit := range commits { + statuses = append(statuses, commit.Status) + statuses = append(statuses, commit.Statuses...) + } + CommitStatusesApplyDoerPermission(ctx, doer, statuses) +} + +func statusRepoCanReadActions(ctx context.Context, doer *user_model.User, status *CommitStatus) bool { + perm, err := cache.GetWithContextCache(ctx, cachegroup.RepoUserPermission, access_model.RepoUserPermissionCacheKey(status.RepoID, doer), + func(ctx context.Context, _ string) (access_model.Permission, error) { // only runs on a cache miss + if err := status.loadRepository(ctx); err != nil { + return access_model.Permission{}, err + } + return access_model.GetDoerRepoPermission(ctx, status.Repo, doer) + }, + ) + if err != nil { + log.Error("GetDoerRepoPermission[%d]: %v", status.RepoID, err) + return false + } + return perm.CanRead(unit.TypeActions) +} diff --git a/models/git/commit_status_test.go b/models/git/commit_status_test.go index 411dd91f73b..86967c1bce8 100644 --- a/models/git/commit_status_test.go +++ b/models/git/commit_status_test.go @@ -4,11 +4,9 @@ package git_test import ( - "fmt" "testing" "time" - actions_model "gitea.dev/models/actions" "gitea.dev/models/db" git_model "gitea.dev/models/git" repo_model "gitea.dev/models/repo" @@ -233,17 +231,23 @@ func TestFindRepoRecentCommitStatusContexts(t *testing.T) { } } -func TestCommitStatusesHideActionsURL(t *testing.T) { +func TestCommitStatusesApplyDoerPermission(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) + // repo4 is public and has the actions unit, repo2 is private and owned by someone else repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - run := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{ID: 791, RepoID: repo.ID}) - assert.NoError(t, run.LoadAttributes(t.Context())) + otherRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + visibleURL := repo.Link() + "/actions/runs/1/jobs/1" statuses := []*git_model.CommitStatus{ { RepoID: repo.ID, - TargetURL: fmt.Sprintf("%s/jobs/%d", run.Link(), run.ID), + TargetURL: visibleURL, + }, + { + RepoID: otherRepo.ID, + TargetURL: otherRepo.Link() + "/actions/runs/1/jobs/1", }, { RepoID: repo.ID, @@ -251,9 +255,10 @@ func TestCommitStatusesHideActionsURL(t *testing.T) { }, } - git_model.CommitStatusesHideActionsURL(t.Context(), statuses) - assert.Empty(t, statuses[0].TargetURL) - assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL) + git_model.CommitStatusesApplyDoerPermission(t.Context(), doer, statuses) + assert.Equal(t, visibleURL, statuses[0].TargetURL) + assert.Empty(t, statuses[1].TargetURL) + assert.Equal(t, "https://mycicd.org/1", statuses[2].TargetURL) } func TestGetCountLatestCommitStatus(t *testing.T) { diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index ee06ca3c504..a59838c4fa9 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -658,6 +658,16 @@ func PermissionNoAccess() Permission { return Permission{AccessMode: perm_model.AccessModeNone} } +// RepoUserPermissionCacheKey is the cachegroup.RepoUserPermission key of a doer's +// permission on a repository. Producers and consumers must agree on it, so it lives here. +func RepoUserPermissionCacheKey(repoID int64, doer *user_model.User) string { + var doerID int64 + if doer != nil { + doerID = doer.ID + } + return fmt.Sprintf("%d-%d", repoID, doerID) +} + // CanReadWorkflowCrossRepo checks whether the run can read workflow files from targetRepo. func CanReadWorkflowCrossRepo(ctx context.Context, targetRepo *repo_model.Repository, run *actions_model.ActionRun) (bool, error) { if err := run.LoadRepo(ctx); err != nil { diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index d415fa86a51..22660fd428c 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -70,14 +70,10 @@ func Branches(ctx *context.Context) { ctx.ServerError("LoadBranches", err) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - for key := range commitStatuses { - git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) - } - } commitStatus := make(map[string]*git_model.CommitStatus) for commitID, cs := range commitStatuses { + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, cs) commitStatus[commitID] = git_model.CalcCommitStatus(cs) } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index ecd4bba4d54..af4d40f5d1b 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -17,7 +17,6 @@ import ( issues_model "gitea.dev/models/issues" "gitea.dev/models/renderhelper" repo_model "gitea.dev/models/repo" - unit_model "gitea.dev/models/unit" user_model "gitea.dev/models/user" "gitea.dev/modules/base" "gitea.dev/modules/fileicon" @@ -388,9 +387,7 @@ func Diff(ctx *context.Context) { if err != nil { log.Error("GetLatestCommitStatus: %v", err) } - if !ctx.Repo.Permission.CanRead(unit_model.TypeActions) { - git_model.CommitStatusesHideActionsURL(ctx, statuses) - } + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, statuses) ctx.Data["CommitStatus"] = git_model.CalcCommitStatus(statuses) ctx.Data["CommitStatuses"] = statuses @@ -466,14 +463,6 @@ func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) ([]*git_m if err != nil { return nil, err } - if !ctx.Repo.Permission.CanRead(unit_model.TypeActions) { - for _, commit := range commits { - if commit.Status == nil { - continue - } - commit.Status.HideActionsURL(ctx) - git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses) - } - } + git_model.SignCommitsApplyDoerPermission(ctx, ctx.Doer, commits) return commits, nil } diff --git a/routers/web/repo/issue_list.go b/routers/web/repo/issue_list.go index 3942eeb07e4..4a4e8a9f9c5 100644 --- a/routers/web/repo/issue_list.go +++ b/routers/web/repo/issue_list.go @@ -13,11 +13,9 @@ import ( "strings" "gitea.dev/models/db" - git_model "gitea.dev/models/git" issues_model "gitea.dev/models/issues" "gitea.dev/models/organization" repo_model "gitea.dev/models/repo" - "gitea.dev/models/unit" user_model "gitea.dev/models/user" issue_indexer "gitea.dev/modules/indexer/issues" db_indexer "gitea.dev/modules/indexer/issues/db" @@ -640,16 +638,11 @@ func prepareIssueFilterAndList(ctx *context.Context, milestoneID int64, projectI } } - commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, issues) + commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, ctx.Doer, issues) if err != nil { ctx.ServerError("GetIssuesAllCommitStatus", err) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - for key := range commitStatuses { - git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) - } - } if err := issues.LoadAttributes(ctx); err != nil { ctx.ServerError("issues.LoadAttributes", err) diff --git a/routers/web/repo/issue_view.go b/routers/web/repo/issue_view.go index 8911b038764..203b40c3303 100644 --- a/routers/web/repo/issue_view.go +++ b/routers/web/repo/issue_view.go @@ -794,15 +794,7 @@ func prepareIssueViewCommentsAndSidebarParticipants(ctx *context.Context, issue ctx.ServerError("LoadCommentPushCommits", err) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - for _, commit := range comment.Commits { - if commit.Status == nil { - continue - } - commit.Status.HideActionsURL(ctx) - git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses) - } - } + git_model.SignCommitsApplyDoerPermission(ctx, ctx.Doer, comment.Commits) } else if comment.Type == issues_model.CommentTypeAddTimeManual || comment.Type == issues_model.CommentTypeStopTracking || comment.Type == issues_model.CommentTypeDeleteTimeManual { diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 8ee80a8b3fe..87efc3091b7 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -432,9 +432,7 @@ func (prInfo *pullRequestViewInfo) prepareMergeBoxStatusCheckData(ctx *context.C } data.hasRequiredStatusContexts = len(requiredContexts) > 0 - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - git_model.CommitStatusesHideActionsURL(ctx, commitStatuses) - } + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, commitStatuses) combinedCommitStatus := git_model.CalcCommitStatus(commitStatuses) statusCheckData.ApproveLink = fmt.Sprintf("%s/actions/approve-all-checks?commit_id=%s", ctx.Repo.Repository.Link(), headCommitID) statusCheckData.PullCommitStatuses = commitStatuses diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 09a535b3071..c3d7c20424b 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -97,11 +97,12 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions) } var ok bool - canReadActions := ctx.Repo.Permission.CanRead(unit.TypeActions) + // statuses describe the tagged code, and unlike the other pages showing them this one is not behind the code unit + canReadCode := ctx.Repo.Permission.CanRead(unit.TypeCode) // Bulk-load commit statuses for all releases in one query. var commitStatusMap map[string][]*git_model.CommitStatus - if canReadActions && len(releases) > 0 { + if canReadCode && len(releases) > 0 { shas := make([]string, 0, len(releases)) for _, r := range releases { shas = append(shas, r.Sha1) @@ -140,8 +141,9 @@ func getReleaseInfos(ctx *context.Context, opts *repo_model.FindReleasesOptions) Release: r, } - if canReadActions { + if canReadCode { statuses := commitStatusMap[r.Sha1] + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, statuses) info.CommitStatus = git_model.CalcCommitStatus(statuses) info.CommitStatuses = statuses } diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 2e195dd32da..43fb14c2d95 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -526,9 +526,7 @@ func SearchRepo(ctx *context.Context) { ctx.JSON(http.StatusInternalServerError, nil) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - git_model.CommitStatusesHideActionsURL(ctx, latestCommitStatuses) - } + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, latestCommitStatuses) results := make([]*repo_service.WebSearchRepository, len(repos)) for i, repo := range repos { diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 0867263a0b3..6f28d6c495a 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -143,9 +143,7 @@ func loadLatestCommitData(ctx *context.Context, latestCommit *git.Commit) bool { if err != nil { log.Error("GetLatestCommitStatus: %v", err) } - if !ctx.Repo.Permission.CanRead(unit_model.TypeActions) { - git_model.CommitStatusesHideActionsURL(ctx, statuses) - } + git_model.CommitStatusesApplyDoerPermission(ctx, ctx.Doer, statuses) ctx.Data["LatestCommitStatus"] = git_model.CalcCommitStatus(statuses) ctx.Data["LatestCommitStatuses"] = statuses diff --git a/routers/web/user/home.go b/routers/web/user/home.go index ffe3106c331..73f8f3aba09 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -17,7 +17,6 @@ import ( activities_model "gitea.dev/models/activities" asymkey_model "gitea.dev/models/asymkey" "gitea.dev/models/db" - git_model "gitea.dev/models/git" issues_model "gitea.dev/models/issues" "gitea.dev/models/organization" "gitea.dev/models/renderhelper" @@ -554,16 +553,11 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) { } } - commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, issues) + commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, ctx.Doer, issues) if err != nil { ctx.ServerError("GetIssuesLastCommitStatus", err) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - for key := range commitStatuses { - git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) - } - } // ------------------------------- // Fill stats to post to ctx.Data. diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index 11bb5ec3eed..31387ac992b 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -11,11 +11,9 @@ import ( activities_model "gitea.dev/models/activities" "gitea.dev/models/db" - git_model "gitea.dev/models/git" issues_model "gitea.dev/models/issues" access_model "gitea.dev/models/perm/access" repo_model "gitea.dev/models/repo" - "gitea.dev/models/unit" user_model "gitea.dev/models/user" "gitea.dev/modules/base" "gitea.dev/modules/container" @@ -268,16 +266,11 @@ func NotificationSubscriptions(ctx *context.Context) { return } - commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, issues) + commitStatuses, lastStatus, err := pull_service.GetIssuesAllCommitStatus(ctx, ctx.Doer, issues) if err != nil { ctx.ServerError("GetIssuesAllCommitStatus", err) return } - if !ctx.Repo.Permission.CanRead(unit.TypeActions) { - for key := range commitStatuses { - git_model.CommitStatusesHideActionsURL(ctx, commitStatuses[key]) - } - } ctx.Data["CommitLastStatus"] = lastStatus ctx.Data["CommitStatuses"] = commitStatuses ctx.Data["Issues"] = issues diff --git a/services/context/repo.go b/services/context/repo.go index ecb8e8d74a7..1c945dea5d2 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -24,6 +24,7 @@ import ( user_model "gitea.dev/models/user" "gitea.dev/modules/base" "gitea.dev/modules/cache" + "gitea.dev/modules/cachegroup" "gitea.dev/modules/git" "gitea.dev/modules/httplib" code_indexer "gitea.dev/modules/indexer/code" @@ -427,6 +428,10 @@ func repoAssignmentLegacy(ctx *Context, data *repoAssignmentPrepareDataStruct) { return } } + // publish it so code resolving the same permission later in this request reuses it + if c := cache.GetContextCache(ctx); c != nil { + c.Put(cachegroup.RepoUserPermission, access_model.RepoUserPermissionCacheKey(repo.ID, ctx.Doer), ctx.Repo.Permission) + } if !ctx.Repo.Permission.HasAnyUnitAccessOrPublicAccess() && !canWriteAsMaintainer(ctx) { if ctx.FormString("go-get") == "1" { diff --git a/services/convert/pull.go b/services/convert/pull.go index 26db895126a..ba564474f37 100644 --- a/services/convert/pull.go +++ b/services/convert/pull.go @@ -5,7 +5,6 @@ package convert import ( "context" - "fmt" git_model "gitea.dev/models/git" issues_model "gitea.dev/models/issues" @@ -55,12 +54,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u return nil } - var doerID int64 - if doer != nil { - doerID = doer.ID - } - - repoUserPerm, err := cache.GetWithContextCache(ctx, cachegroup.RepoUserPermission, fmt.Sprintf("%d-%d", pr.BaseRepoID, doerID), + repoUserPerm, err := cache.GetWithContextCache(ctx, cachegroup.RepoUserPermission, access_model.RepoUserPermissionCacheKey(pr.BaseRepoID, doer), func(ctx context.Context, _ string) (access_model.Permission, error) { return access_model.GetDoerRepoPermission(ctx, pr.BaseRepo, doer) }, diff --git a/services/pull/pull.go b/services/pull/pull.go index 90eb2271dc3..4650a62c928 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -931,8 +931,9 @@ func formatSquashMergeCommitMessages(commits []*git.Commit) string { return util.UnsafeBytesToString(buf) } -// GetIssuesAllCommitStatus returns a map of issue ID to a list of all statuses for the most recent commit as well as a map of issue ID to only the commit's latest status -func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatus, error) { +// GetIssuesAllCommitStatus returns a map of issue ID to a list of all statuses for the most recent commit as well as a map of issue ID to only the commit's latest status. +// The returned statuses are redacted for doer. +func GetIssuesAllCommitStatus(ctx context.Context, doer *user_model.User, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatus, error) { if err := issues.LoadPullRequests(ctx); err != nil { return nil, nil, err } @@ -966,7 +967,7 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList gitRepos[issue.RepoID] = gitRepo } - statuses, lastStatus, err := getAllCommitStatus(ctx, gitRepo, issue.PullRequest) + statuses, lastStatus, err := getAllCommitStatus(ctx, doer, gitRepo, issue.PullRequest) if err != nil { log.Error("getAllCommitStatus: cant get commit statuses of pull [%d]: %v", issue.PullRequest.ID, err) continue @@ -978,13 +979,18 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList } // getAllCommitStatus get pr's commit statuses. -func getAllCommitStatus(ctx context.Context, gitRepo *git.Repository, pr *issues_model.PullRequest) (statuses []*git_model.CommitStatus, lastStatus *git_model.CommitStatus, err error) { +func getAllCommitStatus(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, pr *issues_model.PullRequest) (statuses []*git_model.CommitStatus, lastStatus *git_model.CommitStatus, err error) { sha, shaErr := gitRepo.GetRefCommitID(ctx, pr.GetGitHeadRefName()) if shaErr != nil { return nil, nil, shaErr } statuses, err = git_model.GetLatestCommitStatus(ctx, pr.BaseRepo.ID, sha, db.ListOptionsAll) + for _, status := range statuses { + status.Repo = pr.BaseRepo // the repo is already loaded, spare the permission lookup a query + } + // CalcCommitStatus copies a TargetURL out of the statuses, so hide before combining + git_model.CommitStatusesApplyDoerPermission(ctx, doer, statuses) lastStatus = git_model.CalcCommitStatus(statuses) return statuses, lastStatus, err } diff --git a/services/repository/commitstatus/commitstatus.go b/services/repository/commitstatus/commitstatus.go index 022e8f2458c..78d398ade10 100644 --- a/services/repository/commitstatus/commitstatus.go +++ b/services/repository/commitstatus/commitstatus.go @@ -124,6 +124,8 @@ func FindReposLatestCommitStatuses(ctx context.Context, repos []*repo_model.Repo for i, repo := range repos { if cv := getCommitStatusCache(repo.ID, repo.DefaultBranch); cv != nil { results[i] = &git_model.CommitStatus{ + RepoID: repo.ID, + Repo: repo, State: commitstatus.CommitStatusState(cv.State), TargetURL: cv.TargetURL, } @@ -163,6 +165,7 @@ func FindReposLatestCommitStatuses(ctx context.Context, repos []*repo_model.Repo for _, summary := range summaryResults { for i, repo := range repos { if repo.ID == summary.RepoID { + summary.Repo = repo results[i] = summary repoSHAs = slices.DeleteFunc(repoSHAs, func(repoSHA git_model.RepoSHA) bool { return repoSHA.RepoID == repo.ID @@ -190,6 +193,7 @@ func FindReposLatestCommitStatuses(ctx context.Context, repos []*repo_model.Repo if results[i] == nil { results[i] = git_model.CalcCommitStatus(repoToItsLatestCommitStatuses[repo.ID]) if results[i] != nil { + results[i].Repo = repo if err := updateCommitStatusCache(repo.ID, repo.DefaultBranch, results[i].State, results[i].TargetURL); err != nil { log.Error("updateCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err) } diff --git a/templates/repo/commit_statuses.tmpl b/templates/repo/commit_statuses.tmpl index fb1e6fbf9bc..80b45092533 100644 --- a/templates/repo/commit_statuses.tmpl +++ b/templates/repo/commit_statuses.tmpl @@ -9,7 +9,7 @@ {{end}}
-
+
{{template "repo/pulls/status_items" (dict "CommitStatuses" .Statuses)}}
diff --git a/web_src/css/repo.css b/web_src/css/repo.css index ac1e808ff0e..1ab1e579767 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -1826,7 +1826,7 @@ tbody.commit-list { width: 100%; } -.commit-status-item { /* the item can be used at 2 places: PR's merge box (commit-status-list), commit's status popup (no commit-status-list) */ +.commit-status-item { /* the item is used in the PR merge box and the commit status popup, both are commit-status-list */ height: 40px; padding-top: 0 !important; /* use "height" + "align items center", don't use padding-y (from the list container) to layout */ padding-bottom: 0 !important;