Skip to content
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 tests for JobDSL scripts #33

Merged
merged 4 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 148 additions & 17 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import groovy.transform.Field
import java.nio.file.Paths

plugins {
id 'groovy'
id 'idea'
Expand Down Expand Up @@ -33,19 +36,25 @@ sourceSets {
}
}

configurations {
testPlugins
}

dependencies {
implementation "org.codehaus.groovy:groovy-all:$groovyVersion"
implementation "org.jenkins-ci.main:jenkins-core:$jenkinsVersion"
implementation(getJenkinsPlugins()['workflow-cps'])

testImplementation "com.lesfurets:jenkins-pipeline-unit:$jenkinsPipelineUnitVersion"
testImplementation "org.spockframework:spock-core:$spockVersion"
testImplementation "org.junit.jupiter:junit-jupiter:$junitVersion"
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine'
getJenkinsPlugins().values().each { pluginGAV ->
testRuntimeOnly "${pluginGAV}@jar"
implementationDependencies.each { String dependency ->
implementation dependency
}
testImplementationDependencies.each { String dependency ->
testImplementation dependency
}
jenkinsPlugins.values().each { String pluginGAV ->
testPlugins pluginGAV
}

/* JUnit5 dependencies */
testImplementation platform('org.junit:junit-bom:5.9.2')
testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine'
}

idea {
Expand All @@ -58,6 +67,11 @@ idea {
/* Tasks */

tasks.named('test') {
dependsOn tasks.resolveTestPlugins
inputs.files sourceSets.main.allSource.files
// set build directory for Jenkins test harness, JENKINS-26331
systemProperty 'buildDirectory', buildDir

useJUnitPlatform()
maxParallelForks = 4

Expand All @@ -78,6 +92,46 @@ tasks.named('test') {
}
}

tasks.register('resolveTestPlugins', Copy) {
group 'verification'
description 'Collect Jenkins plugins and make them available for Jenkins Test Harness'

final String destinationDir = "${sourceSets.test.output.resourcesDir}/test-dependencies"

doFirst {
configurations.testPlugins
.resolvedConfiguration
.resolvedArtifacts
.each { ResolvedArtifact artifact ->
if (artifact.extension ==~ '[hj]pi') {
addPluginMapping artifact
}
}
}

from configurations.testPlugins {
rename { String filePath ->
getPluginsMapping(
Paths.get(filePath).getFileName().toString()
)
.fileName
}
}
include '*.hpi', '*.jpi'
into destinationDir

doLast {
new File(destinationDir, 'index').setText(
pluginsMapping
.values()
.collect { JenkinsPlugin plugin -> plugin.name }
.toSorted()
.join('\n'),
'UTF-8'
)
}
}

tasks.named('wrapper') {
gradleVersion = project.gradleVersion
distributionType = Wrapper.DistributionType.BIN
Expand All @@ -86,12 +140,89 @@ tasks.named('wrapper') {

/* Helpers */

Map getJenkinsPlugins() {
jenkinsPluginsVersions.tokenize()
Map<String, String> getJenkinsPlugins() {
property("jenkinsPluginVersions.$jenkinsVersion")
.tokenize()
.collate(2)
.collectEntries {
String pluginName = it[0].split(':')[1]
String pluginGAV = "${it[0]}:${it[1]}"
[(pluginName): pluginGAV]
.findAll { def (String module, String version) = it
!module.startsWith('#')
}
.collectEntries { def (String module, String version) = it
[(module.replaceAll(/:$/, '')): version]
}
.collectEntries { String module, version ->
String pluginName = module.split(':').last()
[(pluginName): "$module:$version".toString()]
}
}

@Field
final Map<String, JenkinsPlugin> pluginsMapping = [:]

void addPluginMapping(ResolvedArtifact artifact) {
pluginsMapping[artifact.file.name] = new JenkinsPlugin(artifact.name, artifact.extension)
}

Map<String, JenkinsPlugin> getPluginsMapping() {
pluginsMapping
}

JenkinsPlugin getPluginsMapping(String fileName) {
getPluginsMapping()[fileName]
}

String getTestHarnessVersion() {
property("testHarnessVersion.$jenkinsVersion")
}

List<String> getImplementationDependencies() {
List<String> result = [
"org.codehaus.groovy:groovy-all:2.4.21",
"org.jenkins-ci.main:jenkins-core:$jenkinsVersion",
jenkinsPlugins['job-dsl-core'],
]
switch (jenkinsVersion) {
case '2.277.4':
result << 'com.cloudbees:groovy-cps:1.22'
break
case '2.346.3':
result << jenkinsPlugins['workflow-cps']
break
default:
throw new IllegalArgumentException("Unrecognized Jenkins version: $jenkinsVersion")
}
result
}

List<String> getTestImplementationDependencies() {
List<String> result = [
"com.lesfurets:jenkins-pipeline-unit:1.19",
"org.spockframework:spock-core:1.3-groovy-2.4",
"org.jenkins-ci.main:jenkins-test-harness:${testHarnessVersion}",
"org.jenkins-ci.main:jenkins-war:$jenkinsVersion",
jenkinsPlugins['job-dsl'],
"${jenkinsPlugins['job-dsl']}@jar",
"${jenkinsPlugins['structs']}@jar",
]
switch (jenkinsVersion) {
case '2.277.4':
result << 'cglib:cglib-nodep:2.2.2'
result << "${jenkinsPlugins['script-security']}@jar"
break
case '2.346.3':
break
default:
throw new IllegalArgumentException("Unrecognized Jenkins version: $jenkinsVersion")
}
result
}

class JenkinsPlugin {
final String name
final String fileName

JenkinsPlugin(String name, String extension) {
this.name = name
this.fileName = "${name}.${extension}"
}
}
52 changes: 52 additions & 0 deletions doc/collectPluginVersions.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
class Plugin {
String groupId
String shortName
String version

@Override
String toString () {
"${groupId}:${shortName}:${version}"
}

static Plugin fromManifest(File manifest) {
String groupId = extractLineByPrefix(manifest, "Group-Id: ")
String shortName = extractLineByPrefix(manifest, "Short-Name: ")
String version = extractLineByPrefix(manifest, "Plugin-Version: ")
new Plugin(groupId: groupId, shortName: shortName, version: version)
}

private static String extractLineByPrefix(File manifest, String prefix) {
manifest
.readLines()
.find { it.startsWith(prefix) }
.replace(prefix, "")
}
}

Boolean isRelevant(Plugin plugin) {
!(plugin.groupId in [
'io.jenkins.blueocean',
'org.jenkins-ci.plugins.aws-java-sdk',
'ru.yandex.qatools.allure',
]) &&
!(plugin.shortName in ['jacoco']) && // jacoco brings weird dependencies
!plugin.version.contains('private') // Filter plugins installed from file
}

final String jenkinsHome = System.getenv("JENKINS_HOME")

//noinspection GrDeprecatedAPIUsage
final Map<String, Plugin> mavenCoordinates = new FileNameFinder()
.getFileNames("${jenkinsHome}/plugins", "**/META-INF/MANIFEST.MF")
.collect { fileName -> Plugin.fromManifest(new File(fileName)) }
.findAll { isRelevant it }
.sort { a, b -> (a.groupId + a.shortName) <=> (b.groupId + b.shortName) }
.collectEntries { plugin -> [(plugin.shortName): plugin] }

println "jobDslVersion=${mavenCoordinates.get("job-dsl").version}"
println "jenkinsVersion=${jenkins.model.Jenkins.getInstance().getVersion()}"
println 'jenkinsPlugins='
println mavenCoordinates
.values()
.collect { "${it.groupId}:${it.shortName}".padRight(64) + it.version }
.join('\n')
41 changes: 20 additions & 21 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
junitVersion = 5.9.2
jenkinsPipelineUnitVersion = 1.17
spockVersion = 1.3-groovy-2.4

# Set version as close as possible to the version of Jenkins in production environment
# Last version of Jenkins which can run on top of Java 8: 2.346.1
# Newer versions require at least Java 11
jenkinsVersion = 2.361.4

groovyVersion = 2.4.21
jenkinsVersion = 2.277.4

# Maven GAV coordinates of Jenkins plugins required in tests' runtime.
# They should match our jenkinsVersion, appropriate version matching of plugins to
Expand All @@ -17,20 +11,25 @@ groovyVersion = 2.4.21
# Eg. the following XPath selector returns cells with non-empty number of installations of
# some plugin for Jenkins version 2.361.4:
# (//tr[th = '2.361.4']/td)[position() < last() and . != '']
jenkinsPluginsVersions = \
org.jenkins-ci.plugins:credentials-binding 523.vd859a_4b_122e6 \
org.jenkins-ci.plugins:durable-task 503.v57154d18d478 \
org.jenkins-ci.plugins:job-dsl 1.82 \
org.jenkins-ci.plugins:pipeline-utility-steps 2.14.0 \
org.jenkins-ci.plugins:script-security 1228.vd93135a_2fb_25 \
org.jenkins-ci.plugins:ssh-agent 295.v9ca_a_1c7cc3a_a_ \
org.jenkins-ci.plugins:ssh-credentials 305.v8f4381501156 \
org.jenkins-ci.plugins:structs 324.va_f5d6774f3a_d \
org.jenkins-ci.plugins.workflow:workflow-api 1200.v8005c684b_a_c6 \
org.jenkins-ci.plugins.workflow:workflow-basic-steps 994.vd57e3ca_46d24 \
org.jenkins-ci.plugins.workflow:workflow-cps 3536.vb_8a_6628079d5 \
org.jenkins-ci.plugins.workflow:workflow-durable-task-step 1217.v38306d8fa_b_5c \
org.jenkins-ci.plugins.workflow:workflow-step-api 639.v6eca_cd8c04a_a_ \


## Jenkins Test Harness and plugins versions for Jenkins 2.277.4

testHarnessVersion.2.277.4 = 2140.ve736dc2b_b_d2c
jenkinsPluginVersions.2.277.4 = \
org.jenkins-ci.plugins.workflow:workflow-cps-global-lib: 2.21 \
org.jenkins-ci.plugins.workflow:workflow-job: 2.41 \
org.jenkins-ci.plugins.workflow:workflow-multibranch: 711.vdfef37cda_816 \
org.jenkins-ci.plugins:cloudbees-folder: 6.15 \
org.jenkins-ci.plugins:credentials: 2.5 \
org.jenkins-ci.plugins:git: 4.7.2 \
org.jenkins-ci.plugins:job-dsl: 1.77 \
org.jenkins-ci.plugins:job-dsl-core: 1.77 \
org.jenkins-ci.plugins:matrix-auth: 2.6.7 \
org.jenkins-ci.plugins:script-security: 1.77 \
org.jenkins-ci.plugins:structs: 1.23 \
org.jenkins-ci.plugins:trilead-api: 1.0.13 \
#


testLoggerPluginVersion = 4.0.0
Expand Down
Empty file removed pipelines/.gitkeep
Empty file.
1 change: 1 addition & 0 deletions pipelines/admin/Seed/Jenkinsfile.dsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
folder 'admin'
pipelineJob 'admin/Seed', {
parameters {
choiceParam {
Expand Down
1 change: 1 addition & 0 deletions pipelines/jenkins-library/OnCommit/Jenkinsfile.dsl
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
folder 'jenkins-library'
multibranchPipelineJob('jenkins-library/OnCommit') {
branchSources {
git {
Expand Down
Empty file removed resources/.gitkeep
Empty file.
Empty file removed src/.gitkeep
Empty file.
Empty file removed test/pipelines/.gitkeep
Empty file.
Loading