Skip to content
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5db34af
DAOS-19247 test: Support scripted Test stages
phender Jul 1, 2026
ef5d151
Restore getFunctionalTestStage.groovy
phender Jul 2, 2026
09d02ef
Updates.
phender Jul 2, 2026
0f14bd5
Debug
phender Jul 2, 2026
d677368
Debug
phender Jul 2, 2026
82667f5
Updates
phender Jul 2, 2026
ffc879a
Updates
phender Jul 2, 2026
5afdaea
Updates
phender Jul 2, 2026
b22f783
Fixes.
phender Jul 2, 2026
89f8bc1
Support passing in the distro arg to provisionNodes
phender Jul 2, 2026
acce7e9
Merge branch 'master' into hendersp/DAOS-19247-fix
phender Jul 7, 2026
efb52c0
Remove unused code.
phender Jul 7, 2026
ab0e990
Merge branch 'master' into hendersp/DAOS-19247-fix
phender Jul 9, 2026
633079a
Cleanup defaults.
phender Jul 9, 2026
304ab81
Groovylint fixes
phender Jul 9, 2026
8cf3e29
Applying feedback.
phender Jul 9, 2026
61a43af
Fix skipping functional test stage due to no tag match
phender Jul 9, 2026
1a3cdef
Update tag fit check for functional test stages
phender Jul 9, 2026
1950b3a
Debug
phender Jul 10, 2026
3e2f4fc
Debug to figure out why testsInStage isn't working.
phender Jul 13, 2026
037d0dd
Fix debug
phender Jul 14, 2026
8d53241
Cleanup debug and apply feedback
phender Jul 14, 2026
9deead5
Cleanup docstrings
phender Jul 14, 2026
0162051
Applying feedback
phender Jul 14, 2026
6b92bcf
Ensure methods relying on the stage name run in the stage
phender Jul 14, 2026
3c8c2dc
Adding info message to testsInStage().
phender Jul 14, 2026
8130ede
Adding clarifications to docstrings.
phender Jul 15, 2026
495d93a
Collect return status from alwaysScript.
phender Jul 15, 2026
8e3ed9d
Allow distro to be passed to daosRepos()
phender Jul 15, 2026
9b496bb
Debug
phender Jul 16, 2026
0c45b16
More debug
phender Jul 16, 2026
ffae8de
Remove debug - problem was passing in NODELIST
phender Jul 16, 2026
ad7d418
Attempt to fix running testsInStage()
phender Jul 16, 2026
8fa926a
Updates to testsInStage()
phender Jul 16, 2026
021404b
Debug.
phender Jul 16, 2026
a5583e1
Removing env.UNIT_TEST handling in testsInStage
phender Jul 17, 2026
e38a6a5
Revert most of the testsInStage() changes
phender Jul 17, 2026
db18bdc
Add self-reference to verify unit tests
phender Jul 17, 2026
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
2 changes: 1 addition & 1 deletion vars/getFunctionalTestStage.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ Map call(Map kwargs = [:]) {
jobStatusUpdate(job_status, name)
}
}
println("[${name}] Finished with ${job_status}")
}
println("[${name}] Finished with ${job_status}")
}
}
142 changes: 142 additions & 0 deletions vars/scriptedDockerStage.groovy
Comment thread
phender marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// vars/scriptedDockerStage.groovy

import org.jenkinsci.plugins.pipeline.modeldefinition.Utils

