Show last commit status in pull request lists (#6465)
This commit is contained in:
		
							parent
							
								
									09fb036ad6
								
							
						
					
					
						commit
						bf5af87eef
					
				
					 6 changed files with 144 additions and 0 deletions
				
			
		
							
								
								
									
										93
									
								
								integrations/pull_status_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								integrations/pull_status_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,93 @@ | |||
| // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||
| // Use of this source code is governed by a MIT-style
 | ||||
| // license that can be found in the LICENSE file.
 | ||||
| package integrations | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 	"path" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	api "code.gitea.io/sdk/gitea" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
| 
 | ||||
| func TestPullCreate_CommitStatus(t *testing.T) { | ||||
| 	prepareTestEnv(t) | ||||
| 	session := loginUser(t, "user1") | ||||
| 	testRepoFork(t, session, "user2", "repo1", "user1", "repo1") | ||||
| 	testEditFileToNewBranch(t, session, "user1", "repo1", "master", "status1", "README.md", "status1") | ||||
| 
 | ||||
| 	url := path.Join("user1", "repo1", "compare", "master...status1") | ||||
| 	req := NewRequestWithValues(t, "POST", url, | ||||
| 		map[string]string{ | ||||
| 			"_csrf": GetCSRF(t, session, url), | ||||
| 			"title": "pull request from status1", | ||||
| 		}, | ||||
| 	) | ||||
| 	session.MakeRequest(t, req, http.StatusFound) | ||||
| 
 | ||||
| 	req = NewRequest(t, "GET", "/user1/repo1/pulls") | ||||
| 	resp := session.MakeRequest(t, req, http.StatusOK) | ||||
| 	doc := NewHTMLParser(t, resp.Body) | ||||
| 
 | ||||
| 	// Request repository commits page
 | ||||
| 	req = NewRequest(t, "GET", "/user1/repo1/pulls/1/commits") | ||||
| 	resp = session.MakeRequest(t, req, http.StatusOK) | ||||
| 	doc = NewHTMLParser(t, resp.Body) | ||||
| 
 | ||||
| 	// Get first commit URL
 | ||||
| 	commitURL, exists := doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href") | ||||
| 	assert.True(t, exists) | ||||
| 	assert.NotEmpty(t, commitURL) | ||||
| 
 | ||||
| 	commitID := path.Base(commitURL) | ||||
| 
 | ||||
| 	statusList := []models.CommitStatusState{ | ||||
| 		models.CommitStatusPending, | ||||
| 		models.CommitStatusError, | ||||
| 		models.CommitStatusFailure, | ||||
| 		models.CommitStatusWarning, | ||||
| 		models.CommitStatusSuccess, | ||||
| 	} | ||||
| 
 | ||||
| 	statesIcons := map[models.CommitStatusState]string{ | ||||
| 		models.CommitStatusPending: "circle icon yellow", | ||||
| 		models.CommitStatusSuccess: "check icon green", | ||||
| 		models.CommitStatusError:   "warning icon red", | ||||
| 		models.CommitStatusFailure: "remove icon red", | ||||
| 		models.CommitStatusWarning: "warning sign icon yellow", | ||||
| 	} | ||||
| 
 | ||||
| 	// Update commit status, and check if icon is updated as well
 | ||||
| 	for _, status := range statusList { | ||||
| 
 | ||||
| 		// Call API to add status for commit
 | ||||
| 		token := getTokenForLoggedInUser(t, session) | ||||
| 		req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/user1/repo1/statuses/%s?token=%s", commitID, token), | ||||
| 			api.CreateStatusOption{ | ||||
| 				State:       api.StatusState(status), | ||||
| 				TargetURL:   "http://test.ci/", | ||||
| 				Description: "", | ||||
| 				Context:     "testci", | ||||
| 			}, | ||||
| 		) | ||||
| 		session.MakeRequest(t, req, http.StatusCreated) | ||||
| 
 | ||||
| 		req = NewRequestf(t, "GET", "/user1/repo1/pulls/1/commits") | ||||
| 		resp = session.MakeRequest(t, req, http.StatusOK) | ||||
| 		doc = NewHTMLParser(t, resp.Body) | ||||
| 
 | ||||
| 		commitURL, exists = doc.doc.Find("#commits-table tbody tr td.sha a").Last().Attr("href") | ||||
| 		assert.True(t, exists) | ||||
| 		assert.NotEmpty(t, commitURL) | ||||
| 		assert.EqualValues(t, commitID, path.Base(commitURL)) | ||||
| 
 | ||||
| 		cls, ok := doc.doc.Find("#commits-table tbody tr td.message i.commit-status").Last().Attr("class") | ||||
| 		assert.True(t, ok) | ||||
| 		assert.EqualValues(t, "commit-status "+statesIcons[status], cls) | ||||
| 	} | ||||
| } | ||||
|  | @ -292,6 +292,31 @@ func (pr *PullRequest) CanAutoMerge() bool { | |||
| 	return pr.Status == PullRequestStatusMergeable | ||||
| } | ||||
| 
 | ||||
