Skip to content

Commit

Permalink
Merge pull request #942 from daspilker/JENKINS-39153
Browse files Browse the repository at this point in the history
[JENKINS-39153] allow GString as argument type for auto-generated DSL
  • Loading branch information
daspilker committed Oct 30, 2016
2 parents 9a9e94c + b1bcdc6 commit 312a71e
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 7 deletions.
2 changes: 2 additions & 0 deletions docs/Home.md
Expand Up @@ -30,6 +30,8 @@ Browse the Jenkins issue tracker to see any [open issues](https://issues.jenkins
* Enhanced support the
[Config File Provider Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Config+File+Provider+Plugin)
([JENKINS-38637](https://issues.jenkins-ci.org/browse/JENKINS-38637))
* Allow `GString` as argument type for Automatically Generated DSL
([JENKINS-39153](https://issues.jenkins-ci.org/browse/JENKINS-39153))
* Fixed a problem with relative job names
([JENKINS-39137](https://issues.jenkins-ci.org/browse/JENKINS-39137))
* Added "Next Launch" and "Next Possible Launch" columns for
Expand Down
Expand Up @@ -4,6 +4,7 @@ import javaposse.jobdsl.dsl.Context
import javaposse.jobdsl.dsl.DslException
import javaposse.jobdsl.dsl.DslScriptException
import javaposse.jobdsl.dsl.JobManagement
import org.apache.commons.lang.ClassUtils
import org.jenkinsci.plugins.structs.describable.ArrayType
import org.jenkinsci.plugins.structs.describable.AtomicType
import org.jenkinsci.plugins.structs.describable.DescribableModel
Expand All @@ -14,7 +15,6 @@ import org.jenkinsci.plugins.structs.describable.HomogeneousObjectType
import org.jenkinsci.plugins.structs.describable.ParameterType

import static javaposse.jobdsl.dsl.ContextHelper.executeInContext
import static org.apache.commons.lang.ClassUtils.isAssignable

/**
* A dynamic {@link Context} that can be used to extend the DSL for any {@link hudson.model.Describable}.
Expand Down Expand Up @@ -77,17 +77,16 @@ class DescribableContext implements Context {
arrayType.elementType instanceof HomogeneousObjectType
} else if (value instanceof Iterable || (value != null && value.class.array)) {
if (arrayType.elementType instanceof AtomicType) {
return value.every { isAssignable(it.class, ((AtomicType) arrayType.elementType).type, true) }
return value.every { isAssignable(it, (AtomicType) arrayType.elementType) }
} else if (arrayType.elementType instanceof EnumType) {
EnumType enumType = (EnumType) arrayType.elementType
return value.every { enumType.type.isInstance(it) || enumType.values.contains(it) }
return value.every { isValidEnumValue(enumType, it) }
}
}
} else if (parameterType instanceof EnumType) {
EnumType enumType = (EnumType) parameterType
return enumType.type.isInstance(value) || enumType.values.contains(value)
return isValidEnumValue((EnumType) parameterType, value)
} else if (parameterType instanceof AtomicType) {
return (value != null && isAssignable(value.class, ((AtomicType) parameterType).type, true)) ||
return (value != null && isAssignable(value, parameterType)) ||
(value == null && !((AtomicType) parameterType).type.primitive)
} else if (parameterType instanceof HomogeneousObjectType) {
return value instanceof Closure || value == null
Expand Down Expand Up @@ -133,4 +132,13 @@ class DescribableContext implements Context {
}
throw new DslException("unsupported array element type: $arrayType.elementType")
}

private static boolean isAssignable(Object value, AtomicType parameterType) {
Class normalizedType = value instanceof GString ? String : value.class
ClassUtils.isAssignable(normalizedType, parameterType.type, true)
}

private static boolean isValidEnumValue(EnumType enumType, Object value) {
enumType.type.isInstance(value) || enumType.values.contains(value)
}
}
Expand Up @@ -1287,6 +1287,19 @@ class ExecuteDslScriptsSpec extends Specification {
freeStyleBuild.getLog(25).join('\n') =~ /jenkins.dsl/
}

def 'JENKINS-39153 GString arguments in auto-generated DSL'() {
setup:
Project job = jenkinsRule.createFreeStyleProject('seed')
job.buildersList.add(new ExecuteDslScripts(scriptText: this.class.getResourceAsStream('gstring.groovy').text))
job.onCreatedFromScratch()

when:
Run build = job.scheduleBuild2(0).get()

then:
build.result == SUCCESS
}

def 'ignore missing file'() {
setup:
FreeStyleProject job = jenkinsRule.createFreeStyleProject('seed')
Expand Down
Expand Up @@ -12,6 +12,7 @@ import jenkins.mvn.FilePathSettingsProvider
import org.jenkinsci.plugins.structs.describable.DescribableModel
import org.junit.ClassRule
import org.jvnet.hudson.test.JenkinsRule
import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Specification

Expand Down Expand Up @@ -96,6 +97,21 @@ class DescribableContextSpec extends Specification {
instance.aString == 'foo'
}

def 'string property with GString'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
String foo = 'foo'

when:
context.aString("${foo}")
def instance = context.createInstance()

then:
instance != null
instance instanceof DummyTrigger
instance.aString == 'foo'
}

def 'string property with null value'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
Expand Down Expand Up @@ -226,6 +242,22 @@ class DescribableContextSpec extends Specification {
instance.anEnum == Thread.State.NEW
}

@Ignore('https://github.com/jenkinsci/structs-plugin/pull/14')
def 'enum property with GString value'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
String foo = 'NEW'

when:
context.anEnum("${foo}")
def instance = context.createInstance()

then:
instance != null
instance instanceof DummyTrigger
instance.anEnum == Thread.State.NEW
}

def 'enum property with enum value'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
Expand Down Expand Up @@ -348,7 +380,7 @@ class DescribableContextSpec extends Specification {
!e.static
}

def 'heterogeneous list property with inull value'() {
def 'heterogeneous list property with null value'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)

Expand Down Expand Up @@ -743,6 +775,24 @@ class DescribableContextSpec extends Specification {
instance.stringList[1] == 'bar'
}

def 'string list property with GString'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
String foo = 'foo'
String bar = 'bar'

when:
context.stringList(["${foo}", "${bar}"])
def instance = context.createInstance()

then:
instance != null
instance instanceof DummyTrigger
instance.stringList.size() == 2
instance.stringList[0] == 'foo'
instance.stringList[1] == 'bar'
}

def 'empty string property list'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
Expand Down Expand Up @@ -816,6 +866,25 @@ class DescribableContextSpec extends Specification {
instance.enumList[1] == Thread.State.BLOCKED
}

@Ignore('https://github.com/jenkinsci/structs-plugin/pull/14')
def 'enum list property with GString'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
String one = 'NEW'
String two = 'BLOCKED'

when:
context.enumList(["${one}", "${two}"])
def instance = context.createInstance()

then:
instance != null
instance instanceof DummyTrigger
instance.enumList.size() == 2
instance.enumList[0] == Thread.State.NEW
instance.enumList[1] == Thread.State.BLOCKED
}

def 'empty enum property list'() {
setup:
DescribableContext context = new DescribableContext(new DescribableModel(DummyTrigger), jobManagement)
Expand Down
@@ -0,0 +1,9 @@
def TRIGGER = '@midnight'

job('a') {
triggers {
timerTrigger {
spec("${TRIGGER}")
}
}
}

0 comments on commit 312a71e

Please sign in to comment.