/**
* scriptedDockerStage
*
* Get a build stage in scripted syntax.
*
* @param kwargs Map containing the following optional arguments (empty strings yield defaults):
* name the build stage name
* runStage optional additional condition to determine if the stage runs
* jobStatus Map of status for each stage in the job/build
* dockerTag the docker image tag to use for the build
* dockerBuildArgs optional docker build arguments
* buildRpms whether or not to build rpms; defaults to true
* distro the shorthand distro name; defaults to 'el8'
* rpmDistro the distro to use for rpm building; defaults to distro
* release the DAOS RPM release value to use; defaults to env.DAOS_RELVAL
* compiler the compiler to use; defaults to 'gcc'
* sconsBuildArgs optional scons build arguments
* valgrindSconsBuildArgs optional scons build arguments for valgrind build
* artifacts optional artifacts name to archive; defaults to
* "config.log-${distro}-${compiler}"
* uploadTarget the distro to use when uploading rpms; defaults to distro
* installScript optional script to run to install rpms; defaults to ''
* publishHtmlArgs optional arguments to pass to publishHTML()
* archiveArtifactsArgs optional arguments to pass to archiveArtifacts()
* @return a scripted stage to run in a pipeline
*/
Map call(Map kwargs = [:]) {
String name = kwargs.get('name', 'Unknown Docker Stage')
Boolean runStage = kwargs.get('runStage', true)
Map jobStatus = kwargs.get('jobStatus', [:])
String dockerTag = jobStatusKey("build-${uploadTarget}-${compiler}").toLowerCase()
String dockerBuildArgs = kwargs.get('dockerBuildArgs', '')

// Build stage parameters
Boolean buildRpms = kwargs.get('buildRpms', true)
String distro = kwargs.get('distro', 'el8')
Comment thread
phender marked this conversation as resolved.
Outdated
String rpmDistro = kwargs.get('rpmDistro', distro)
String release = kwargs.get('release', env.DAOS_RELVAL)
String compiler = kwargs.get('compiler', 'gcc')
Map sconsBuildArgs = kwargs.get('sconsBuildArgs', [:])
Map valgrindSconsBuildArgs = kwargs.get('valgrindSconsBuildArgs', [:])
String artifacts = kwargs.get('artifacts', "config.log-${distro}-${compiler}")
String uploadTarget = kwargs.get('uploadTarget', distro)
String bullseye = 'false'
if (compiler == 'covc') {
bullseye = 'true'
}

// Summary stage parameters
String installScript = kwargs.get('installScript', '')
Map publishHtmlArgs = kwargs.get('publishHtmlArgs', [:])
Map archiveArtifactsArgs = kwargs.get('archiveArtifactsArgs', [:])

return {
stage("${name}") {
if (!runStage) {
println("[${name}] Marking docker stage as skipped")
Utils.markStageSkippedForConditional("${name}")
return
}
node('docker_runner') {
println("[${name}] Check out from version control")
checkoutScm(pruneStaleBranch: true)

def dockerImage = docker.build(dockerTag, dockerBuildArgs)
try {
dockerImage.inside() {
if (buildRpms) {
sh label: 'Install RPMs',
script: "./ci/rpm/install_deps.sh ${rpmDistro} ${release} ${bullseye}"
Comment thread
phender marked this conversation as resolved.
Outdated
// Avoid interpolation of sensitive environment variables
sh label: 'Build deps',
script: "./ci/rpm/build_deps.sh ${bullseye}" + ' ${BULLSEYE_KEY}'
}
if (sconsBuildArgs) {
job_step_update(sconsBuild(sconsBuildArgs))
}
if (valgrindSconsBuildArgs) {
// For non-release builds, create a separate build with the valgrind
// tag for NLT memcheck testing. This is necessary to avoid problems
// caused by valgrind being confused by the Go runtime. We don't want
// to use the valgrind build for normal testing because it is much
// slower. BUILD_TYPE=dev is set for PR/dev builds in sconsArgs(), and
// TARGET_TYPE=release is used to select pre-built cached prerequisites.
job_step_update(sconsBuild(valgrindSconsBuildArgs))
sh label: 'Stash valgrind install tree for NLT',
script: 'tar -C / -cf opt-daos-valgrind.tar opt/daos'
stash(name: 'opt-daos-valgrind', includes: 'opt-daos-valgrind.tar')
}
if (buildRpms) {
sh label: 'Generate RPMs',
script: "./ci/rpm/gen_rpms.sh ${rpmDistro} ${release} ${bullseye}"
// Success actions
uploadNewRPMs(uploadTarget, 'success')
}
if (installScript) {
sh label: 'Install RPMs',
script: "${installScript} ${distro}"
}
}
} catch (Exception e) {
println("[${name}] Caught exception in try: ${e}")
if (sconsBuildArgs) {
// Unsuccessful actions
sh """if [ -f config.log ]; then
mv config.log ${artifacts}
fi"""
archiveArtifacts artifacts: "${artifacts}", allowEmptyArchive: true
}
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
} finally {
// Cleanup actions
try{
if (buildRpms) {
println("[${name}] Running uploadNewRPMs()")
uploadNewRPMs(uploadTarget, 'cleanup')
}
if (publishHtmlArgs) {
println("[${name}] Running publishHTML()")
publishHTML(publishHtmlArgs)
}
if (archiveArtifactsArgs) {
println("[${name}] Running archiveArtifacts()")
archiveArtifacts(archiveArtifactsArgs)
}
jobStatusUpdate(jobStatus, name)
} catch (Exception e) {
println("[${name}] Caught exception in finally: ${e}")
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
}
}
}
println("[${name}] Finished with ${jobStatus}")
}
}
}
95 changes: 95 additions & 0 deletions vars/scriptedTestRpmStage.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// vars/scriptedTestRpmStage.groovy

