-
Notifications
You must be signed in to change notification settings - Fork 84
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 build step with timeout feature #61
Conversation
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 you plan to add test codes?
|
||
import hudson.Extension; | ||
import hudson.Launcher; | ||
import hudson.model.*; |
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 don't use wildcard imports.
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
|
||
|
||
public class BuildStepWithTimeout extends Builder implements BuildStep { | ||
private /* final */ BuildTimeOutStrategy strategy; |
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 can be final
.
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
|
||
public class BuildStepWithTimeout extends Builder implements BuildStep { | ||
private /* final */ BuildTimeOutStrategy strategy; | ||
private BuildStep buildStep; |
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.
Would you consider to accept multiple steps?
That should make this feature more useful.
You can do that by using <f:hetero-list>
instead of <f:dropdownDescriptor>
.
This review may be helpful: https://github.com/jenkinsci/flexible-publish-plugin/pull/6/files
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.
To be honest, I think it's too dangerous :)
From my perspective somebody should implement "multiple steps" build step once and all other plugins should just re-use it. I don't think that it's good idea to re-implement such logic, because even now I can't guarantee that all kind of build steps are supported (i.e. conditional steps
doesn't work if it's used at child).
And in my case I don't need multiple steps - this "feature" was designed to split one global timeout on smallest chunks.
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.
Actually, wrapping another buildstep is always dangerous.
Problems should happen even wrapping a single buildstep.
I can't get why you think it gets more dangerous when supporting multiple steps.
conditional steps doesn't work if it's used at child
I'll see why this happen.
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.
Anyway, supporting multiple steps isn't required for this request.
|
||
public void setBuildStep(BuildStep buildStep) { | ||
this.buildStep = buildStep; | ||
} |
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 you need this setter, and buildStep
can be final
.
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
|
||
|
||
public boolean perform(final Build<?,?> build, final Launcher launcher, final BuildListener listener) throws InterruptedException, IOException { | ||
final Timer timer = new Timer("Timer-" + build.getDisplayName().replace(" ", "_"), 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.
You can use Trigger.timer
as in BuildTimeoutWrapper
.
http://javadoc.jenkins-ci.org/hudson/triggers/Trigger.html#timer
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
return "Run with timeout"; | ||
} | ||
|
||
public boolean isApplicable(Class<? extends AbstractProject> jobType) { |
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.
Let's annotate with Override
.
BuildStep buildstep = BuildTimeOutUtility.bindJSONWithDescriptor(req, formData, "buildStep", BuildStep.class); | ||
BuildTimeOutStrategy strategy = BuildTimeOutUtility.bindJSONWithDescriptor(req, formData, "strategy", BuildTimeOutStrategy.class); | ||
|
||
if (!(strategy instanceof AbsoluteTimeOutStrategy || strategy instanceof DeadlineTimeOutStrategy)) { |
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.
Add a new method like TimeOutStrategy#isApplicableAsBuildStep
and filter with that.
That's not a good idea to list up applicable classes in codes.
} | ||
|
||
public List<BuildTimeOutStrategyDescriptor> getStrategies() { | ||
return Jenkins.getInstance().getDescriptorList(BuildTimeOutStrategy.class); |
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 can apply TimeOutStrategy#isApplicableAsBuildStep
also here.
@@ -65,6 +65,8 @@ public boolean perform(AbstractBuild<?, ?> build, BuildListener listener, long e | |||
if (e != null) { | |||
e.interrupt(Result.ABORTED); | |||
} | |||
build.setResult(Result.ABORTED); |
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 happens if you don't add this?
(You mean e.interrupt
doesn't work?)
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.
Yes, it doesn't work for some reason. Interruption itself works as expected, but build result is different.
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 result set with e.inturrupt
isn't used as you suppressed InterruptedException
.
I don't think it's good idea to suppress InterruptException
as it may cause Jenkins work differently when you use BuildTimeOutWrapper
and BuildStepWithTimeout
.
As far as I tested the behavior, stacktraces aren't output into build logs (console logs), but are output only into system logs.
Can I know more details about why you want to suppress InterruptedException
?
@@ -65,6 +61,7 @@ public boolean perform(AbstractBuild<?, ?> build, BuildListener listener, long e | |||
if (e != null) { | |||
e.interrupt(Result.FAILURE); | |||
} | |||
build.setResult(Result.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.
ditto
d347ac7
to
cc8d661
Compare
Ok, everything is done (I hope). I added a couple of tests for basic mechanic. |
} | ||
|
||
@Test | ||
public void testTimeoutWasNotTriggered() throws IOException, ExecutionException, InterruptedException { |
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.
JFYI: It's easy for you to use throws Exception
in test codes.
project.getBuildersList().add(step); | ||
|
||
Future<FreeStyleBuild> future = project.scheduleBuild2(0, new Cause.UserIdCause()); | ||
FreeStyleBuild build = future.get(); |
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 have to test the result of the build with JenkinsRule#assertBuildStatusSuccess
or JenkinsRule#assertBuildStatus
Future<FreeStyleBuild> future = project.scheduleBuild2(0, new Cause.UserIdCause()); | ||
FreeStyleBuild build = future.get(); | ||
|
||
assertTrue(IOUtils.toString(build.getLogReader()).contains("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.
JFYI: JenkinsRule#assertLogContains
is useful (but there isn't assertLogNotContains
...)
|
||
try { | ||
timer.schedule(task, delay); | ||
return buildStep.perform((AbstractBuild) build, launcher, listener); |
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 generic types (AbstractBuild<?, ?>
) as they are warned by compilers.
Would you tell me more details about " I believe this is an important issue as conditional buildstep can be used as "multiple steps". |
Also: Add new tests to verify build results
As far as I know,
Sorry, I missed that problem. |
I plan to make a new release in the next weekend (11th or 12th Nov) |
Released 1.18. |
Sometimes it's much better to have several small timeouts instead of one global one.