205 lines
7.1 KiB
Groovy
205 lines
7.1 KiB
Groovy
#!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}.xml"
|
|
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.')
|
|
string(name: 'filter_with',
|
|
defaultValue: '',
|
|
description: 'If not empty, only actions including this filter in their output will be reported.')
|
|
|
|
}
|
|
|
|
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 {
|
|
def start_el = "<actions from=\"${actionURL}\">"
|
|
sh "echo -e '${start_el}' >> $ACTION_OUTPUT"
|
|
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"
|
|
}
|
|
}
|
|
sh "echo -e '</actions>' >> $ACTION_OUTPUT"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// post-build actions
|
|
post {
|
|
always {
|
|
script {
|
|
sh '''
|
|
cp $ACTION_REPORT ./action.${PIPELINE_BUILD_NUMBER}.csv
|
|
cat ./action.${PIPELINE_BUILD_NUMBER}.csv
|
|
cp $ACTION_OUTPUT ./action-output.${PIPELINE_BUILD_NUMBER}.xml
|
|
cat ./action-output.${PIPELINE_BUILD_NUMBER}.xml
|
|
'''
|
|
}
|
|
}
|
|
success {
|
|
echo 'The actions pipeline worked!'
|
|
|
|
emailext attachmentsPattern: "**/action*${env.BUILD_NUMBER}.*",
|
|
to: 'manuele.simi@isti.cnr.it,roberto.cirillo@isti.cnr.it,pasquale.pagano@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,roberto.cirillo@isti.cnr.it,pasquale.pagano@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)?.trim()
|
|
}
|
|
}
|
|
if ((!filter_with) || (filter_with && output.contains(filter_with))) {
|
|
def xml_action = """
|
|
<action repo="${repo_url}">
|
|
<stdout>
|
|
${output}
|
|
</stdout>
|
|
</action>
|
|
"""
|
|
sh "echo -e '${xml_action}' >> $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
|
|
} |