import org.jenkinsci.plugins.pipeline.modeldefinition.Utils

/**
* scriptedTestRpmStage.groovy
*
* Get a test stage in scripted syntax.
*
* @param kwargs Map containing the following optional arguments (empty strings yield defaults):
* name test stage name
* runStage whether or not to run the test stage
Comment thread
grom72 marked this conversation as resolved.
Outdated
* label test stage default cluster label
* testBranch if specified, checkout sources from this branch before running tests
Comment thread
grom72 marked this conversation as resolved.
Outdated
* jobStatus Map of status for each stage in the job/build
* imageVersion testRpm() target argument; defaults to ''
* instRepos testRpm() inst_repos argument; defaults to daosRepos()
* daosPkgVersion testRpm() daos_pkg_version argument; defaults to
* daosPackagesVersion(next_version())
* instRpms testRpm() inst_rpms argument; defaults to 'mercury-libfabric'
* ignoreFailure testRpm() ignore_failure argument; defaults to false
* alwaysScript script to run always after the test stage; defaults to ''.
* archiveArtifactsArgs Map of arguments to pass to archiveArtifacts() for the stage
* @return a scripted stage to run in a pipeline
*/
Map call(Map kwargs = [:]) {
// General parameters
String name = kwargs.get('name', 'Unknown Functional Test Stage')
Boolean runStage = kwargs.get('runStage', true) as Boolean
String label = kwargs.get('label')
String testBranch = kwargs.get('testBranch', '')
Map jobStatus = kwargs.get('jobStatus', null) ?: [:]
Map testRpmArgs = [
target: kwargs.get('imageVersion', ''),
inst_repos: kwargs.get('instRepos', daosRepos()),
daos_pkg_version: kwargs.get(
'daosPkgVersion', daosPackagesVersion(kwargs.get('next_version', null))),
inst_rpms: kwargs.get('instRpms', 'mercury-libfabric'),
ignore_failure: kwargs.get('ignoreFailure', false)
]
String alwaysScript = kwargs.get('alwaysScript', '')
Map archiveArtifactsArgs = kwargs.get('archiveArtifactsArgs', null) ?: [:]

return {
stage("${name}") {
println("[${name}] Starting stage: kwargs keys=${kwargs.keySet()}")

if (!runStage) {
println("[${name}] Stage skipped by runStage=false")
Utils.markStageSkippedForConditional("${name}")
return
}

node(label) {
// Ensure access to any branch provisioning scripts exist
if (testBranch) {
println("[${name}] Check out '${testBranch}' from version control")
checkoutScm(
url: 'https://github.com/daos-stack/daos.git',
branch: testBranch,
withSubmodules: false,
pruneStaleBranch: true)
} else {
println("[${name}] Check out branch from version control")
checkoutScm(pruneStaleBranch: true)
}

try {
println("[${name}] Running testRpm() on ${label}")
jobStatusUpdate(jobStatus, name, testRpm(testRpmArgs))
} catch (Exception e) {
println("[${name}] Caught exception in try: ${e}")
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
} finally {
try {
if (alwaysScript) {
sh(script: alwaysScript, label: "Running alwaysScript: ${alwaysScript}")
}
if (archiveArtifactsArgs) {
println("[${name}] Running archiveArtifacts()")
archiveArtifacts(archiveArtifactsArgs)
}
jobStatusUpdate(jobStatus, name)
} catch (Exception e) {
println("[${name}] Caught exception in finally: ${e}")
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
}
}
}
println("[${name}] Finished with ${jobStatus}")
}
}
}
110 changes: 110 additions & 0 deletions vars/scriptedUnitTestStage.groovy
Comment thread
grom72 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// vars/scriptedUnitTestStage.groovy

import org.jenkinsci.plugins.pipeline.modeldefinition.Utils

