Skip to content

Commit 4eede64

Browse files
committed
Merge remote-tracking branch 'origin' into JENKINS-48523
Conflicts: pipeline-model-definition/src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/AbstractModelDefTest.java pipeline-model-definition/src/test/java/org/jenkinsci/plugins/pipeline/modeldefinition/WhenStageTest.java
2 parents 4ed6d73 + a85f7c5 commit 4eede64

File tree

28 files changed

+599
-39
lines changed

28 files changed

+599
-39
lines changed

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pipeline {
2020
environment {
2121
GIT_COMMITTER_NAME = "jenkins"
2222
GIT_COMMITTER_EMAIL = "[email protected]"
23-
NEWER_CORE_VERSION = "2.89.2"
23+
NEWER_CORE_VERSION = "2.89.3"
2424
}
2525

2626

pipeline-model-api/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<parent>
2828
<groupId>org.jenkinsci.plugins</groupId>
2929
<artifactId>pipeline-model-parent</artifactId>
30-
<version>1.2.7-SNAPSHOT</version>
30+
<version>1.2.8-SNAPSHOT</version>
3131
</parent>
3232

3333
<groupId>org.jenkinsci.plugins</groupId>

pipeline-model-definition/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<parent>
2828
<groupId>org.jenkinsci.plugins</groupId>
2929
<artifactId>pipeline-model-parent</artifactId>
30-
<version>1.2.7-SNAPSHOT</version>
30+
<version>1.2.8-SNAPSHOT</version>
3131
</parent>
3232

3333
<groupId>org.jenkinsci.plugins</groupId>

pipeline-model-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/model/conditions/Changed.groovy

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,17 @@ class Changed extends BuildCondition {
4141
Result execResult = getExecutionResult(r)
4242
// Only look at the previous completed build.
4343
WorkflowRun prev = r.getPreviousCompletedBuild()
44+
45+
// Get the *worst* result of either the execution or the run. If the run's result is null, that's effectively
46+
// SUCCESS.
47+
Result runResult = execResult.combine(r.getResult() ?: Result.SUCCESS)
48+
4449
// If there's no previous build, we're inherently changed.
4550
if (prev == null) {
4651
return true
47-
}
48-
// If the current build's result isn't null (i.e., it's got a specified status), and it's different than the
49-
// previous build's result, we're changed.
50-
else if ((execResult != null && prev.getResult() != execResult) ||
51-
(r.getResult() != null && prev.getResult() != r.getResult())) {
52-
return true
53-
}
54-
// If the current build's result is null and the previous build's result is not SUCCESS, we're changed.
55-
else if ((execResult == Result.SUCCESS && prev.getResult() != Result.SUCCESS) ||
56-
(r.getResult() == null && prev.getResult() != Result.SUCCESS)) {
57-
return true
58-
}
59-
// And in any other condition, we're not changed, so return false.
60-
else {
61-
return false
52+
} else {
53+
// Otherwise, compare the combined execution/run result to the previous result.
54+
return runResult != prev.getResult()
6255
}
6356
}
6457

pipeline-model-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/Converter.groovy

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import org.codehaus.groovy.control.customizers.ImportCustomizer
4141
import org.jenkinsci.plugins.pipeline.modeldefinition.ASTSchema
4242
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTPipelineDef
4343
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStep
44+
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.DeclarativeValidatorContributor
4445
import org.jenkinsci.plugins.workflow.cps.CpsThread
4546
import org.jenkinsci.plugins.workflow.cps.GroovyShellDecorator
4647

@@ -94,16 +95,18 @@ class Converter {
9495
* Converts a script at a given URL into {@link ModelASTPipelineDef}
9596
*
9697
* @param src A URL pointing to a Pipeline script
98+
* @param enabledOptionalValidators A list of optional validator classes that should be enabled. Defaults to empty.
9799
* @return the converted script
98100
*/
99-
static ModelASTPipelineDef urlToPipelineDef(URL src) {
101+
static ModelASTPipelineDef urlToPipelineDef(URL src,
102+
final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = []) {
100103
CompilationUnit cu = new CompilationUnit(
101104
makeCompilerConfiguration(),
102105
new CodeSource(src, new Certificate[0]),
103106
getCompilationClassLoader())
104107
cu.addSource(src)
105108

106-
return compilationUnitToPipelineDef(cu)
109+
return compilationUnitToPipelineDef(cu, enabledOptionalValidators)
107110
}
108111

109112
private static GroovyClassLoader getCompilationClassLoader() {
@@ -115,16 +118,18 @@ class Converter {
115118
* Converts a string containing a Pipeline script into {@link ModelASTPipelineDef}
116119
*
117120
* @param script A string containing a Pipeline script
121+
* @param enabledOptionalValidators A list of optional validator classes that should be enabled. Defaults to empty.
118122
* @return the converted script
119123
*/
120-
static ModelASTPipelineDef scriptToPipelineDef(String script) {
124+
static ModelASTPipelineDef scriptToPipelineDef(String script,
125+
final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = []) {
121126
CompilationUnit cu = new CompilationUnit(
122127
makeCompilerConfiguration(),
123128
new CodeSource(new URL("file", "", DEFAULT_CODE_BASE), (Certificate[]) null),
124129
getCompilationClassLoader())
125130
cu.addSource(PIPELINE_SCRIPT_NAME, script)
126131

127-
return compilationUnitToPipelineDef(cu)
132+
return compilationUnitToPipelineDef(cu, enabledOptionalValidators)
128133
}
129134

130135
private static CompilerConfiguration makeCompilerConfiguration() {
@@ -141,21 +146,24 @@ class Converter {
141146

142147
return cc
143148
}
149+
144150
/**
145151
* Takes a {@link CompilationUnit}, copmiles it with the {@link ModelParser} injected, and returns the resulting
146152
* {@link ModelASTPipelineDef}
147153
*
148154
* @param cu {@link CompilationUnit} assembled by another method.
155+
* @param enabledOptionalValidators A list of optional validator classes that should be enabled. Defaults to empty.
149156
* @return The converted script
150157
*/
151-
private static ModelASTPipelineDef compilationUnitToPipelineDef(CompilationUnit cu) {
158+
private static ModelASTPipelineDef compilationUnitToPipelineDef(CompilationUnit cu,
159+
final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = []) {
152160
final ModelASTPipelineDef[] model = new ModelASTPipelineDef[1]
153161

154162
cu.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
155163
@Override
156164
void call(SourceUnit source) throws CompilationFailedException {
157165
if (model[0] == null) {
158-
model[0] = new ModelParser(source).parse(true)
166+
model[0] = new ModelParser(source, enabledOptionalValidators).parse(true)
159167
}
160168
}
161169
}, CANONICALIZATION)
@@ -165,24 +173,26 @@ class Converter {
165173
return model[0]
166174
}
167175

168-
static List<ModelASTStep> scriptToPlainSteps(String script) {
176+
static List<ModelASTStep> scriptToPlainSteps(String script,
177+
final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = []) {
169178
CompilationUnit cu = new CompilationUnit(
170179
makeCompilerConfiguration(),
171180
new CodeSource(new URL("file", "", DEFAULT_CODE_BASE), (Certificate[]) null),
172181
getCompilationClassLoader())
173182
cu.addSource(PIPELINE_SCRIPT_NAME, script)
174183

175-
return compilationUnitToPlainSteps(cu)
184+
return compilationUnitToPlainSteps(cu, enabledOptionalValidators)
176185
}
177186

178-
private static List<ModelASTStep> compilationUnitToPlainSteps(CompilationUnit cu) {
187+
private static List<ModelASTStep> compilationUnitToPlainSteps(CompilationUnit cu,
188+
final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = []) {
179189
final List<ModelASTStep>[] model = new List<ModelASTStep>[1]
180190

181191
cu.addPhaseOperation(new CompilationUnit.SourceUnitOperation() {
182192
@Override
183193
void call(SourceUnit source) throws CompilationFailedException {
184194
if (model[0] == null) {
185-
model[0] = new ModelParser(source).parsePlainSteps(source.AST)
195+
model[0] = new ModelParser(source, enabledOptionalValidators).parsePlainSteps(source.AST)
186196
}
187197
}
188198
}, CANONICALIZATION)

pipeline-model-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/parser/ModelParser.groovy

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import org.jenkinsci.plugins.pipeline.modeldefinition.agent.DeclarativeAgentDesc
4848
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.*
4949
import org.jenkinsci.plugins.pipeline.modeldefinition.ModelStepLoader
5050
import org.jenkinsci.plugins.pipeline.modeldefinition.model.BuildCondition
51+
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.DeclarativeValidatorContributor
5152
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ErrorCollector
5253
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator
5354
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidatorImpl
@@ -92,14 +93,26 @@ class ModelParser implements Parser {
9293

9394
private final Run<?,?> build
9495

96+
@Deprecated
9597
ModelParser(SourceUnit sourceUnit) {
96-
this(sourceUnit, null)
98+
this(sourceUnit, [], null)
9799
}
98100

101+
@Deprecated
99102
ModelParser(SourceUnit sourceUnit, @CheckForNull FlowExecution execution) {
103+
this(sourceUnit, [], execution)
104+
}
105+
106+
ModelParser(SourceUnit sourceUnit, @Nonnull List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators) {
107+
this(sourceUnit, enabledOptionalValidators, null)
108+
}
109+
110+
ModelParser(SourceUnit sourceUnit,
111+
@Nonnull List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators,
112+
@CheckForNull FlowExecution execution) {
100113
this.sourceUnit = sourceUnit
101114
this.errorCollector = new SourceUnitErrorCollector(sourceUnit)
102-
this.validator = new ModelValidatorImpl(errorCollector, execution)
115+
this.validator = new ModelValidatorImpl(errorCollector, enabledOptionalValidators, execution)
103116
this.lookup = DescriptorLookupCache.getPublicCache()
104117
Queue.Executable executable = null
105118
if (execution != null) {
@@ -1165,7 +1178,18 @@ class ModelParser implements Parser {
11651178
*/
11661179
protected ModelASTValue parseArgument(Expression e) {
11671180
if (e instanceof ConstantExpression) {
1168-
return ModelASTValue.fromConstant(e.value, e)
1181+
Object val = e.value
1182+
if (val instanceof BigDecimal) {
1183+
val = val.doubleValue()
1184+
} else if (val instanceof BigInteger) {
1185+
if (val > Long.MAX_VALUE || val < Long.MIN_VALUE) {
1186+
errorCollector.error(ModelASTValue.fromConstant(-1, e), Messages.ModelParser_BigIntegerValue())
1187+
val = -1
1188+
} else {
1189+
val = val.longValue()
1190+
}
1191+
}
1192+
return ModelASTValue.fromConstant(val, e)
11691193
}
11701194
if (e instanceof GStringExpression) {
11711195
String rawSrc = getSourceText(e)

pipeline-model-definition/src/main/groovy/org/jenkinsci/plugins/pipeline/modeldefinition/validator/ModelValidatorImpl.groovy

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,34 @@ import javax.annotation.Nonnull
6767
class ModelValidatorImpl implements ModelValidator {
6868

6969
private final ErrorCollector errorCollector
70+
private final List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators = new ArrayList<>()
7071
private transient DescriptorLookupCache lookup
7172
private transient FlowExecution execution
73+
private transient List<DeclarativeValidatorContributor> validatorContributors
7274

73-
ModelValidatorImpl(ErrorCollector e, FlowExecution execution = null) {
75+
ModelValidatorImpl(@Nonnull ErrorCollector e, FlowExecution execution = null) {
76+
this(e, [], execution)
77+
}
78+
79+
ModelValidatorImpl(@Nonnull ErrorCollector e,
80+
@Nonnull List<Class<? extends DeclarativeValidatorContributor>> enabledOptionalValidators,
81+
FlowExecution execution = null) {
7482
this.errorCollector = e
83+
this.enabledOptionalValidators.addAll(enabledOptionalValidators)
7584
this.execution = execution
7685
this.lookup = DescriptorLookupCache.getPublicCache()
7786
}
7887

88+
private List<DeclarativeValidatorContributor> getContributors() {
89+
if (validatorContributors == null) {
90+
validatorContributors = DeclarativeValidatorContributor.all().findAll { c ->
91+
!c.isOptional() || c.class in enabledOptionalValidators
92+
}
93+
}
94+
95+
return validatorContributors
96+
}
97+
7998
DescriptorLookupCache getLookup() {
8099
return lookup
81100
}
@@ -763,7 +782,7 @@ class ModelValidatorImpl implements ModelValidator {
763782
}
764783

765784
private boolean validateFromContributors(ModelASTElement element, boolean isValid, boolean isNested = false) {
766-
boolean contributorsValid = DeclarativeValidatorContributor.all().collect { contributor ->
785+
boolean contributorsValid = getContributors().collect { contributor ->
767786
List<String> errors
768787
if (!(element instanceof ModelASTStage)) {
769788
errors = contributor.validateElementAll(element, getExecution())
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2018, CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package org.jenkinsci.plugins.pipeline.modeldefinition.when.impl;
26+
27+
import hudson.Extension;
28+
import org.codehaus.groovy.ast.expr.Expression;
29+
import org.jenkinsci.Symbol;
30+
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTWhenContent;
31+
import org.jenkinsci.plugins.pipeline.modeldefinition.parser.ASTParserUtils;
32+
import org.jenkinsci.plugins.pipeline.modeldefinition.when.DeclarativeStageConditional;
33+
import org.jenkinsci.plugins.pipeline.modeldefinition.when.DeclarativeStageConditionalDescriptor;
34+
import org.kohsuke.stapler.DataBoundConstructor;
35+
import org.kohsuke.stapler.DataBoundSetter;
36+
37+
import javax.annotation.CheckForNull;
38+
39+
import static org.apache.commons.lang.StringUtils.isEmpty;
40+
41+
/**
42+
* Stage condition based on object equality.
43+
*/
44+
public class EqualsConditional extends DeclarativeStageConditional<EqualsConditional> {
45+
private final Object expected;
46+
private final Object actual;
47+
48+
@DataBoundConstructor
49+
public EqualsConditional(Object expected, Object actual) {
50+
this.expected = expected;
51+
this.actual = actual;
52+
}
53+
54+
public Object getActual() {
55+
return actual;
56+
}
57+
58+
public Object getExpected() {
59+
return expected;
60+
}
61+
62+
@Extension
63+
@Symbol("equals")
64+
public static class DescriptorImpl extends DeclarativeStageConditionalDescriptor<EqualsConditional> {
65+
@Override
66+
public Expression transformToRuntimeAST(@CheckForNull ModelASTWhenContent original) {
67+
return ASTParserUtils.transformWhenContentToRuntimeAST(original);
68+
}
69+
}
70+
}

pipeline-model-definition/src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/Messages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Parser.Triggers=Triggers
3434
Parser.UndefinedSection=Undefined section "{0}"
3535

3636
ModelParser.BareDollarCurly={0} cannot be used as a value directly. Did you mean "{0}"?
37+
ModelParser.BigIntegerValue=BigIntegers cannot be used as constants in Declarative. The maximum value for an integer is 9,223,372,036,854,775,807 and the minimum value for an integer is -9,223,372,036,854,775,808.
3738
ModelParser.CannotHaveBlocks={0} definitions cannot have blocks
3839
ModelParser.DuplicateEnvVar=Duplicate environment variable name: "{0}"
3940
ModelParser.ExpectedAgent=Expected an agent

pipeline-model-definition/src/main/resources/org/jenkinsci/plugins/pipeline/modeldefinition/agent/impl/DockerPipelineFromDockerfileScript.groovy

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ package org.jenkinsci.plugins.pipeline.modeldefinition.agent.impl
2828
import org.jenkinsci.plugins.pipeline.modeldefinition.SyntheticStageNames
2929
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
3030
import org.jenkinsci.plugins.workflow.cps.CpsScript
31+
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
3132

3233
class DockerPipelineFromDockerfileScript extends AbstractDockerPipelineScript<DockerPipelineFromDockerfile> {
3334

@@ -74,7 +75,8 @@ class DockerPipelineFromDockerfileScript extends AbstractDockerPipelineScript<Do
7475
return {
7576
def dockerfilePath = describable.getDockerfilePath(script.isUnix())
7677
try {
77-
def hash = Utils.stringToSHA1(script.readFile("${dockerfilePath}"))
78+
RunWrapper runWrapper = (RunWrapper)script.getProperty("currentBuild")
79+
def hash = Utils.stringToSHA1("${runWrapper.fullProjectName}\n${script.readFile("${dockerfilePath}")}")
7880
def imgName = "${hash}"
7981
def additionalBuildArgs = describable.getAdditionalBuildArgs() ? " ${describable.additionalBuildArgs}" : ""
8082
script.sh "docker build -t ${imgName}${additionalBuildArgs} -f \"${dockerfilePath}\" \"${describable.getActualDir()}\""

0 commit comments

Comments
 (0)