Skip to content

Commit

Permalink
[JENKINS-37781] Adding Stage.when to specify if a stage should run or…
Browse files Browse the repository at this point in the history
… not
  • Loading branch information
rsandell committed Oct 26, 2016
1 parent 198a423 commit dfab9e2
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 37 deletions.
Expand Up @@ -7,13 +7,17 @@
*/
public class ModelASTScriptBlock extends ModelASTStep {
public ModelASTScriptBlock(Object sourceLocation) {
this(sourceLocation, "script");
}

protected ModelASTScriptBlock(Object sourceLocation, String name) {
super(sourceLocation);
this.setName("script");
this.setName(name);
}

@Override
public String toGroovy() {
StringBuilder result = new StringBuilder("script {\n");
StringBuilder result = new StringBuilder(getName()).append(" {\n");
if (getArgs() != null
&& getArgs() instanceof ModelASTSingleArgument
&& ((ModelASTSingleArgument) getArgs()).getValue()!=null
Expand Down
Expand Up @@ -18,6 +18,7 @@ public final class ModelASTStage extends ModelASTElement {
private ModelASTAgent agent;
private List<ModelASTBranch> branches = new ArrayList<ModelASTBranch>();
private ModelASTPostStage post;
private ModelASTWhen when;

public ModelASTStage(Object sourceLocation) {
super(sourceLocation);
Expand All @@ -35,6 +36,9 @@ public JSONObject toJSON() {
if (agent != null) {
o.accumulate("agent", agent.toJSON());
}
if (when != null) {
o.accumulate("when", when.toJSON());
}

if (post != null) {
o.accumulate("post", post.toJSON());
Expand All @@ -52,6 +56,9 @@ public void validate(final ModelValidator validator) {
if (agent != null) {
agent.validate(validator);
}
if (when != null) {
when.validate(validator);
}
if (post != null) {
post.validate(validator);
}
Expand All @@ -66,6 +73,10 @@ public String toGroovy() {
result.append(agent.toGroovy());
}

if (when != null) {
result.append(when.toGroovy());
}

result.append("steps {\n");
if (branches.size() > 1) {
result.append("parallel(");
Expand Down Expand Up @@ -107,6 +118,10 @@ public void removeSourceLocation() {
if (post != null) {
post.removeSourceLocation();
}

if (when != null) {
when.removeSourceLocation();
}
}

public String getName() {
Expand Down Expand Up @@ -141,13 +156,22 @@ public void setPost(ModelASTPostStage post) {
this.post = post;
}

public ModelASTWhen getWhen() {
return when;
}

public void setWhen(ModelASTWhen when) {
this.when = when;
}

@Override
public String toString() {
return "ModelASTStage{" +
"name='" + name + '\'' +
", agent=" + agent +
", branches=" + branches +
", post=" + post +
", when=" + when +
"}";
}

Expand All @@ -174,6 +198,10 @@ public boolean equals(Object o) {
if (getPost() != null ? !getPost().equals(that.getPost()) : that.getPost() != null) {
return false;
}
if (getWhen() != null ? !getWhen().equals(that.getWhen()) : that.getWhen() != null) {
return false;
}

return getBranches() != null ? getBranches().equals(that.getBranches()) : that.getBranches() == null;

}
Expand All @@ -184,6 +212,7 @@ public int hashCode() {
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
result = 31 * result + (getAgent() != null ? getAgent().hashCode() : 0);
result = 31 * result + (getBranches() != null ? getBranches().hashCode() : 0);
result = 31 * result + (getWhen() != null ? getWhen().hashCode() : 0);
return result;
}
}
@@ -0,0 +1,51 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

package org.jenkinsci.plugins.pipeline.modeldefinition.ast;

import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator;

/**
* Represents a block for when/if a {@link ModelASTStage} will be executed or not.
*/
public class ModelASTWhen extends ModelASTScriptBlock { //Model wise we don't really extend it but there are plenty of reuse
public ModelASTWhen(Object sourceLocation) {
super(sourceLocation, "when");
}

@Override
public String toString() {
return "ModelASTWhen{" +
"name='" + getName() + '\'' +
", args=" + getArgs() +
"}";
}

@Override
public void validate(ModelValidator validator) {
super.validate(validator);
validator.validateElement(this);
}
}
Expand Up @@ -45,6 +45,7 @@
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTools;
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTrigger;
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTriggers;
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTWhen;


public interface ModelValidator {
Expand All @@ -68,6 +69,8 @@ public interface ModelValidator {

boolean validateElement(ModelASTStep step);

boolean validateElement(ModelASTWhen when);

boolean validateElement(ModelASTMethodCall methodCall);

boolean validateElement(ModelASTJobProperties jobProperties);
Expand Down
Expand Up @@ -50,6 +50,9 @@ public class Stage implements NestedModel, Serializable {
@Whitelisted
PostStage post

@Whitelisted
Closure<Boolean> when

@Whitelisted
Stage name(String n) {
this.name = n
Expand Down Expand Up @@ -80,6 +83,12 @@ public class Stage implements NestedModel, Serializable {
return this
}

@Whitelisted
Stage when(Closure<Boolean> when) {
this.when = when
return this
}

@Override
@Whitelisted
public void modelFromMap(Map<String,Object> m) {
Expand Down
Expand Up @@ -61,6 +61,7 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTPostBuild
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTScriptBlock
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTools
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTreeStep
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTWhen
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ErrorCollector
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.JSONErrorCollector
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator
Expand Down Expand Up @@ -186,6 +187,13 @@ class JSONParser {
stage.post = parsePostStage(object)
}
}

if (j.has("when")) {
def object = j.getJSONObject("when")
if (!object.isNullObject()) {
stage.when = parseWhen(object)
}
}
return stage

}
Expand Down Expand Up @@ -391,6 +399,13 @@ class JSONParser {
return scriptBlock
}

public @CheckForNull ModelASTWhen parseWhen(JSONObject j) {
ModelASTWhen scriptBlock = new ModelASTWhen(j)
scriptBlock.args = parseArgumentList(j.getJSONObject("arguments"))

return scriptBlock
}

public @CheckForNull ModelASTTreeStep parseTreeStep(JSONObject j) {
ModelASTTreeStep step = new ModelASTTreeStep(j)
step.name = j.getString("name")
Expand Down
Expand Up @@ -64,6 +64,7 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTScriptBlock
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStep
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTools
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTreeStep
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTWhen
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ErrorCollector
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidatorImpl
Expand Down Expand Up @@ -322,6 +323,9 @@ class ModelParser {
case 'agent':
stage.agent = parseAgent(s)
break
case 'when':
stage.when = parseWhen(s)
break
case 'steps':
def stepsBlock = matchBlockStatement(s);
stage.branches.addAll(parseStepsBlock(asBlock(stepsBlock.body.code)))
Expand Down Expand Up @@ -579,19 +583,27 @@ class ModelParser {

return thisStep
}

public ModelASTWhen parseWhen(Statement st) {
return parseScriptBlockInternal(st, new ModelASTWhen(st), "When")
}

/**
* Parses a statement into a {@link ModelASTScriptBlock}
*/
public ModelASTScriptBlock parseScriptBlock(Statement st) {
ModelASTScriptBlock scriptBlock = new ModelASTScriptBlock(st)
return parseScriptBlockInternal(st, new ModelASTScriptBlock(st), "Script")
}

private <T extends ModelASTScriptBlock> T parseScriptBlockInternal(Statement st, T scriptBlock, String pronoun) {
// TODO: Probably error out for cases with parameters?
def bs = matchBlockStatement(st);
if (bs != null) {
ModelASTSingleArgument groovyBlock = new ModelASTSingleArgument(bs.body)
groovyBlock.value = ModelASTValue.fromConstant(getSourceText(bs.body.code), bs.body.code)
scriptBlock.args = groovyBlock
} else {
errorCollector.error(scriptBlock, "Script step without a script block")
errorCollector.error(scriptBlock, "${pronoun} step without a block")
}

return scriptBlock
Expand Down
Expand Up @@ -59,6 +59,7 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTValue
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTBuildCondition
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTAgent
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTools
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTWhen
import org.jenkinsci.plugins.pipeline.modeldefinition.model.BuildCondition
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Agent
import org.jenkinsci.plugins.pipeline.modeldefinition.model.JobProperties
Expand Down Expand Up @@ -191,6 +192,11 @@ class ModelValidatorImpl implements ModelValidator {
return valid
}

public boolean validateElement(ModelASTWhen when) {
//TODO can we evaluate if the closure will return something that can be tries for true?
}


public boolean validateElement(@Nonnull ModelASTStep step) {
boolean valid = true

Expand Down

0 comments on commit dfab9e2

Please sign in to comment.