Skip to content

Commit

Permalink
Add commit statuses reports on pull request view (#6845)
Browse files Browse the repository at this point in the history
* Add commit statuses reports on pull view

* Add some translations

* improve the UI

* fix fmt

* fix tests

* add a new test git repo to fix tests

* fix bug when headRepo or headBranch missing

* fix tests

* fix tests

* fix consistency

* fix tests

* fix tests

* change the test repo

* fix tests

* fix tests

* fix migration

* keep db size consistency

* fix translation

* change commit hash status table unique index

* remove unused table

* use char instead varchar

* make hashCommitStatusContext private

* split merge section with status check on pull view ui

* fix tests; fix arc-green theme on pull ui
  • Loading branch information
lunny authored and zeripath committed Jun 30, 2019
1 parent 1e46eed commit ff85dd3
Show file tree
Hide file tree
Showing 23 changed files with 236 additions and 85 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0abcb056019adb8336cf9db3ad9d9cf80cd4b141
2 changes: 1 addition & 1 deletion integrations/pull_merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func TestCantMergeWorkInProgress(t *testing.T) {
req := NewRequest(t, "GET", resp.Header().Get("Location"))
resp = session.MakeRequest(t, req, http.StatusOK)
htmlDoc := NewHTMLParser(t, resp.Body)
text := strings.TrimSpace(htmlDoc.doc.Find(".merge.segment > .text.grey").Text())
text := strings.TrimSpace(htmlDoc.doc.Find(".merge-section.segment > .text.grey").Text())
assert.NotEmpty(t, text, "Can't find WIP text")

// remove <strong /> from lang
Expand Down
104 changes: 33 additions & 71 deletions models/status.go → models/commit_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@ package models

import (
"container/list"
"crypto/sha1"
"fmt"
"strings"

"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"

"github.com/go-xorm/xorm"
)

// CommitStatusState holds the state of a Status
Expand Down Expand Up @@ -61,6 +59,7 @@ type CommitStatus struct {
SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
TargetURL string `xorm:"TEXT"`
Description string `xorm:"TEXT"`
ContextHash string `xorm:"char(40) index"`
Context string `xorm:"TEXT"`
Creator *User `xorm:"-"`
CreatorID int64
Expand Down Expand Up @@ -146,7 +145,7 @@ func GetLatestCommitStatus(repo *Repository, sha string, page int) ([]*CommitSta
Table(&CommitStatus{}).
Where("repo_id = ?", repo.ID).And("sha = ?", sha).
Select("max( id ) as id").
GroupBy("context").OrderBy("max( id ) desc").Find(&ids)
GroupBy("context_hash").OrderBy("max( id ) desc").Find(&ids)
if err != nil {
return nil, err
}
Expand All @@ -157,27 +156,6 @@ func GetLatestCommitStatus(repo *Repository, sha string, page int) ([]*CommitSta
return statuses, x.In("id", ids).Find(&statuses)
}

// GetCommitStatus populates a given status for a given commit.
// NOTE: If ID or Index isn't given, and only Context, TargetURL and/or Description
// is given, the CommitStatus created _last_ will be returned.
func GetCommitStatus(repo *Repository, sha string, status *CommitStatus) (*CommitStatus, error) {
conds := &CommitStatus{
Context: status.Context,
State: status.State,
TargetURL: status.TargetURL,
Description: status.Description,
}
has, err := x.Where("repo_id = ?", repo.ID).And("sha = ?", sha).Desc("created_unix").Get(conds)
if err != nil {
return nil, fmt.Errorf("GetCommitStatus[%s, %s]: %v", repo.RepoPath(), sha, err)
}
if !has {
return nil, fmt.Errorf("GetCommitStatus[%s, %s]: not found", repo.RepoPath(), sha)
}

return conds, nil
}

// NewCommitStatusOptions holds options for creating a CommitStatus
type NewCommitStatusOptions struct {
Repo *Repository
Expand All @@ -186,31 +164,31 @@ type NewCommitStatusOptions struct {
CommitStatus *CommitStatus
}

func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error {
opts.CommitStatus.Description = strings.TrimSpace(opts.CommitStatus.Description)
opts.CommitStatus.Context = strings.TrimSpace(opts.CommitStatus.Context)
opts.CommitStatus.TargetURL = strings.TrimSpace(opts.CommitStatus.TargetURL)
opts.CommitStatus.SHA = opts.SHA
opts.CommitStatus.CreatorID = opts.Creator.ID

// NewCommitStatus save commit statuses into database
func NewCommitStatus(opts NewCommitStatusOptions) error {
if opts.Repo == nil {
return fmt.Errorf("newCommitStatus[nil, %s]: no repository specified", opts.SHA)
return fmt.Errorf("NewCommitStatus[nil, %s]: no repository specified", opts.SHA)
}
opts.CommitStatus.RepoID = opts.Repo.ID
repoPath := opts.Repo.repoPath(sess)

repoPath := opts.Repo.RepoPath()
if opts.Creator == nil {
return fmt.Errorf("newCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA)
return fmt.Errorf("NewCommitStatus[%s, %s]: no user specified", repoPath, opts.SHA)
}

gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository[%s]: %v", repoPath, err)
}
if _, err := gitRepo.GetCommit(opts.SHA); err != nil {
return fmt.Errorf("GetCommit[%s]: %v", opts.SHA, err)
sess := x.NewSession()
defer sess.Close()

if err := sess.Begin(); err != nil {
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %v", opts.Repo.ID, opts.Creator.ID, opts.SHA, err)
}

opts.CommitStatus.Description = strings.TrimSpace(opts.CommitStatus.Description)
opts.CommitStatus.Context = strings.TrimSpace(opts.CommitStatus.Context)
opts.CommitStatus.TargetURL = strings.TrimSpace(opts.CommitStatus.TargetURL)
opts.CommitStatus.SHA = opts.SHA
opts.CommitStatus.CreatorID = opts.Creator.ID
opts.CommitStatus.RepoID = opts.Repo.ID

// Get the next Status Index
var nextIndex int64
lastCommitStatus := &CommitStatus{
Expand All @@ -220,46 +198,25 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error {
has, err := sess.Desc("index").Limit(1).Get(lastCommitStatus)
if err != nil {
if err := sess.Rollback(); err != nil {
log.Error("newCommitStatus: sess.Rollback: %v", err)
log.Error("NewCommitStatus: sess.Rollback: %v", err)
}
return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
return fmt.Errorf("NewCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
}
if has {
log.Debug("newCommitStatus[%s, %s]: found", repoPath, opts.SHA)
log.Debug("NewCommitStatus[%s, %s]: found", repoPath, opts.SHA)
nextIndex = lastCommitStatus.Index
}
opts.CommitStatus.Index = nextIndex + 1
log.Debug("newCommitStatus[%s, %s]: %d", repoPath, opts.SHA, opts.CommitStatus.Index)
log.Debug("NewCommitStatus[%s, %s]: %d", repoPath, opts.SHA, opts.CommitStatus.Index)

opts.CommitStatus.ContextHash = hashCommitStatusContext(opts.CommitStatus.Context)

// Insert new CommitStatus
if _, err = sess.Insert(opts.CommitStatus); err != nil {
if err := sess.Rollback(); err != nil {
log.Error("newCommitStatus: sess.Rollback: %v", err)
log.Error("Insert CommitStatus: sess.Rollback: %v", err)
}
return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
}

return nil
}

// NewCommitStatus creates a new CommitStatus given a bunch of parameters
// NOTE: All text-values will be trimmed from whitespaces.
// Requires: Repo, Creator, SHA
func NewCommitStatus(repo *Repository, creator *User, sha string, status *CommitStatus) error {
sess := x.NewSession()
defer sess.Close()

if err := sess.Begin(); err != nil {
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %v", repo.ID, creator.ID, sha, err)
}

if err := newCommitStatus(sess, NewCommitStatusOptions{
Repo: repo,
Creator: creator,
SHA: sha,
CommitStatus: status,
}); err != nil {
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %v", repo.ID, creator.ID, sha, err)
return fmt.Errorf("Insert CommitStatus[%s, %s]: %v", repoPath, opts.SHA, err)
}

return sess.Commit()
Expand Down Expand Up @@ -295,3 +252,8 @@ func ParseCommitsWithStatus(oldCommits *list.List, repo *Repository) *list.List
}
return newCommits
}

// hashCommitStatusContext hash context
func hashCommitStatusContext(context string) string {
return fmt.Sprintf("%x", sha1.Sum([]byte(context)))
}
File renamed without changes.
11 changes: 11 additions & 0 deletions models/fixtures/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,14 @@
created_unix: 946684830
updated_unix: 978307200

-
id: 8
repo_id: 10
index: 1
poster_id: 11
name: pr2
content: a pull request
is_closed: false
is_pull: true
created_unix: 946684820
updated_unix: 978307180
14 changes: 14 additions & 0 deletions models/fixtures/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,17 @@
base_branch: master
merge_base: fedcba9876543210
has_merged: false

-
id: 3
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 8
index: 1
head_repo_id: 11
base_repo_id: 10
head_user_name: user13
head_branch: branch2
base_branch: master
merge_base: 0abcb056019adb83
has_merged: false
4 changes: 2 additions & 2 deletions models/fixtures/repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@
is_private: false
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_pulls: 1
num_closed_pulls: 0
is_mirror: false
num_forks: 1
Expand Down Expand Up @@ -496,4 +496,4 @@
num_stars: 0
num_forks: 0
num_issues: 0
is_mirror: false
is_mirror: false
2 changes: 2 additions & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ var migrations = []Migration{
NewMigration("add http method to webhook", addHTTPMethodToWebhook),
// v87 -> v88
NewMigration("add avatar field to repository", addAvatarFieldToRepository),
// v88 -> v89
NewMigration("add commit status context field to commit_status", addCommitStatusContext),
}

// Migrate database to current version
Expand Down
2 changes: 1 addition & 1 deletion models/migrations/v87.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2019 Gitea. All rights reserved.
// 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.

Expand Down
66 changes: 66 additions & 0 deletions models/migrations/v88.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// 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 migrations

import (
"crypto/sha1"
"fmt"

"github.com/go-xorm/xorm"
)

func hashContext(context string) string {
return fmt.Sprintf("%x", sha1.Sum([]byte(context)))
}

func addCommitStatusContext(x *xorm.Engine) error {
type CommitStatus struct {
ID int64 `xorm:"pk autoincr"`
ContextHash string `xorm:"char(40) index"`
Context string `xorm:"TEXT"`
}

if err := x.Sync2(new(CommitStatus)); err != nil {
return err
}

sess := x.NewSession()
defer sess.Close()

var start = 0
for {
var statuses = make([]*CommitStatus, 0, 100)
err := sess.OrderBy("id").Limit(100, start).Find(&statuses)
if err != nil {
return err
}
if len(statuses) == 0 {
break
}

if err = sess.Begin(); err != nil {
return err
}

for _, status := range statuses {
status.ContextHash = hashContext(status.Context)
if _, err := sess.ID(status.ID).Cols("context_hash").Update(status); err != nil {
return err
}
}

if err := sess.Commit(); err != nil {
return err
}

if len(statuses) < 100 {
break
}

start += len(statuses)
}

return nil
}
39 changes: 39 additions & 0 deletions modules/repofiles/commit_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 repofiles

import (
"fmt"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
)

// CreateCommitStatus creates a new CommitStatus given a bunch of parameters
// NOTE: All text-values will be trimmed from whitespaces.
// Requires: Repo, Creator, SHA
func CreateCommitStatus(repo *models.Repository, creator *models.User, sha string, status *models.CommitStatus) error {
repoPath := repo.RepoPath()

// confirm that commit is exist
gitRepo, err := git.OpenRepository(repoPath)
if err != nil {
return fmt.Errorf("OpenRepository[%s]: %v", repoPath, err)
}
if _, err := gitRepo.GetCommit(sha); err != nil {
return fmt.Errorf("GetCommit[%s]: %v", sha, err)
}

if err := models.NewCommitStatus(models.NewCommitStatusOptions{
Repo: repo,
Creator: creator,
SHA: sha,
CommitStatus: status,
}); err != nil {
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %v", repo.ID, creator.ID, sha, err)
}

return nil
}
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,9 @@ pulls.rebase_merge_commit_pull_request = Rebase and Merge (--no-ff)
pulls.squash_merge_pull_request = Squash and Merge
pulls.invalid_merge_option = You cannot use this merge option for this pull request.
pulls.open_unmerged_pull_exists = `You cannot perform a reopen operation because there is a pending pull request (#%d) with identical properties.`
pulls.status_checking = Some checks are pending
pulls.status_checks_success = All checks were successful
pulls.status_checks_error = Some checks failed
milestones.new = New Milestone
milestones.open_tab = %d Open
Expand Down
1 change: 1 addition & 0 deletions public/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
.repository.view.issue .comment-list .comment .content>.header:before{border-right-color:#d3d3d4;border-width:9px;margin-top:-9px}
.repository.view.issue .comment-list .comment .content>.header:after{border-right-color:#f7f7f7;border-width:8px;margin-top:-8px}
.repository.view.issue .comment-list .comment .content>.header .text{max-width:78%;padding-top:10px;padding-bottom:10px}
.repository.view.issue .comment-list .comment .content>.merge-section{border-top:1px solid #d4d4d5;background-color:#f7f7f7}
.repository.view.issue .comment-list .comment .content .markdown{font-size:14px}
.repository.view.issue .comment-list .comment .content .no-content{color:#767676;font-style:italic}
.repository.view.issue .comment-list .comment .content>.bottom.segment{background:#f3f4f5}
Expand Down
1 change: 1 addition & 0 deletions public/css/theme-arc-green.css
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ footer{background:#2e323e;border-top:1px solid #313131}
.ui.attached.segment{border:1px solid #404552}
.repository.view.issue .comment-list .comment .content>.bottom.segment{background:#353945}
.repository.view.issue .comment-list .comment .content .header{color:#dbdbdb;background-color:#404552;border-bottom:1px solid #353944}
.repository.view.issue .comment-list .comment .content .merge-section{background-color:#404552;border-top:1px solid #353944}
.ui .text.grey a{color:#dbdbdb!important}
.ui.comments .comment .actions a{color:#dbdbdb}
.repository.view.issue .comment-list .comment .content .header:after{border-right-color:#404552}
Expand Down
5 changes: 5 additions & 0 deletions public/less/_repository.less
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,11 @@
}
}

> .merge-section {
border-top: 1px solid #d4d4d5;
background-color: #f7f7f7;
}

.markdown {
font-size: 14px;
}
Expand Down
Loading

0 comments on commit ff85dd3

Please sign in to comment.