Skip to content

Commit b3a34b5

Browse files
authored
Merge pull request #1075 from daspilker/JENKINS-44256
[JENKINS-44256] enhanced support for the Groovy plugin
2 parents b2c93e1 + 099b8f8 commit b3a34b5

File tree

5 files changed

+225
-8
lines changed

5 files changed

+225
-8
lines changed

docs/Home.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Browse the Jenkins issue tracker to see any [open issues](https://issues.jenkins
2929

3030
## Release Notes
3131
* 1.67 (unreleased)
32+
* Enhanced support for the [Groovy Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin)
33+
([JENKINS-44256](https://issues.jenkins-ci.org/browse/JENKINS-44256))
34+
* Support for the older versions of the [Groovy Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin) is
35+
deprecated, see [Migration](Migration#migrating-to-167)
3236
* 1.66 (October 14 2017)
3337
* Enhanced support for the [Notification Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Notification+Plugin)
3438
([#1067](https://github.com/jenkinsci/job-dsl-plugin/pull/1067))

docs/Migration.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Migrating to 1.67
2+
3+
### Groovy Plugin
4+
5+
Support for versions older than 2.0 of the [Groovy Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin) is
6+
[[deprecated|Deprecation-Policy]] and will be removed.
7+
18
## Migrating to 1.66
29

310
### Notification

job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/helpers/step/StepContext.groovy

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ class StepContext extends AbstractExtensibleContext {
348348
groovy(fileName, false, groovyName, groovyClosure)
349349
}
350350

351-
protected groovyScriptSource(String commandOrFileName, boolean isCommand) {
351+
protected Node groovyScriptSource(String commandOrFileName, boolean isCommand) {
352352
new NodeBuilder().scriptSource(class: "hudson.plugins.groovy.${isCommand ? 'String' : 'File'}ScriptSource") {
353353
if (isCommand) {
354354
command commandOrFileName
@@ -359,6 +359,8 @@ class StepContext extends AbstractExtensibleContext {
359359
}
360360

361361
protected groovy(String commandOrFileName, boolean isCommand, String groovyInstallation, Closure groovyClosure) {
362+
jobManagement.logPluginDeprecationWarning('groovy', '2.0')
363+
362364
GroovyContext groovyContext = new GroovyContext()
363365
ContextHelper.executeInContext(groovyClosure, groovyContext)
364366

@@ -379,27 +381,66 @@ class StepContext extends AbstractExtensibleContext {
379381
* Executes a system Groovy script.
380382
*/
381383
@RequiresPlugin(id = 'groovy')
382-
void systemGroovyCommand(String command, @DslContext(SystemGroovyContext) Closure systemGroovyClosure = null) {
383-
systemGroovy(command, true, systemGroovyClosure)
384+
void systemGroovyCommand(String command, @DslContext(SystemGroovyCommandContext) Closure closure = null) {
385+
jobManagement.logPluginDeprecationWarning('groovy', '2.0')
386+
387+
SystemGroovyCommandContext systemGroovyContext = new SystemGroovyCommandContext(jobManagement)
388+
ContextHelper.executeInContext(closure, systemGroovyContext)
389+
390+
Node systemGroovyNode = new NodeBuilder().'hudson.plugins.groovy.SystemGroovy' {
391+
bindings systemGroovyContext.bindings.collect { key, value -> "${key}=${value}" }.join('\n')
392+
if (!jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0')) {
393+
classpath systemGroovyContext.classpathEntries.join(File.pathSeparator)
394+
}
395+
}
396+
Node scriptSource
397+
if (jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0')) {
398+
scriptSource = new NodeBuilder().source(class: 'hudson.plugins.groovy.StringSystemScriptSource') {
399+
script {
400+
script(command)
401+
sandbox(systemGroovyContext.sandbox)
402+
classpath {
403+
systemGroovyContext.classpathEntries.each { path ->
404+
entry {
405+
url(path)
406+
}
407+
}
408+
}
409+
}
410+
}
411+
} else {
412+
scriptSource = groovyScriptSource(command, true)
413+
}
414+
systemGroovyNode.append(scriptSource)
415+
416+
stepNodes << systemGroovyNode
384417
}
385418

386419
/**
387420
* Executes a system Groovy script.
388421
*/
389422
@RequiresPlugin(id = 'groovy')
390423
void systemGroovyScriptFile(String fileName, @DslContext(SystemGroovyContext) Closure systemGroovyClosure = null) {
391-
systemGroovy(fileName, false, systemGroovyClosure)
392-
}
424+
jobManagement.logPluginDeprecationWarning('groovy', '2.0')
393425

394-
protected systemGroovy(String commandOrFileName, boolean isCommand, Closure systemGroovyClosure) {
395426
SystemGroovyContext systemGroovyContext = new SystemGroovyContext()
396427
ContextHelper.executeInContext(systemGroovyClosure, systemGroovyContext)
397428

398429
Node systemGroovyNode = new NodeBuilder().'hudson.plugins.groovy.SystemGroovy' {
399430
bindings systemGroovyContext.bindings.collect { key, value -> "${key}=${value}" }.join('\n')
400-
classpath systemGroovyContext.classpathEntries.join(File.pathSeparator)
431+
if (!jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0')) {
432+
classpath systemGroovyContext.classpathEntries.join(File.pathSeparator)
433+
}
434+
}
435+
Node scriptSource
436+
if (jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0')) {
437+
scriptSource = new NodeBuilder().source(class: 'hudson.plugins.groovy.FileSystemScriptSource') {
438+
scriptFile fileName
439+
}
440+
} else {
441+
scriptSource = groovyScriptSource(fileName, false)
401442
}
402-
systemGroovyNode.append(groovyScriptSource(commandOrFileName, isCommand))
443+
systemGroovyNode.append(scriptSource)
403444

404445
stepNodes << systemGroovyNode
405446
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package javaposse.jobdsl.dsl.helpers.step
2+
3+
import javaposse.jobdsl.dsl.DslScriptException
4+
import javaposse.jobdsl.dsl.JobManagement
5+
import javaposse.jobdsl.dsl.RequiresPlugin
6+
7+
class SystemGroovyCommandContext extends SystemGroovyContext {
8+
private final JobManagement jobManagement
9+
10+
boolean sandbox
11+
12+
SystemGroovyCommandContext(JobManagement jobManagement) {
13+
this.jobManagement = jobManagement
14+
}
15+
16+
/**
17+
* If set, run the Groovy script in a sandbox with limited abilities. Defaults to {@code false}.
18+
*
19+
* @since 1.67
20+
*/
21+
@RequiresPlugin(id = 'groovy', minimumVersion = '2.0')
22+
void sandbox(boolean sandbox = true) {
23+
this.sandbox = sandbox
24+
}
25+
26+
@Override
27+
void classpath(String classpath) {
28+
if (jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0')) {
29+
try {
30+
new URL(classpath)
31+
} catch (MalformedURLException e) {
32+
throw new DslScriptException("classpath must be a valid URL: ${e.message}")
33+
}
34+
}
35+
super.classpath(classpath)
36+
}
37+
}

job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/helpers/step/StepContextSpec.groovy

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,7 @@ class StepContextSpec extends Specification {
780780
scriptSourceNode.command.size() == 1
781781
scriptSourceNode.command[0].value() == "println 'Hello World!'"
782782
1 * jobManagement.requirePlugin('groovy')
783+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
783784

784785
when:
785786
context.groovyCommand('acme.Acme.doSomething()', 'Groovy 2.0') {
@@ -817,6 +818,7 @@ class StepContextSpec extends Specification {
817818
acmeScriptSourceNode.command.size() == 1
818819
acmeScriptSourceNode.command[0].value() == 'acme.Acme.doSomething()'
819820
1 * jobManagement.requirePlugin('groovy')
821+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
820822
}
821823

822824
def 'call groovyScriptFile methods'() {
@@ -845,6 +847,7 @@ class StepContextSpec extends Specification {
845847
scriptSourceNode.scriptFile.size() == 1
846848
scriptSourceNode.scriptFile[0].value() == 'scripts/hello.groovy'
847849
1 * jobManagement.requirePlugin('groovy')
850+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
848851

849852
when:
850853
context.groovyScriptFile('acme.groovy', 'Groovy 2.0') {
@@ -894,6 +897,7 @@ class StepContextSpec extends Specification {
894897
groovy21Node.groovyName.size() == 1
895898
groovy21Node.groovyName[0].value() == 'Groovy 2.1'
896899
1 * jobManagement.requirePlugin('groovy')
900+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
897901
}
898902

899903
def 'call systemGroovyCommand methods'() {
@@ -914,6 +918,7 @@ class StepContextSpec extends Specification {
914918
scriptSourceNode.command.size() == 1
915919
scriptSourceNode.command[0].value() == "println 'Hello World!'"
916920
1 * jobManagement.requirePlugin('groovy')
921+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
917922

918923
when:
919924
context.systemGroovyCommand('acme.Acme.doSomething()') {
@@ -937,6 +942,7 @@ class StepContextSpec extends Specification {
937942
acmeScriptSourceNode.command.size() == 1
938943
acmeScriptSourceNode.command[0].value() == 'acme.Acme.doSomething()'
939944
1 * jobManagement.requirePlugin('groovy')
945+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
940946
}
941947

942948
def 'call systemGroovyScriptFile methods'() {
@@ -957,6 +963,7 @@ class StepContextSpec extends Specification {
957963
scriptSourceNode.scriptFile.size() == 1
958964
scriptSourceNode.scriptFile[0].value() == 'scripts/hello.groovy'
959965
1 * jobManagement.requirePlugin('groovy')
966+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
960967

961968
when:
962969
context.systemGroovyScriptFile('acme.groovy') {
@@ -980,6 +987,127 @@ class StepContextSpec extends Specification {
980987
acmeScriptSourceNode.scriptFile.size() == 1
981988
acmeScriptSourceNode.scriptFile[0].value() == 'acme.groovy'
982989
1 * jobManagement.requirePlugin('groovy')
990+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
991+
}
992+
993+
def 'call systemGroovyCommand methods with plugin version 2.0'() {
994+
setup:
995+
jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0') >> true
996+
997+
when:
998+
context.systemGroovyCommand("println 'Hello World!'")
999+
1000+
then:
1001+
context.stepNodes.size() == 1
1002+
with(context.stepNodes[0]) {
1003+
name() == 'hudson.plugins.groovy.SystemGroovy'
1004+
children().size() == 2
1005+
bindings[0].value() == ''
1006+
source.size() == 1
1007+
with(source[0]) {
1008+
attribute('class') == 'hudson.plugins.groovy.StringSystemScriptSource'
1009+
children().size() == 1
1010+
script[0].children().size() == 3
1011+
script[0].script[0].value() == "println 'Hello World!'"
1012+
script[0].sandbox[0].value() == false
1013+
script[0].classpath[0].children().size() == 0
1014+
}
1015+
}
1016+
1 * jobManagement.requirePlugin('groovy')
1017+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
1018+
1019+
when:
1020+
context.systemGroovyCommand('acme.Acme.doSomething()') {
1021+
binding('foo', 'bar')
1022+
binding('test', '0815')
1023+
classpath('file:/foo/acme.jar')
1024+
classpath('file:/foo/test.jar')
1025+
sandbox()
1026+
}
1027+
1028+
then:
1029+
context.stepNodes.size() == 2
1030+
with (context.stepNodes[1]) {
1031+
name() == 'hudson.plugins.groovy.SystemGroovy'
1032+
children().size() == 2
1033+
bindings[0].value() == 'foo=bar\ntest=0815'
1034+
with(source[0]) {
1035+
attribute('class') == 'hudson.plugins.groovy.StringSystemScriptSource'
1036+
children().size() == 1
1037+
script[0].children().size() == 3
1038+
script[0].script[0].value() == 'acme.Acme.doSomething()'
1039+
script[0].sandbox[0].value() == true
1040+
script[0].classpath[0].children().size() == 2
1041+
script[0].classpath[0].entry[0].children().size() == 1
1042+
script[0].classpath[0].entry[0].url[0].value() == 'file:/foo/acme.jar'
1043+
script[0].classpath[0].entry[1].children().size() == 1
1044+
script[0].classpath[0].entry[1].url[0].value() == 'file:/foo/test.jar'
1045+
}
1046+
}
1047+
1 * jobManagement.requirePlugin('groovy')
1048+
1 * jobManagement.requireMinimumPluginVersion('groovy', '2.0')
1049+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
1050+
}
1051+
1052+
def 'call systemGroovyCommand with invalid classpath and plugin version 2.0'() {
1053+
setup:
1054+
jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0') >> true
1055+
1056+
when:
1057+
context.systemGroovyCommand('acme.Acme.doSomething()') {
1058+
classpath('/foo/acme.jar')
1059+
}
1060+
1061+
then:
1062+
thrown(DslScriptException)
1063+
}
1064+
1065+
def 'call systemGroovyScriptFile methods with plugin version 2.0'() {
1066+
setup:
1067+
jobManagement.isMinimumPluginVersionInstalled('groovy', '2.0') >> true
1068+
1069+
when:
1070+
context.systemGroovyScriptFile('scripts/hello.groovy')
1071+
1072+
then:
1073+
context.stepNodes.size() == 1
1074+
with(context.stepNodes[0]) {
1075+
name() == 'hudson.plugins.groovy.SystemGroovy'
1076+
bindings.size() == 1
1077+
bindings[0].value() == ''
1078+
source.size() == 1
1079+
with(source[0]) {
1080+
attribute('class') == 'hudson.plugins.groovy.FileSystemScriptSource'
1081+
scriptFile.size() == 1
1082+
scriptFile[0].value() == 'scripts/hello.groovy'
1083+
}
1084+
}
1085+
1 * jobManagement.requirePlugin('groovy')
1086+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
1087+
1088+
when:
1089+
context.systemGroovyScriptFile('acme.groovy') {
1090+
binding('foo', 'bar')
1091+
binding('test', '0815')
1092+
classpath('/foo/acme.jar')
1093+
classpath('/foo/test.jar')
1094+
}
1095+
1096+
then:
1097+
context.stepNodes.size() == 2
1098+
with(context.stepNodes[1]) {
1099+
name() == 'hudson.plugins.groovy.SystemGroovy'
1100+
bindings.size() == 1
1101+
bindings[0].value() == 'foo=bar\ntest=0815'
1102+
source.size() == 1
1103+
with(source[0]) {
1104+
attribute('class') == 'hudson.plugins.groovy.FileSystemScriptSource'
1105+
scriptFile.size() == 1
1106+
scriptFile[0].value() == 'acme.groovy'
1107+
}
1108+
}
1109+
1 * jobManagement.requirePlugin('groovy')
1110+
1 * jobManagement.logPluginDeprecationWarning('groovy', '2.0')
9831111
}
9841112

9851113
def 'call copyArtifacts selector variants'() {

0 commit comments

Comments
 (0)