-
Notifications
You must be signed in to change notification settings - Fork 104
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
Implement invalidate_on_push without pushedDate field #602
Changes from all commits
f307fec
2ec5748
bfaf1a1
7ab68cd
40fdd84
56fb7fa
56ee0c4
3f3e779
a39a23a
4a92d55
4199679
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -301,10 +301,6 @@ func (r *Rule) filterEditedCandidates(ctx context.Context, prctx pull.Context, c | |
func (r *Rule) filterInvalidCandidates(ctx context.Context, prctx pull.Context, candidates []*common.Candidate) ([]*common.Candidate, []*common.Dismissal, error) { | ||
log := zerolog.Ctx(ctx) | ||
|
||
if !r.Options.InvalidateOnPush { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is already checked by the caller |
||
return candidates, nil, nil | ||
} | ||
|
||
commits, err := r.filteredCommits(ctx, prctx) | ||
if err != nil { | ||
return nil, nil, err | ||
|
@@ -313,37 +309,61 @@ func (r *Rule) filterInvalidCandidates(ctx context.Context, prctx pull.Context, | |
return candidates, nil, nil | ||
} | ||
|
||
last := findLastPushed(commits) | ||
if last == nil { | ||
return nil, nil, errors.New("no commit contained a push date") | ||
sha := commits[0].SHA | ||
lastPushedAt, err := prctx.PushedAt(sha) | ||
if err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to get last push timestamp") | ||
} | ||
|
||
// The most recent filtered commit did not have a status. This can happen | ||
// in two situations: | ||
// | ||
// The commit was pushed in a batch where the head commit is ignored... | ||
if lastPushedAt.IsZero() && sha != prctx.HeadSHA() { | ||
sha = prctx.HeadSHA() | ||
lastPushedAt, err = prctx.PushedAt(sha) | ||
if err != nil { | ||
return nil, nil, errors.Wrap(err, "failed to get last push timestamp") | ||
} | ||
} | ||
// ... or the commit (or the head commit) hasn't been evaluated yet | ||
// | ||
// In this case, we're the first evaluation for this commit, so set the | ||
// push time to the curent time, which is guaranteed to be after the actual | ||
// push due to webhook delivery and processing time. | ||
if lastPushedAt.IsZero() { | ||
lastPushedAt = prctx.EvaluationTimestamp() | ||
} | ||
|
||
var allowed []*common.Candidate | ||
var dismissed []*common.Dismissal | ||
for _, c := range candidates { | ||
if c.CreatedAt.After(*last.PushedAt) { | ||
if c.CreatedAt.After(lastPushedAt) { | ||
allowed = append(allowed, c) | ||
} else { | ||
dismissed = append(dismissed, &common.Dismissal{ | ||
Candidate: c, | ||
Reason: fmt.Sprintf("Invalidated by push of %.7s", last.SHA), | ||
Reason: fmt.Sprintf("Invalidated by push of %.7s", sha), | ||
}) | ||
} | ||
} | ||
|
||
log.Debug().Msgf("discarded %d candidates invalidated by push of %s at %s", | ||
len(dismissed), | ||
last.SHA, | ||
last.PushedAt.Format(time.RFC3339)) | ||
log.Debug().Msgf( | ||
"discarded %d candidates invalidated by push of %s on or before %s", | ||
len(dismissed), sha, lastPushedAt.Format(time.RFC3339), | ||
) | ||
|
||
return allowed, dismissed, nil | ||
} | ||
|
||
// filteredCommits returns the relevant commits for the evaluation ordered in | ||
// history order, from most to least recent. | ||
func (r *Rule) filteredCommits(ctx context.Context, prctx pull.Context) ([]*pull.Commit, error) { | ||
commits, err := prctx.Commits() | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to list commits") | ||
} | ||
commits = sortCommits(commits, prctx.HeadSHA()) | ||
|
||
ignoreUpdates := r.Options.IgnoreUpdateMerges | ||
ignoreCommits := !r.Options.IgnoreCommitsBy.IsEmpty() | ||
|
@@ -430,19 +450,32 @@ func isIgnoredCommit(ctx context.Context, prctx pull.Context, actors *common.Act | |
return len(c.Users()) > 0, nil | ||
} | ||
|
||
func findLastPushed(commits []*pull.Commit) *pull.Commit { | ||
var last *pull.Commit | ||
for _, c := range commits { | ||
if c.PushedAt != nil && (last == nil || c.PushedAt.After(*last.PushedAt)) { | ||
last = c | ||
} | ||
} | ||
return last | ||
} | ||
|
||
func numberOfApprovals(count int) string { | ||
if count == 1 { | ||
return "1 approval" | ||
} | ||
return fmt.Sprintf("%d approvals", count) | ||
} | ||
|
||
// sortCommits orders commits in history order starting from head. It must be | ||
// called on the unfiltered set of commits. | ||
func sortCommits(commits []*pull.Commit, head string) []*pull.Commit { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is unnecessary because GitHub already returns the commits in this order, but I'd rather be explicit than have this break strangely if the order changes for some reason - this ordering is important for push detection to work in all cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it worth adding some small test cases for this ordering function? |
||
commitsBySHA := make(map[string]*pull.Commit) | ||
for _, c := range commits { | ||
commitsBySHA[c.SHA] = c | ||
} | ||
|
||
ordered := make([]*pull.Commit, 0, len(commits)) | ||
for { | ||
c, ok := commitsBySHA[head] | ||
if !ok { | ||
break | ||
} | ||
ordered = append(ordered, c) | ||
if len(c.Parents) == 0 { | ||
break | ||
} | ||
head = c.Parents[0] | ||
} | ||
return ordered | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section was removed a long time ago, but we didn't update the ToC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not still necessary to maintain a ToC by hand, at least for the github web UI: https://github.blog/changelog/2021-04-13-table-of-contents-support-in-markdown-files/