/**
* scriptedUnitTestStage.groovy
*
* Get a unit test stage in scripted syntax.
*
* @param kwargs Map containing the following optional arguments (empty strings yield defaults):
* name test stage name
* runStage whether or not to run the test stage
* label test stage default cluster label
* testBranch if specified, checkout sources from this branch before running tests
* jobStatus Map of status for each stage in the job/build
* target the target distro to use for the test stage; defaults to 'el9'
* timeoutTime unitTest() timeout time in minutes; defaults to 60
* instRepos unitTest() inst_repos argument; defaults to daosRepos()
* testScript unitTest() test_script argument; defaults to ''
* withValgrind unitTest() with_valgrind argument; defaults to ''
* alwaysScript unitTest() always_script argument; defaults to 'ci/unit/test_nlt_post.sh'
* testResults unitTest() test_results argument; defaults to 'nlt-junit.xml'
* unstashOpt unitTest() unstash_opt argument; defaults to true
* unstashTests unitTest() unstash_tests argument; defaults to false
* instRpms unitTest() inst_rpms argument; defaults to unitPackages(target: target) + ' daos-client-tests'
* imageVersion unitTest() image_version argument; defaults to 'el9.7'
* provEnvVars unitTest() prov_env_vars argument; defaults to ''
* unitTestPostArgs Map of arguments to pass to unitTestPost() for the stage
* archiveArtifactsArgs Map of arguments to pass to archiveArtifacts() for the stage
* @return a scripted stage to run in a pipeline
Comment thread
grom72 marked this conversation as resolved.
*/
Map call(Map kwargs = [:]) {
// General parameters
String name = kwargs.get('name', 'Unknown Functional Test Stage')
Boolean runStage = kwargs.get('runStage', true) as Boolean
String label = kwargs.get('label')
String testBranch = kwargs.get('testBranch', '')
Map jobStatus = kwargs.get('jobStatus', null) ?: [:]
String distro = kwargs.get('distro', 'el9')

// Unit Test stage parameters
Map unitTestArgs = [
'timeout_time': kwargs.get('timeoutTime', 60),
'inst_repos': kwargs.get('instRepos', daosRepos(distro)),
'test_script': kwargs.get('testScript', ''),
'with_valgrind': kwargs.get('withValgrind', ''),
'always_script': kwargs.get('alwaysScript', 'ci/unit/test_nlt_post.sh'),
'test_results': kwargs.get('testResults', 'nlt-junit.xml'),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it the case that unitTest expects testResults instead of test_results?

p['testResults'] = config.get('testResults',

Suggested change
'test_results': kwargs.get('testResults', 'nlt-junit.xml'),
'testResults': kwargs.get('testResults', 'nlt-junit.xml'),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. Fixed in https://github.com/daos-stack/pipeline-lib/pull/526/changes/037d0ddc14145bc96d08751797e10cc4b86a0d2a..0162051eb3f92cb52c3abeabeb3404c1c389b1ed. The arguments for unitTest.groovy are now passed through.

Comment thread
grom72 marked this conversation as resolved.
Outdated
'unstash_opt': kwargs.get('unstashOpt', true),
'unstash_tests': kwargs.get('unstashTests', false),
'inst_rpms': kwargs.get('instRpms', unitPackages(target: distro) + ' daos-client-tests'),
'image_version': kwargs.get('imageVersion', 'el9.7'),
'prov_env_vars': kwargs.get('provEnvVars', '')
]
Map unitTestPostArgs = kwargs.get('unitTestPostArgs', null) ?: [:]
Map archiveArtifactsArgs = kwargs.get('archiveArtifactsArgs', null) ?: [:]

return {
stage("${name}") {
println("[${name}] Starting stage: kwargs keys=${kwargs.keySet()}")

if (!runStage) {
println("[${name}] Stage skipped by runStage=false")
Utils.markStageSkippedForConditional("${name}")
return
}

node(label) {
// Ensure access to any branch provisioning scripts exist
if (testBranch) {
println("[${name}] Check out '${testBranch}' from version control")
checkoutScm(
url: 'https://github.com/daos-stack/daos.git',
branch: testBranch,
withSubmodules: false,
pruneStaleBranch: true)
} else {
println("[${name}] Check out branch from version control")
checkoutScm(pruneStaleBranch: true)
}

try {
println("[${name}] Running unitTest() on ${label}")
jobStatusUpdate(jobStatus, name, unitTest(unitTestArgs))
} catch (Exception e) {
println("[${name}] Caught exception in try: ${e}")
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
} finally {
try {
if (unitTestPostArgs) {
println("[${name}] Running unitTestPost()")
unitTestPost(unitTestPostArgs)
}
if (archiveArtifactsArgs) {
println("[${name}] Running archiveArtifacts()")
archiveArtifacts(archiveArtifactsArgs)
}
jobStatusUpdate(jobStatus, name)
} catch (Exception e) {
println("[${name}] Caught exception in finally: ${e}")
jobStatusUpdate(jobStatus, name, 'FAILURE')
throw e
}
}
}
println("[${name}] Finished with ${jobStatus}")
}
}
}