Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commit status on repo and user pull request lists #2519

Closed
wants to merge 14 commits into from

Conversation

lunny
Copy link
Member

@lunny lunny commented Sep 15, 2017

And something confusing me is should I use issue.PullRequest.MergeBase as the last commit of a pull request? Anyway, see the screenshots below:

-1
-2

@lunny lunny added type/enhancement An improvement of existing functionality topic/ui Change the appearance of the Gitea UI labels Sep 15, 2017
@lunny lunny added this to the 1.3.0 milestone Sep 15, 2017
@lafriks
Copy link
Member

lafriks commented Sep 15, 2017

Integration test would be nice for this

@tboerger tboerger added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Sep 15, 2017
@lunny
Copy link
Member Author

lunny commented Sep 15, 2017

@lafriks It seems some difficult since our integration tests didn't run a drone instance?

@codecov-io
Copy link

codecov-io commented Sep 15, 2017

Codecov Report

Merging #2519 into master will increase coverage by 6.06%.
The diff coverage is 4.49%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2519      +/-   ##
==========================================
+ Coverage   20.62%   26.68%   +6.06%     
==========================================
  Files         166       90      -76     
  Lines       32261    17893   -14368     
==========================================
- Hits         6654     4775    -1879     
+ Misses      24628    12438   -12190     
+ Partials      979      680     -299
Impacted Files Coverage Δ
models/pull.go 20.38% <ø> (+3.64%) ⬆️
models/status.go 2.81% <0%> (+1.08%) ⬆️
routers/user/home.go 20.93% <7.69%> (-4%) ⬇️
models/repo_issue.go 0% <0%> (-52.64%) ⬇️
models/wiki.go 10.76% <0%> (-51.74%) ⬇️
models/graph.go 0% <0%> (-39.66%) ⬇️
models/repo_unit.go 8% <0%> (-29.94%) ⬇️
modules/markup/html.go 51.43% <0%> (-28.47%) ⬇️
models/git_diff.go 6.74% <0%> (-21.3%) ⬇️
models/issue_indexer.go 7.79% <0%> (-10.6%) ⬇️
... and 133 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 00bd627...09ec95b. Read the comment docs.

@lafriks
Copy link
Member

lafriks commented Sep 15, 2017

@lunny you can just call status api to set status for commit you dont need real CI


if issue.IsPull {
issue.LoadAttributes()
statuses, err := models.GetLatestCommitStatus(issue.Repo, issue.PullRequest.MergeBase, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you extract this block to new function? I've found this (almost) same code block 3 times in existing codebase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are different for ... range.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should have a issue.GetLatestCommitStatus that does what this if-block does?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so instead of

if issue.IsPull {
 ...
 append(...)
}

it would be

issueStatuses = append(issueStatuses, models.CalcCommitStatus(issue.GetLatestCommitStatus()))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's same, the only difference is you are adding result of models.CalcCommitStatus(statuses) to slice. Instead of calling 2 functions and 1 err check, you can call just 1 function (err check can be inside too, it changes nothing). Best thing would be to rename GetLatestCommitStatus to GetCommitStatuses (as it returns array, not just 1 status) and create/use GetLatestCommitStatus to return just one status (for now, this few lines of code can be used, but I want to change it to pure SQL select).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, GetCommitStatuses is here also, I don't understand GetLatestCommitStatus implementation... As I understand, it should return only 1 status in slice.


if issue.IsPull {
issue.LoadAttributes()
statuses, err := models.GetLatestCommitStatus(issue.Repo, issue.PullRequest.MergeBase, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should have a issue.GetLatestCommitStatus that does what this if-block does?


if issue.IsPull {
issue.LoadAttributes()
statuses, err := models.GetLatestCommitStatus(issue.Repo, issue.PullRequest.MergeBase, 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so instead of

if issue.IsPull {
 ...
 append(...)
}

it would be

issueStatuses = append(issueStatuses, models.CalcCommitStatus(issue.GetLatestCommitStatus()))

<div class="ui {{if $issue.IsRead}}black{{else}}green{{end}} label">#{{$issue.Index}}</div>
<a class="title has-emoji" href="{{$.Link}}/{{$issue.Index}}">{{$issue.Title}}</a>
{{if $issue.IsPull}}
{{template "repo/commit_status" (index $.IssuesStates $index)}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@lunny
Copy link
Member Author

lunny commented Sep 15, 2017

In fact I prefer to implement GetLatestCommitStatusByIDs

@bkcsoft
Copy link
Member

bkcsoft commented Sep 15, 2017

@lunny ByIDs ? What ID?

@lunny
Copy link
Member Author

lunny commented Sep 16, 2017

@bkcsoft GetLatestCommitStatusByRepoIDsAndCommitIDs(repoIDs, commitIDs)

// Check read status
if !ctx.IsSigned {
issues[i].IsRead = true
} else if err = issues[i].GetIsRead(ctx.User.ID); err != nil {
ctx.Handle(500, "GetIsRead", err)
return
}

if issue.IsPull {
issue.LoadAttributes()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not ignore the error returned here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

for _, issue := range issues {
issue.Repo = showReposMap[issue.RepoID]

if issue.IsPull {
issue.LoadAttributes()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not ignore the error returned here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@bkcsoft
Copy link
Member

bkcsoft commented Sep 16, 2017

@lunny That function name is waaaay to long 😂 I say that (repoID, commitID) is enough documentation to just call it GetLatestCommitStatuses ;)

@@ -207,17 +207,44 @@ func Issues(ctx *context.Context) {
}
}

var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use 1 slice of structs instead?

type pull struct{
    repoID int64
    sha string
    pullID int64
}

var pulls = make([]pull , 0, len(issues))

...

pulls = append(pulls, pull{ctx.Repo.Repository.ID, issue.PullRequest.MergeBase, issue.ID})

// Check read status
if !ctx.IsSigned {
issues[i].IsRead = true
} else if err = issues[i].GetIsRead(ctx.User.ID); err != nil {
ctx.Handle(500, "GetIsRead", err)
return
}

if issue.IsPull {
if err := issue.LoadAttributes(); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you don't need to run issue.LoadAttributes() again, models.Issues() has already did it.

models/status.go Outdated
var results = make([]struct {
ID int64
RepoID int64
}, 0, 10*len(repoIDs))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 10*len(repoIDs)?

var issuesStates = make(map[int64]*models.CommitStatus, len(issues))
for i, statuses := range commitStatuses {
issuesStates[pullIDs[i]] = models.CalcCommitStatus(statuses)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there way to reduce all of this lines above to just 1 function call? I am thinking about doing just 1 sql select to get what you need. There are too many for loops and also nested loop.

I think we can add something like "StateLevel" or "StateCode" to CommitStatus table (there are only strings - CommitStatus.State- right now). Then we can do simple select to get "worst" status. For "latests" status there is CommitStatus.Index or max CommitStatus.ID.

@@ -307,10 +307,37 @@ func Issues(ctx *context.Context) {
return
}

var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as for "routers/repo/issue.go".

models/status.go Outdated
err := x.Table(&CommitStatus{}).
Where(cond).
Select("max( id ) as id, repo_id").
GroupBy("repo_id, sha, context").OrderBy("max( id ) desc").Find(&results)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is not this select everything you need to get latest commit for each repo commit (I was just writing about adding columns to "group by" when you updated it)? You can use this as subselect (just remove repo_id from select) for mainy "where" clause.

@lunny
Copy link
Member Author

lunny commented Sep 18, 2017

@lafriks integration tests added

@lunny
Copy link
Member Author

lunny commented Sep 18, 2017

@Morlinest I think the best way is add a field LastCommitID on PullRequest and fill in it when push commit to the headbranch. So I will do it on another PR and keep this one simple.

} else {
var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use just 1 slice for repoIDs + shas and 1 for pullIDs (see comment for GetLatestCommitStatuses function). Or you can use composition and create just 1 slice.

// can be used as arg for GetLatestCommitStatuses
type CommitOption struct {
    RepoID int64
    Sha string
}

type results struct {
    CommitOption
    pullID int64
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right. But I think store the last commit id in pullrequest table is the best way. I will send another PR to do that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do, call it RepoSHA instead of CommitOption since that better explains the purpose of the struct. Though in general I dislike FunctionOptions structs since they hide the arguments from the docs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bkcsoft But 2 slices is not solution to that as you can't be sure about the order nor dependency between values on same key. I don't think that you are hiding something with structs in go.

models/status.go Outdated
@@ -170,6 +172,60 @@ func GetLatestCommitStatus(repo *Repository, sha string, page int) ([]*CommitSta
return statuses, x.In("id", ids).Find(&statuses)
}

// GetLatestCommitStatuses returns all statuses with given repoIDs and shas
func GetLatestCommitStatuses(repoIDs []int64, shas []string) ([][]*CommitStatus, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of 2 slices it should be 1 slice of structs with 2 values. You can't be sure, both slices are in same order and values on concrete index belongs each other.

models/status.go Outdated
var repoIDsMap = make(map[string][]int64, len(repoIDs))
for _, res := range results {
ids = append(ids, res.ID)
repoIDsMap[fmt.Sprintf("%d-%s", res.RepoID, res.SHA)] = append(repoIDsMap[fmt.Sprintf("%d-%s", res.RepoID, res.SHA)], res.ID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Save fmt.Sprintf("%d-%s", res.RepoID, res.SHA) to variable and use it as key.

models/status.go Outdated
var repoIDsMap = make(map[string][]int64, len(repoIDs))
for _, res := range results {
ids = append(ids, res.ID)
repoIDsMap[fmt.Sprintf("%d-%s", res.RepoID, res.SHA)] = append(repoIDsMap[fmt.Sprintf("%d-%s", res.RepoID, res.SHA)], res.ID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will overwrite value of repoIDsMap if you have 2 different context for same commit (res.RepoID and res.SHA is same). What is the point here?

var repoIDs = make([]int64, 0, len(issues))
var shas = make([]string, 0, len(issues))
var pullIDs = make([]int64, 0, len(issues))
var repoCache = make(map[int64]*git.Repository)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as for "routers/repo/issue.go". Also looks like duplicated code (one if/else check less).

@Morlinest
Copy link
Member

@lunny OK, I'll wait for new PR and updated version because I have more comments to this PR :)

@lunny
Copy link
Member Author

lunny commented Sep 19, 2017

@Morlinest I will update this after #2548 merged.


req = NewRequestWithValues(t, "POST", url,
map[string]string{
"_csrf": htmlDoc.GetCSRF(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you can use GetCSRF(..), so you don't have to manually make GET request just for the csrf token.

{{end}}
{{if eq .State "warning"}}
<a href="{{.TargetURL}}" target=_blank><i class="commit-status warning sign icon yellow"></i></a>
{{if .}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should use tabs instead of spaces


var rep *git.Repository
var ok bool
if rep, ok = repoCache[issue.PullRequest.HeadRepoID]; !ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we call the variable gitRepo, or something more descriptive? Without context, it's not obvious (at least not to me) that rep stands for repo.

@@ -162,36 +162,38 @@
</div>

<div class="issue list">
{{range .Issues}}
{{ $timeStr:= TimeSince .Created $.Lang }}
{{range $index, $issue := .Issues}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is $index ever used? Similarly for the other template.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems no needed after my second push.

@MorphBonehunter MorphBonehunter mentioned this pull request Oct 28, 2017
4 tasks
@lunny
Copy link
Member Author

lunny commented Oct 28, 2017

will resolve #996

@lunny lunny modified the milestones: 1.3.0, 1.4.0 Nov 10, 2017
@lunny lunny force-pushed the lunny/add_commit_status_pr branch from 315fc0c to 207fccd Compare January 6, 2019 02:31
@techknowlogick techknowlogick modified the milestones: 1.8.0, 1.x.x Feb 12, 2019
@lafriks lafriks modified the milestones: 1.x.x, 1.9.0 Mar 25, 2019
@lunny
Copy link
Member Author

lunny commented Mar 25, 2019

@SijmenSchoon if you want to work on this, just take it and create another PR. I think this PR needs to fix tests. I'm now busy on other PRs.

@stale
Copy link

stale bot commented May 24, 2019

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs during the next 2 months. Thank you for your contributions.

@stale stale bot added the issue/stale label May 24, 2019
@lunny
Copy link
Member Author

lunny commented May 24, 2019

Since #6465 merged, I will close this one.

@lunny lunny closed this May 24, 2019
@lunny lunny removed this from the 1.9.0 milestone Sep 18, 2019
@lunny lunny deleted the lunny/add_commit_status_pr branch September 18, 2019 06:00
@go-gitea go-gitea locked and limited conversation to collaborators Nov 24, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
issue/stale lgtm/need 1 This PR needs approval from one additional maintainer to be merged. topic/ui Change the appearance of the Gitea UI type/enhancement An improvement of existing functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.