| // GetLastCommitStatus returns the last commit status for this pull request.
 | ||||
| func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) { | ||||
| 	if err = pr.GetHeadRepo(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	repo := pr.HeadRepo | ||||
| 	lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var statusList []*CommitStatus | ||||
| 	statusList, err = GetLatestCommitStatus(repo, lastCommitID, 0) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return CalcCommitStatus(statusList), nil | ||||
| } | ||||
| 
 | ||||
| // MergeStyle represents the approach to merge commits into base branch.
 | ||||
| type MergeStyle string | ||||
| 
 | ||||
|  |  | |||
|  | @ -214,6 +214,8 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	var commitStatus = make(map[int64]*models.CommitStatus, len(issues)) | ||||
| 
 | ||||
| 	// Get posters.
 | ||||
| 	for i := range issues { | ||||
| 		// Check read status
 | ||||
|  | @ -223,8 +225,14 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB | |||
| 			ctx.ServerError("GetIsRead", err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if isPullOption == util.OptionalBoolTrue { | ||||
| 			commitStatus[issues[i].PullRequest.ID], _ = issues[i].PullRequest.GetLastCommitStatus() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Issues"] = issues | ||||
| 	ctx.Data["CommitStatus"] = commitStatus | ||||
| 
 | ||||
| 	// Get assignees.
 | ||||
| 	ctx.Data["Assignees"], err = repo.GetAssignees() | ||||
|  |  | |||
|  | @ -319,8 +319,13 @@ func Issues(ctx *context.Context) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	var commitStatus = make(map[int64]*models.CommitStatus, len(issues)) | ||||
| 	for _, issue := range issues { | ||||
| 		issue.Repo = showReposMap[issue.RepoID] | ||||
| 
 | ||||
| 		if isPullList { | ||||
| 			commitStatus[issue.PullRequest.ID], _ = issue.PullRequest.GetLastCommitStatus() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	issueStats, err := models.GetUserIssueStats(models.UserIssueStatsOptions{ | ||||
|  | @ -344,6 +349,7 @@ func Issues(ctx *context.Context) { | |||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["Issues"] = issues | ||||
| 	ctx.Data["CommitStatus"] = commitStatus | ||||
| 	ctx.Data["Repos"] = showRepos | ||||
| 	ctx.Data["Counts"] = counts | ||||
| 	ctx.Data["Page"] = paginater.New(total, setting.UI.IssuePagingNum, page, 5) | ||||
|  |  | |||
|  | @ -203,6 +203,12 @@ | |||
| 					<div class="ui {{if .IsRead}}black{{else}}green{{end}} label">#{{.Index}}</div> | ||||
| 					<a class="title has-emoji" href="{{$.Link}}/{{.Index}}">{{.Title}}</a> | ||||
| 
 | ||||
|                     {{if .IsPull }} | ||||
|                         {{if (index $.CommitStatus .ID)}} | ||||
|                             {{template "repo/commit_status" (index $.CommitStatus .ID)}} | ||||
| 						{{end}} | ||||
| 					{{end}} | ||||
| 
 | ||||
| 					{{if .Ref}} | ||||
| 						<a class="ui label" href="{{$.RepoLink}}/src/branch/{{.Ref}}">{{.Ref}}</a> | ||||
| 					{{end}} | ||||
|  |  | |||
|  | @ -66,6 +66,12 @@ | |||
| 							<div class="ui label">{{if not $.RepoID}}{{.Repo.FullName}}{{end}}#{{.Index}}</div> | ||||
| 							<a class="title has-emoji" href="{{AppSubUrl}}/{{.Repo.Owner.Name}}/{{.Repo.Name}}/issues/{{.Index}}">{{.Title}}</a> | ||||
| 
 | ||||
|                             {{if .IsPull }} | ||||
|                                 {{if (index $.CommitStatus .ID)}} | ||||
|                                     {{template "repo/commit_status" (index $.CommitStatus .ID)}} | ||||
|                                 {{end}} | ||||
|                             {{end}} | ||||
| 
 | ||||
| 							{{with .Labels}} | ||||
| 								{{/* If we have any labels, we should show them | ||||
| 								with a 2.5 line height, this way they don't look | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue