#!groovy /** * Checkouts and executes actions over a list of repositories. * * Manuele Simi (ISTI-CNR) */ def agent_root_folder = '/var/lib/jenkins/.m2' //locate the action file String actionURL = "${action_root}/${action_file}" println "Querying ${actionURL}" //save the action code def action_code = actionURL.toURL().getText() println "Action code: ${action_code}" //locate the repos file println "Querying ${repo_list}" //save the action code def repo_content = repo_list.toURL().getText() def projects = parseProjectList(repo_content) pipeline { agent { label 'CD' } environment { AGENT_ROOT_FOLDER = "${agent_root_folder}" PIPELINE_BUILD_NUMBER = "${env.BUILD_NUMBER}" ACTION_REPORT = "${agent_root_folder}/actions.${env.BUILD_NUMBER}.csv" ACTION_OUTPUT = "${agent_root_folder}/action-output.${env.BUILD_NUMBER}.txt" ACTION_URL="${actionURL}" REPO_ROOT="${git_root}" } parameters { string(name: 'git_root', defaultValue: 'https://code-repo.d4science.org/TestActions/', description: 'The root URL of the repositories') string(name: 'repo_list', defaultValue: 'https://code-repo.d4science.org/gCubeCI/gCubeActions/raw/branch/master/repos/TestActions_all_sorted.txt', description: 'The file with the list of repositories to update') string(name: 'action_root', defaultValue: 'https://code-repo.d4science.org/gCubeCI/gCubeActions/raw/branch/master/', description: 'The root URL of the Bash fragment to execute.') string(name: 'action_file', defaultValue: '', description: 'The relative path of the Bash fragment to execute.') } stages { stage('initialize report') { steps { sh ''' date=`date` echo "#Build ${PIPELINE_BUILD_NUMBER},," > $ACTION_REPORT echo "#StartTime ${date},," >> $ACTION_REPORT echo "Project,Repo,Result" >> $ACTION_REPORT ''' } } stage('clone and exec') { steps { script { for (int i = 0; i < projects.size(); i++) { stage(projects[i]) { echo "About to execute over ${projects[i]}" checkout_and_exec(projects[i]) sh "echo -e ${projects[i]},${git_root}/${projects[i]},Completed >> $ACTION_REPORT" } } } } } } // post-build actions post { always { script { sh ''' cp $ACTION_REPORT ./actions.${PIPELINE_BUILD_NUMBER}.csv cat ./actions.${PIPELINE_BUILD_NUMBER}.csv cp $ACTION_OUTPUT ./action-output.${PIPELINE_BUILD_NUMBER}.txt cat ./action-output.${PIPELINE_BUILD_NUMBER}.txt ''' } } success { echo 'The actions pipeline worked!' emailext attachmentsPattern: "**/actions.${env.BUILD_NUMBER}.csv", to: 'manuele.simi@isti.cnr.it', subject: "Actions report(build #${PIPELINE_BUILD_NUMBER})", body: "${currentBuild.fullDisplayName}. Build time: ${currentBuild.durationString}. See ${env.BUILD_URL}" } failure { echo 'The actions pipeline has failed' emailext attachLog: true, to: 'manuele.simi@isti.cnr.it', subject: "[Jenkins build D4S] build ${currentBuild.fullDisplayName} failed", body: "Something is wrong with ${env.BUILD_URL}" } } } /** * Clones the repository and executes the fragment * NOTE: 'credentialsId' be manually configured in Jenkins to access all the repos */ def checkout_and_exec(repo_name) { def repo_url = "${git_root}/${repo_name}" sh(script: "rm -r ${repo_name} || true", returnStdout: true)?.trim() checkout([ $class : 'GitSCM', branches : [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions : [ [$class: 'RelativeTargetDirectory', relativeTargetDir: repo_name], [$class: 'CloneOption', noTags: false, reference: ''] ], submoduleCfg : [], userRemoteConfigs : [ [credentialsId: '88b54962-1c0e-49cb-8155-22276860f346', url: repo_url] //git.gcube credentials on jenkins ] ]) // just to show we can access the cloned repository get_last_commit(repo_name) //exec the action exec(repo_url, repo_name) } String get_last_commit(repo_name) { String msg; dir(repo_name) { msg = sh(script: 'git rev-parse HEAD', returnStdout: true)?.trim() } return msg; } /** Execs the bash fragment */ def exec(repo_url, repo_name) { def output = ''; dir(repo_name) { withCredentials([usernamePassword(credentialsId: '88b54962-1c0e-49cb-8155-22276860f346', passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) { def complete_url = "${repo_url}.git" def repository = complete_url.replaceFirst(".+://", "https://${GIT_USERNAME}:${GIT_PASSWORD}@") def bashWrapper = """ git remote set-url origin $repository git remote -v git config user.email "git.gcube@localhost" git config user.name "git.gcube" curl "${ACTION_URL}" -o actions.sh chmod a+x actions.sh source actions.sh rm actions.sh git push --force origin HEAD:master || true """ output = sh(script: bashWrapper, returnStdout: true) } } sh "echo -e --- STDOUT FROM REPO ${repo_url} --- >> $ACTION_OUTPUT" sh "echo -e '${output}' >> $ACTION_OUTPUT" sh "echo -e --- END REPO ${repo_url} --- >> $ACTION_OUTPUT" } //a non CPS method is necessary for the usage of splitEachLine() @NonCPS def parseProjectList(def text) { def projects = [] text.readLines().each { project -> if (!project) return projects.add(project) } return projects }