-
Improvement
-
Resolution: Unresolved
-
Minor
-
None
-
Powered by SuggestiMate
When inside the `retry{}` clause, it may be useful to know which attempt number this is (e.g. to `archiveArtifacts` the debug logs under a uniquely named archive). Expose the retry number as a groovy and/or environment variable.
[JENKINS-49341] Pipeline retry clause : expose the retry number
Also, we could instead do something like env.RETRIES_REMAINING - that's actually simpler, since RetryStepExecution.Callback actually determines when to stop retrying based on counting down to 0 from the specified retry count, so I don't need to do any changes other than just dumping that into the environment.
I think the environment representation would be used in `sh` clauses and so shell script would take it into numeric consideration if needed. For groovy it can remain a number if that's easier.
For starting value in my workaround, 1 was a starting value. Or actually, in the code it went like
`script { def retrynum = 0; retry { try { retrynum++; ... } / catch...} }`
So as the build step processing actually started, the value became 1.
Yes, at least for unique naming - dumping a raw unique value is also good
Even better if the same variable could be "defined" even if empty (or 0) when not inside a retry clause, so accessing it in any context is not an error
jimklimov - that's harder, annoyingly. I don't think I can do that outside of retry. But if you do something like if (env.RETRY_COUNT == null), that'll work fine. It's only if you try to do if (RETRY_COUNT ...) that you'll hit Groovy errors.
Will this be usable outside of pipelines, or is it out of scope?
One of my projects is not using pipelines, but xml job configs. Basically, we've got a bunch of jobs with:
<builders>
<hudson.tasks.Shell>
<command>/bin/sh /some/script.sh ...</command>
</hudson.tasks.Shell>
</builders>
It would be nice to utilize an env var in that command to determine if the command is going to fail for the last time.
Nevermind. I should have been looking into naginator plugin, which is what we actually use to trigger retries.
This is the workaround I thought I'd come up with for this:
environment { retryCount = '0' } stages { stage ('try') { options { retry(3) } steps { script { tryCount = env.retryCount as Integer echo "first step: tryCount = ${tryCount}" if(tryCount > 0) { echo 'entered catcher' } tryCount++ echo "after bump: tryCount = ${tryCount}" env.retryCount = tryCount as String echo "After set: env.retryCount = ${env.retryCount}" error "${env.retryCount}" } } }
But i can't get the env.retryCount to stick, even immediately after setting it:
[Pipeline] echo first step: tryCount = 0 [Pipeline] echo after bump: tryCount = 1 [Pipeline] echo After set: env.retryCount = 0 [Pipeline] error [Pipeline] } [Pipeline] // script [Pipeline] } ERROR: 0 Retrying [Pipeline] { [Pipeline] script [Pipeline] { [Pipeline] echo first step: tryCount = 0 [Pipeline] echo after bump: tryCount = 1 [Pipeline] echo After set: env.retryCount = 0 [Pipeline] error [Pipeline] } [Pipeline] // script [Pipeline] } ERROR: 0 Retrying [Pipeline] { [Pipeline] script [Pipeline] { [Pipeline] echo first step: tryCount = 0 [Pipeline] echo after bump: tryCount = 1 [Pipeline] echo After set: env.retryCount = 0
Why isn't that env.tryCount getting set, even locally?
Also, it seems that the entire environment is reset in a retry, including any changes made to environment variables?
How can we get the retry count/remaining/whatever to use in our stages?
thanks.
UPDATE: I knew about this too, but it's still tricky. As explained extremely well by Szymon Stepniak in this post, you can't alter env vars set implicitly in an environment clause.
By moving the variable setting into a script block in a stage, it all works as intended.
pipeline { agent any stages { stage ('init') { steps { script { env.retryCount = '0' } } } stage ('try') { options { retry(3) } steps { script { tryCount = env.retryCount as Integer echo "first step: tryCount = ${tryCount}" if(tryCount > 0) { echo 'entered catcher' } tryCount++ echo "after bump: tryCount = ${tryCount}" env.retryCount = "${tryCount}" echo "After set: env.retryCount = ${env.retryCount}" error "${env.retryCount}" } } } } }
first step: tryCount = 0 [Pipeline] echo after bump: tryCount = 1 [Pipeline] echo After set: env.retryCount = 1 [Pipeline] error [Pipeline] } [Pipeline] // script [Pipeline] } ERROR: 1 Retrying [Pipeline] { [Pipeline] script [Pipeline] { [Pipeline] echo first step: tryCount = 1 [Pipeline] echo entered catcher [Pipeline] echo after bump: tryCount = 2 [Pipeline] echo After set: env.retryCount = 2 [Pipeline] error [Pipeline] } [Pipeline] // script [Pipeline] } ERROR: 2 Retrying [Pipeline] { [Pipeline] script [Pipeline] { [Pipeline] echo first step: tryCount = 2 [Pipeline] echo entered catcher [Pipeline] echo after bump: tryCount = 3 [Pipeline] echo After set: env.retryCount = 3 [Pipeline] error [Pipeline] } [Pipeline] // script [Pipeline] } [Pipeline] // retry [Pipeline] } [Pipeline] // stage [Pipeline] } [Pipeline] // node [Pipeline] End of Pipeline [Checks API] No suitable checks publisher found. ERROR: 3 Finished: FAILURE
This has be "in progress" for 4 years. Is there any progress on this? The workarounds below are pretty hacky, and don't play well with parallel steps. I'm trying to keep track of retried steps in parallel stages.
So I can put this in the environment - of course, then it's "2", not 2 - i.e., a String, not an int. I'm trying to think if there's a way I can get around that and have it actually be an int but I don't think I'll be able to.
What should the count be starting at? First attempt is 0, second attempt (a.k.a. the first retry) is 1, etc? Or first attempt is 1, second attempt is 2, etc?