void call(Map config = [:], Closure body) { defaultConfig = [ pythonPath: 'python3', recreateVenv: true, venvDir: '.venv', updatePip: true, installPipTools: true, requirementsFile: 'requirements.in', stepName: 'python' ] runConfig = defaultConfig + config venvDir = [ env.WORKSPACE, runConfig.venvDir ] venvBinDir = venvDir + 'bin' venvPython = venvBinDir + 'python' venvEnv = [ "VIRTUAL_ENV=${venvDir.join('/')}", "PATH+CUSTOM=${venvBinDir.join('/')}" ] stage(runConfig.stepName) { printBanner(runConfig.stepName) ansiColor('css') { if (fileExists(runConfig.venvDir) && runConfig.recreateVenv) { echo 'INFO: Removing old venv from workspace.' dir(runConfig.venvDir) { deleteDir() } } if (!fileExists(runConfig.venvDir)) { echo "INFO: Creating new venv in ${runConfig.venvDir}." sh "${runConfig.pythonPath} -m venv ${runConfig.venvDir}" } withEnv(venvEnv) { List setupCmds = [] if (runConfig.updatePip) { echo 'INFO: Will update pip if an update is available.' updateCmd = "${venvPython.join('/')} -m pip install --upgrade pip" setupCmds.add(updateCmd) } if (runConfig.installPipTools) { echo 'INFO: Will install pip-tools.' installCmd = "${venvPython.join('/')} -m pip install pip-tools" setupCmds.add(installCmd) } if (fileExists(runConfig.requirementsFile)) { echo "INFO: Will resolve requirements from ${runCOnfig.requirementsFile}." reqCmd = "pip-compile ${runConfig.requirementsFile}" setupCmds.add(reqCmd) } if (!setupCmds.isEmpty()) { echo 'INFO: Beginning venv setup.' sh setupCmds.join('\n') } echo 'Executing closure...' body() } } } }