-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Adds ability to set required and optional checks #7983
Conversation
/ok-to-test |
prow/config/branch_protection.go
Outdated
} | ||
return required | ||
return |
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.
-1 to named returns
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.
Agreed on not using named returns
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.
May I ask why ?
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.
harder to maintain, it's not obvious what's the returned value
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.
I find almost universally they are harder to reason about and read through. They are almost nonexistant in the codebase as it is. Stats:
$ grep -rh func prow/ | grep -Po "(?<=\) \()[^\(\)]+(?=\) \{)" | tr ',' '\n' | awk '{print $2 }' | grep -v "^$" | wc -l
19
$ grep -rh func prow/ | wc -l
2084
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.
I actually discovered them in k8s codebase :) but right it may be confusing ! fixed.
prow/config/branch_protection.go
Outdated
p, ok := presubmits[org+"/"+repo] | ||
if !ok { | ||
return nil | ||
return |
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.
-1 to named returns
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.
fixed
@@ -298,11 +298,11 @@ func TestJobRequirements(t *testing.T) { | |||
} | |||
|
|||
for _, tc := range cases { | |||
masterActual := jobRequirements(tc.config, "master", false) | |||
masterActual, _ := jobRequirements(tc.config, "master", false) |
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.
extend the test to test both?
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.
done
prow/cmd/branchprotector/README.md
Outdated
@@ -22,6 +22,8 @@ branch-protection: | |||
# Ensure that the extra-process-followed github status context passes. | |||
# In addition, adds any required prow jobs (aka always_run: true) | |||
require-contexts: ["extra-process-followed"] | |||
# Tell Tide to merge when unspecified contexts are pending or failing | |||
skip-unknown-contexts: true |
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.
Configuration for tide
actions should not live in the branch protector's config.
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.
+1, this should be part of the job spec
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.
For prow jobs we already have the optional setting. For optional jobs that are not prowjob we need to define it somewhere. I had a global setting in tide configuration, but that was not practical. It makes sense for me to define it in branch protection since this option only works when branch protection is set and you might want to apply this globally, on a repo or on a branch which branch protection already does. I had discussed this with @cjwagner
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.
also skipunknown context does not have any meaning if we don't have a branch protection, meaning no jobs defined at all in Prow config since all are unknown.
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.
but that was not practical.
Why not? It's a simple mapping with the same parent/child scheme as in this config. I would expect it to live in tide
config exclusively. It's configuring tide
to run. Members can protect their branches without using the branch-protector
and can run the branch-protector
without running tide
.
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.
So the original idea was to use the github required check to figure that out, but that was doing too many request to the github api. After a meeting with the @fejta, @cjwagner and @BenTheElder it was decided to use branch protection instead. You don't have to actually enforce branch protection, you can just use the config and set protect to false, and then use that to define the required checks that you required for a PR to be merged. I don't see the point of duplicating those configs since they map back to protecting a branch. I think the Prow config is big and complicated enough.
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.
You don't have to actually enforce branch protection, you can just use the config and set protect to false, and then use that to define the required checks that you required for a PR to be merged.
Err, what? If you want to configure branch protection for statuses, do that. Then let tide
honor required statuses. If you want to configure statuses for tide
, do that, and don't touch the branch protection config (which you might have never even written since you don't use the branch protector). IDK. These seem like two entirely separate use cases that are being put in one place.
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.
I agree I am defining a tide options which will basically allow you to use branch protection or otherwise allow you to define your own if you don't want to use branch protection. If that option is not set, it will use combined status from github as it is today.
prow/tide/contextregister.go
Outdated
|
||
"github.com/shurcooL/githubql" | ||
"k8s.io/apimachinery/pkg/util/sets" | ||
"k8s.io/test-infra/prow/config" |
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.
nit: indent of this repo should be in separate block at bottom
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.
done
prow/tide/tide.go
Outdated
string(pr.BaseRef.Name), | ||
sc.ca.Config()) | ||
if err != nil { | ||
log.WithError(err).Error("Getting branch protection") |
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.
nit: bad error
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.
fixed
prow/tide/tide.go
Outdated
var failed []Context | ||
for _, ctx := range contexts { | ||
if string(ctx.Context) == statusContext { | ||
if cc.ignoreContext(ctx) { |
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 seems like a regression if we mark the tide
status required
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.
cc already ignores tide
@@ -944,7 +954,7 @@ func (c *Controller) presubmitsByPull(sp subpool) (map[int]sets.String, error) { | |||
}() | |||
|
|||
for _, ps := range c.ca.Config().Presubmits[sp.org+"/"+sp.repo] { | |||
if ps.SkipReport || !ps.RunsAgainstBranch(sp.branch) { | |||
if !ps.ContextRequired() || !ps.RunsAgainstBranch(sp.branch) { |
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.
Why are we changing this functionality? If we want to do this, let's do it in a separate PR?
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.
The goal of this PR is to allow optional jobs to be skipped for tide. So yes this is in scope.
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.
Right now we have the SkipReport
as the means by which we accomplish that. Why do we want to change that right now? Can we continue honoring the SkipReport
as well? Breaking changes for cluster admins are annoying.
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.
The reason is that SkipReport = false does not mean the check is required. In our use case you might want to push a status on a PR for a test that is not required, this is the reason I added Optional a while back. Optional is false by default so it will not impact anything, but then if you define a prowjob with Optional set to true, you defintely want to skip it to merge a PR. So this is the reason I added this.
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.
I understand they are not identical features, what I am saying is today we use SkipReport
to mean "tide ignore" because whether or not it's required, if it's not reported, tide
ignores it. As long as SkipReport=true
continues to mean that tide
ignores the job, but now in addition, SkipReport=false Optional=true
works, that is OK.
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.
ok.
prow/tide/tide_test.go
Outdated
combinedContexts map[string]string | ||
}{ | ||
{ | ||
name: "required checks disabled should not impact - passing", |
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.
these names are a bit confusing
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.
thanks for pointing that out. After reviewing some of the test I discovered some issues.
prow/tide/tide_test.go
Outdated
{ | ||
name: "required checks disabled should not impact - passing", | ||
passing: true, | ||
config: &config.Policy{ |
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.
@fejta is it even valid config to have a policy with explicitly listed required checks but have the policy be set to not enforce? why?
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.
I think there could multiple use cases. When you define policy at the repo or org level, and then you create a branch for testing and you don't want to protect it or if you just want to disable temporarily.
PTAL |
Please no merge commits. Rebase on |
@stevekuznetsov I think we got it. I think you are going to like this. |
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.
PTAL
prow/tide/contextregister.go
Outdated
|
||
// contextRegister implements contextChecker and allow registering of required and optional contexts. | ||
type contextRegister struct { | ||
lock sync.RWMutex |
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.
I had it since tide code is using multiple go routine, but since the object is created inside a funciton, the lock is overkill.
prow/tide/contextregister.go
Outdated
optional: sets.NewString(), | ||
skipUnknownContexts: skipUnknownContexts, | ||
} | ||
r.registerOptionalContexts(statusContext) |
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 is coming from tide.go (its the tide status). I know the name is not very well chosen, but I am trying to do the least amount of changes.
prow/tide/contextregister.go
Outdated
// - context is registered as optional | ||
// - required contexts are registered and the context provided is not required | ||
// Will return false otherwise. Every context is required. | ||
func (r *contextRegister) ignoreContext(c Context) bool { |
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.
we do, that s tide status. its registered by default. This implementation could be use in another context, so I did not want to hard code in there.
prow/tide/contextregister.go
Outdated
func (r *contextRegister) missingRequiredContexts(contexts []Context) []Context { | ||
r.lock.RLock() | ||
defer r.lock.RUnlock() | ||
if r.required.Len() == 0 { |
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 will but why bother doing all that when you already know the answer.
prow/config/tide.go
Outdated
return b | ||
} | ||
c := TideContextPolicy{} | ||
c.FromBranchProtection = mergeBool(c.FromBranchProtection, b.FromBranchProtection) |
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.
Merge a
and b
, not c
and b
.
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.
Please also add a test case to catch this.
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.
done
prow/config/tide.go
Outdated
if bp == nil { | ||
return TideContextPolicy{}, errors.New("branch protection is not set") | ||
} | ||
if bp.Protect == nil || !*bp.Protect || bp.RequiredStatusChecks == nil { |
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.
I don't think that we should consider this an error. If I set FromBranchProtection
at the org level I wouldn't expect an error if some repo in the org does not have RequiredStatusChecks
. In this case we should probably just not add anything to required
?
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.
done
prow/config/tide.go
Outdated
} | ||
required.Insert(bp.RequiredStatusChecks.Contexts...) | ||
} | ||
|
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.
Please add a TideContextPolicy.Validate
function and call it here to validate the policy before it is returned.
Specifically, validate that no required context is also an optional context.
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.
done and added tc
prow/tide/contextregister.go
Outdated
} | ||
|
||
// contextRegister implements contextChecker and allow registering of required and optional contexts. | ||
type contextRegister struct { |
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.
I don't think that we need this any more. Its functionality could be moved into the TideContextPolicy
struct.
In other words, instead of constructing a contextRegister
from a TideContextPolicy
in order to get a contextChecker
, just make the TideContextPolicy
match the contextChecker
interface itself.
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.
I tend to agree with you, but that would create circular dependency and I would have to move the Context struct out as an example. Plus I would have to hard code the tide status in there. I am trying to keep this as the minimum amount of change. However, I don't think that the context checker interface is something that we need. The implementation is very general and straightforward. What do you think ?
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.
What is the circular dependency? The contextRegister
is basically copying the fields from TideContextPolicy
and defining new methods so I'd really prefer to condense these into one struct and just configure the packages and imports properly to avoid a circular dependency.
The tide status shouldn't need to be hard coded? It can be passed down from the tide
package.
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.
The circular deps is on the Context object defined in prow/tide/tide.go
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.
Done
prow/tide/tide.go
Outdated
@@ -991,6 +1002,10 @@ func (c *Controller) syncSubpool(sp subpool) (Pool, error) { | |||
if err != nil { | |||
return Pool{}, fmt.Errorf("error determining required presubmits: %v", err) | |||
} | |||
cr, err := newContextRegisterFromConfig(sp.org, sp.repo, sp.branch, c.ca.Config()) | |||
if err != nil { | |||
return Pool{}, fmt.Errorf("error parsing branch protection: %v", err) |
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 error message is no longer accurate.
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.
done
@cjwagner Please take a look |
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.
Just a couple nits. This is looking ready.
prow/config/tide.go
Outdated
|
||
// RegisterRequiredContexts register required contexts. | ||
// Once required contexts are registered other contexts will be considered optional. | ||
func (cp *TideContextPolicy) RegisterRequiredContexts(c ...string) { |
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 func is no longer needed.
prow/config/tide.go
Outdated
} | ||
|
||
// RegisterOptionalContexts registers optional contexts | ||
func (cp *TideContextPolicy) RegisterOptionalContexts(c ...string) { |
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 might make more sense to just pass the tide context name to GetTideContextPolicy and have that func make the tide context required. That is all that RegisterOptionalContexts is used for now.
Not a big deal either way.
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.
We can also just revert part of my change such that tide skip its own status. What do you think ?
@cjwagner Please take a look. I ll be deploying this today for istio. Will keep you up to date. |
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.
/lgtm
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: cjwagner, sebastienvas The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Redoing #7457 as it takes forever to load.
Ref: https://goo.gl/cd9MEu which was discussed with @fejta @cjwagner @BenTheElder
Instead of getting required checks from the github api, it will use the branch protection configuration and infere the required context from it. We are also adding a optional options to Prow Presubmits.
Config would look like this:
#7140