-
Notifications
You must be signed in to change notification settings - Fork 77
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 special case for retry step #77
base: master
Are you sure you want to change the base?
Conversation
Update CHANGELOG.md Remove unnecessary import
// special-case the retry() step to run up to count times | ||
int left = _args[0] | ||
Closure body = _args[1] | ||
while (left > 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.
This is a greatly simplified implementation of RetryStepExecution
@awittha could you please review this when you have a chance? |
I am not sold on this idea. In general I do not want to special-case any pipeline steps unless
My main objection is running the There are three possible correct quantities to run a
Because of this, I can't say with confidence what the one right behavior to bake into the special case actually is. So, I don't want to ship one behavior that will be wrong for 2/3 of the test situations! |
Why wouldn't folks just choose the right behavior and mock up def "all attempts fail"() {
setup:
getPipelineMock("retry")(_ as int, _ as Closure) >> { _args ->
def arguments = _args[0]
def max = arguments[0]
def body = arguments[1]
for(int i = 0; i < max; i++) {
body()
}
// simulate failure
throw new IDontExactlyRememberTheRightException()
}
when:
someScript.run()
// has a retry(3)
then:
3 * getPipelineMock("someStepInsideTheRetry")()
}
def "intermittent failure overcome by retry"() {
setup:
getPipelineMock("retry")(_ as int, _ as Closure) >> { _args ->
def arguments = _args[0]
def max = arguments[0]
def body = arguments[1]
for(int i = 0; i < max - 1; i++) {
body()
}
}
when:
someScript.run()
// has a retry(3)
then:
2 * getPipelineMock("someStepInsideTheRetry")()
}
def "no problems in retry"() {
setup:
getPipelineMock("retry")(_ as int, _ as Closure) >> { _args ->
def arguments = _args[0]
def body = arguments[1]
body()
}
when:
someScript.run()
// has a retry(3)
then:
1 * getPipelineMock("someStepInsideTheRetry")()
} Well, they can't right now, because jenkins-spock already special-cases any step whose last argument is a Closure, to run that closure exactly once. So, you can test the "retry runs w/out any problem" case, but it's much more confusing to wire up a "intermittent failure eventually is overcome" situation, and it is impossible (I think) to test the "all retry attempts failed" case. I think that jenkins-spock should change so that the set of steps that get special-casing of "execute the trailing closure" is configurable. (default: all, to match current behavior and most use-cases) Additionally, a real Documentation site (not just hosted GroovyDoc) is needed to lay out examples like this. There isn't really a single "right" answer for ( As it stands, I do not think that adding a special case to always run the body of Additionally, |
In summary:
I believe Jenkins-Spock needs a different solution for |
I don't agree with this. The only correct behaviour is to retry the body up to
I don't understand what you mean by this. Are you referring to user implemented I am happy with the ability to mock up the right behaviour for |
Summary
Add special case for
retry
step.Fixes #76
Additional Details
N/A
Checklist
Testing
(Remove this checklist and replace it with "N/A - no code changes" if this PR does not modify source code)
Documentation
(Remove this checklist and replace it with "N/A - no code changes" if this PR does not modify source code)
CHANGELOG.md
with a brief description of my changes.CONTRIBUTING.md
and have followed its guidance.