-
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
Add support for EasyCLA #22742
Add support for EasyCLA #22742
Conversation
Added a new field `EasyCLAEnabled` in the plugins config and based on this field, if set will assign the claContextName to cla/easy-cla, else default to cla/linuxfoundation
Welcome @anusha94! |
Hi @anusha94. Thanks for your PR. I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
/cc @nikhita |
Fixes #22742 |
/ok-to-test |
Fixes #22721 |
/label tide/merge-method-squash |
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 the PR!
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: anusha94 The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@cjwagner Could you please review again? |
/lgtm |
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 have concerns over dueling contexts
prow/plugins/cla/cla.go
Outdated
// Valid status values are cla/linuxfoundation and EasyCLA | ||
if contains(cc.CLAContextNames, status.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.
Can we rewrite this so that it iterates through statuses to determine CLA yes/no first, and then once outside the for loop, applies labels accordingly? I'd like to avoid wasting GitHub tokens on label apply/remove calls while we decide which status wins if they start competing.
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.
Is combined.Statuses
sorted at this point? or could we be walking these in random order?
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.
@spiffxp Can you please elaborate on competing statuses? Going by the existing code if status.Context == claContextName
, I assumed the for loop
should not continue if it is not one of cla/linuxfoundation
or EasyCLA
Or are you saying this entire for loop
should be rewritten such that applying of ClaNo
or ClaYes
should be outside the for loop?
Thanks.
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.
Is combined.Statuses sorted at this point? or could we be walking these in random order?
@mrbobbytables Do you know about the sort order of combined.Statuses
? Or rather, how can I check / verify the order?
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.
Can you please elaborate on competing statuses?
I missed the break
down below. You're right, one of them will win. But will it be the same one every time? And how will I know which one that is?
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 removed the break
statement so that all contexts will be processed.
context: "EasyCLA", | ||
state: "failure", |
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.
Since the plugin now supports multiple contexts, I think it's fair to ask the test cases be written to test multiple contexts (or that you add a new Test that supports this).
I would like to see test cases with multiple contexts having conflicting values, so we can confirm that it's first-context-wins in all cases
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.
e.g. I would like to see something like
contexts:
"cla/linuxfoundation": "success"
"EasyCLA": "failure"
and vice-versa
I removed the In |
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'm not confident enough to deploy this plugin in a manner that listens to two status contexts simultaneously yet. I wrote down some test cases I would want to see exercised to ensure consistency vs. a race between last-context-reporting-wins.
I can be convinced to allow the EasyCLA check to report to PRs as non-blocking, without this plugin configured to listen to it, to allow us to gather data on how often we encounter conflict between the old CLA check and the new CLA check.
// Only consider "cla/linuxfoundation" status. | ||
if status.Context == claContextName { | ||
// Only consider "cla/linuxfoundation" or "EasyCLA" status | ||
if contains(cc.CLAContextNames, status.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.
do we know if combined.Statuses
is sorted by the time we get here?
|
||
// No need to consider other contexts once you find the one you need. | ||
break |
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.
Since there's no break anymore, now we are potentially adding/removing labels twice.
What I asked for in last review was to make the decision before acting, e.g.
claState := github.StatusPending
for _, status := range combined.Statuses {
// code that sets claState
}
// code that sets labels based on claState
} | ||
var statuses []github.Status | ||
for context, state := range tc.contexts { | ||
statuses = append(statuses, github.Status{ |
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.
re: my "are the statuses sorted" comment above, your unit tests are relying on this being the sort
what I lack is proof that you've verified this sort is what you actually see in production (show me code that presorts the statuses, or docs from github guaranteeing the order in which they deliver statuses)
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 hear you. But I could not find proof for sort order. Here is the docs for getting combined status
and the client code to get the same
Any pointers on how we can validate the order?
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 best way to ensure something is sorted is to sort it. So, sort the contexts before you iterate over them. Or, flip the loop so that you iterate over the context names that you care about in the order you care about, and then see if they're contained in combined statuses
cc := plugins.CLAConfig{ | ||
CLAContextNames: []string{"cla/linuxfoundation", "EasyCLA"}, | ||
} | ||
if err := handle(fc, logrus.WithField("plugin", pluginName), se, cc); err != 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.
OK, I think I assumed there was less duplication of logic before
So the way I read the StatusEvent handling code, is that it will respond to whatever the status is. So if the CLA plugin is configured to listen to two CLA statuses, we will have a race between which of the two statuses reports in first. Slowest status wins.
I think what would provide more consistency is to try to de-dupe the logic and do what handleComment
does: get the PR's combined statuses, and ensure one of them consistently wins the race.
e.g. let's say cla/linuxfoundation consistently wins:
# happy path
state:
cla/linuxfoundation: pending
EasyCLA: pending
labels: []
receive:
cla/linuxfoundation: success
result:
add: "cncf-cla: yes"
# conflict: EasyCLA arrives last
state:
cla/linuxfoundation: success
EasyCLA: pending
labels: ["cncf-cla: yes"]
receive:
EasyCLA: failure
result:
# do nothing
# conflict: cla/linuxfoundation arrives last
state:
cla/linuxfoundation: pending
EasyCLA: success
labels: ["cncf-cla: yes"]
receive:
cla/linuxfoundation: failure
result:
add: "cncf-cla: no"
remove: "cncf-cla: yes"
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 if the CLA plugin is configured to listen to two CLA statuses
From the docs, The most recent status for each context is returned
.
I think my question is - are EasyCLA
and cla/linuxfoundation
considered as two different contexts or different names for a single CLA
context? How does getting combined status here work? Combined status is still going to return both the contexts - how do we know which one is the latest?
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 my question is - are EasyCLA and cla/linuxfoundation considered as two different contexts or different names for a single CLA context
Well, I'm assuming I'm going to see two entries, one called cla/linuxfoundation
and one called EasyCLA
while the CNCF has both things running simultaneously on their end. So they're different contexts. You're updating the plugin to decide which one to treat as the authoritative source of truth from the CNCF. This allows us to have the plugin pay attention to the new EasyCLA check, but defer to the old cla/linuxfoundation check as authoritative, without having to change anything.
Another possibly simpler option is to roll back some of what you've done, and update the plugin to listen to one-and-only-one context. In this scenario we would:
- make the plugin listen to a configurable context
- start with cla/linuxfoundation as this plugin's source of truth
- setup EasyCLA on the CNCF's end to start reporting to PRs
- setup prow/branch-protector to treat EasyCLA contexts as non-blocking
- wait
- generate a report that shows over time, for all PRs within a given window, PRs where cla/linuxfoundation and EasyCLA differed
- figure out why and fix
- wait again
- generate report again
- repeat until there is no difference, and then we change branch-protector to make the EasyCLA context required, the cla/linuxfoundation context non-blocking, and the cla plugin to listen to EasyCLA to apply "cncf-cla: yes" labels
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.
How does getting combined status here work? Combined status is still going to return both the contexts - how do we know which one is the latest?
What I was saying above is that the handle
function doesn't call GetCombinedStatus, it only consider the status from the StatusEvent it's handling. So it will get called once whenever cla/linuxfoundation
is update, and again whenever EasyCLA
is updated, and there's no way to guarantee which of those is going to arrive first.
Calling GetCombinedStatus to get both contexts is the point. We don't care which one came in latest, we only care that it came in for the commit we're considering, and that the authoritative context (if set) always overrides the others.
Again, I'm thinking this may all be too confusing, and it might be simpler to support a single (configurable) context only. But we need to see how EasyCLA behaves live (in terms of responsiveness, reliability, consistency, and agreement with cla/linuxfoundation) before I will ever consider changing our workflow to pay attention to that over cla/linuxfoundation.
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.
EasyCLA has been enabled for the k/org repo in a non-blocking way as a test.
For some additional information, EasyCLA is currently in use by 3 other CNCF projects:
- Open telemetry (47 repos)
- grpc (26 repos)
- cloud custodian (6 repos)
For gRPC it's been some time (most of the kinks in the project were worked out with this one), I don't know when it was enabled for Otel or cloud custodian.
The LF has said if we do have problems we can roll back.
contexts: map[string]string{ | ||
"cla/linuxfoundation": "failure", | ||
"EasyCLA": "success", | ||
}, |
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 the refactor down here. I think I'm asking for a similar refactor to the status event handling test
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.
sure. will do :)
/hold |
The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs. This bot triages issues and PRs according to the following rules:
You can:
Please send feedback to sig-contributor-experience at kubernetes/community. /lifecycle stale |
/remove-lifecycle stale |
/close |
@MadhavJivrajani: Closed this PR. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Added a new field
EasyCLAEnabled
in the plugins config and based onthis field, if set will assign the
claContextName
tocla/easy-cla
, elsedefault to
cla/linuxfoundation
Fixes #22721