2020-06-06 21:08:48 +02:00
|
|
|
#!groovy
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checkouts and builds notes for released components.
|
|
|
|
*
|
|
|
|
* Manuele Simi (ISTI-CNR)
|
|
|
|
*/
|
|
|
|
|
|
|
|
def agent_root_folder = '/var/lib/jenkins/.m2'
|
|
|
|
|
|
|
|
//locate the build file
|
2020-06-06 21:13:23 +02:00
|
|
|
String reportURL = "https://code-repo.d4science.org/gCubeCI/gCubeReleaseConfigs/raw/branch/master/closed/${gCube_release_version}/build_commits.${report_number}.csv"
|
2020-06-06 21:08:48 +02:00
|
|
|
println "Querying ${reportURL}"
|
|
|
|
|
|
|
|
//load and parse the release file
|
|
|
|
def text = reportURL.toURL().getText()
|
|
|
|
def components = parseBuildCommits(text)
|
|
|
|
assert 0 < components.size(): "No component found in build_commits.${report_number}.csv"
|
|
|
|
for (component in components) {
|
|
|
|
println "$component"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pipeline {
|
|
|
|
|
|
|
|
agent {
|
|
|
|
label 'CD'
|
|
|
|
}
|
|
|
|
|
|
|
|
environment {
|
|
|
|
AGENT_ROOT_FOLDER = "${agent_root_folder}"
|
|
|
|
GCUBE_RELEASE_NUMBER = "${params.gCube_release_version}"
|
|
|
|
PIPELINE_BUILD_NUMBER = "${env.BUILD_NUMBER}"
|
2020-06-06 22:14:37 +02:00
|
|
|
REPORT_NUMBER = "${params.report_number}"
|
2020-06-06 21:08:48 +02:00
|
|
|
RELEASE_NOTES = "${agent_root_folder}/release_notes.${report_number}.md"
|
|
|
|
}
|
|
|
|
|
|
|
|
parameters {
|
|
|
|
|
|
|
|
string(name: 'gCube_release_version',
|
|
|
|
defaultValue: 'x.y.z',
|
|
|
|
description: 'The number of the gCube release. Sample values: 4.14, 4.15, etc.')
|
|
|
|
|
|
|
|
string(name: 'report_number',
|
|
|
|
defaultValue: '',
|
|
|
|
description: 'The report number to use for tagging.')
|
|
|
|
|
|
|
|
booleanParam(name: 'use_report_commits',
|
|
|
|
defaultValue: true,
|
|
|
|
description: 'Use the commits on the report or the latest is on master?')
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
stages {
|
|
|
|
stage('initialize reports') {
|
|
|
|
steps {
|
|
|
|
sh '''
|
|
|
|
date=`date`
|
|
|
|
echo "# Release Notes for gCube ${gCube_release_version}" > $RELEASE_NOTES
|
|
|
|
echo "" >> $RELEASE_NOTES
|
|
|
|
echo "---" >> $RELEASE_NOTES
|
|
|
|
'''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
stage('notes') {
|
|
|
|
steps {
|
|
|
|
script {
|
|
|
|
for (int i = 0; i < components.size(); i++) {
|
|
|
|
stage(components[i]['name']) {
|
|
|
|
appendHeading(components[i]['name'], components[i]['version'])
|
|
|
|
createNotes(components[i]['name'], components[i]['gitRepo'],
|
2020-06-06 22:04:08 +02:00
|
|
|
params.use_report_commits? components[i]['commitID']:null, components[i]['version'], gCube_release_version)
|
2020-06-06 21:08:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
appendFooter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// post-build actions
|
|
|
|
post {
|
|
|
|
always {
|
|
|
|
script {
|
|
|
|
sh '''
|
|
|
|
cp $RELEASE_NOTES ./release_notes.${PIPELINE_BUILD_NUMBER}.md
|
|
|
|
cat ./release_notes.${PIPELINE_BUILD_NUMBER}.md
|
|
|
|
'''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
success {
|
|
|
|
echo 'The release notes pipeline worked!'
|
|
|
|
emailext to: 'jenkinsbuilds@d4science.org',
|
2020-06-06 21:50:40 +02:00
|
|
|
subject: "[Jenkins build D4S] build ${currentBuild.fullDisplayName} worked",
|
2020-06-06 21:08:48 +02:00
|
|
|
body: "Build time: ${currentBuild.durationString}. See ${env.BUILD_URL}"
|
|
|
|
emailext attachmentsPattern: "**/release_notes.${PIPELINE_BUILD_NUMBER}.md",
|
|
|
|
to: 'jenkinsreleases@d4science.org',
|
|
|
|
subject: "Release notes for ${GCUBE_RELEASE_NUMBER} (build #${PIPELINE_BUILD_NUMBER})",
|
|
|
|
body: "Release notes extracted from the CHANGELOG.md(s) of the released components. See ${env.BUILD_URL}"
|
|
|
|
}
|
|
|
|
failure {
|
|
|
|
echo 'The release notes pipeline has failed'
|
|
|
|
emailext attachLog: true,
|
|
|
|
to: 'jenkinsbuilds@d4science.org',
|
|
|
|
subject: "[Jenkins build D4S] build ${currentBuild.fullDisplayName} failed",
|
|
|
|
body: "Something is wrong with ${env.BUILD_URL}"
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clones the repository, tags and creates notes
|
|
|
|
* NOTE: 'credentialsId' be manually configured in Jenkins to access all the repos
|
|
|
|
*/
|
|
|
|
def createNotes(repo_name, repo_url, commit, version, gCube_release_version) {
|
|
|
|
|
|
|
|
echo "Checkout SHA from reference $commit"
|
|
|
|
sh(script: "rm -r ${repo_name} || true", returnStdout: true)?.trim()
|
|
|
|
checkout([
|
|
|
|
$class : 'GitSCM',
|
2020-06-06 22:04:08 +02:00
|
|
|
branches : [[name: commit? commit : '*/master']],
|
2020-06-06 21:08:48 +02:00
|
|
|
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
|
|
|
|
]
|
|
|
|
])
|
|
|
|
|
|
|
|
def log_content = get_changelog(repo_name)
|
2020-06-06 21:23:35 +02:00
|
|
|
appendNotes(extract(log_content, version, gCube_release_version,repo_name))
|
2020-06-06 21:08:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String get_last_commit(repo_name) {
|
|
|
|
String msg;
|
|
|
|
dir(repo_name) {
|
|
|
|
msg = sh(script: 'git rev-parse HEAD', returnStdout: true)?.trim()
|
|
|
|
}
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reads the CHANGELOG.md for the given repository.
|
|
|
|
*
|
|
|
|
* @param repo_name
|
|
|
|
* @return the full content of CHANGELOG.md
|
|
|
|
*/
|
|
|
|
String get_changelog(repo_name) {
|
|
|
|
String text;
|
|
|
|
dir(repo_name) {
|
2020-06-07 17:02:41 +02:00
|
|
|
text = sh(script: 'cat CHANGELOG.md || echo NA', returnStdout: true)?.trim()
|
2020-06-06 21:08:48 +02:00
|
|
|
}
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the notes from the changelog's content.
|
|
|
|
*
|
|
|
|
* @param log_content
|
|
|
|
* @param gCube_release_version
|
|
|
|
* @param tag
|
|
|
|
* @params component
|
|
|
|
* @return the notes for then current release
|
|
|
|
*/
|
|
|
|
String extract(log_content, tag, gCube_release_version, component) {
|
2020-06-07 17:02:41 +02:00
|
|
|
println "Changelong content: ${log_content}"
|
|
|
|
def matcher = "${log_content}" =~ /(?im)\([v${tag}\]\s\[r${gCube_release_version}\].*)\[v.*\]\s\[r.*\]/
|
2020-06-06 21:43:55 +02:00
|
|
|
if (!matcher.find()) {
|
|
|
|
return 'NA'
|
|
|
|
}
|
2020-06-06 21:36:37 +02:00
|
|
|
assert matcher[0]: "Missing release notes for ${component}"
|
2020-06-07 17:02:41 +02:00
|
|
|
for (g in matcher) {
|
|
|
|
println "Group: $g"
|
|
|
|
}
|
2020-06-06 21:36:37 +02:00
|
|
|
return matcher[0]
|
2020-06-06 21:08:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends the header to the release notes file.
|
|
|
|
*/
|
|
|
|
def appendHeader() {
|
|
|
|
sh("""
|
|
|
|
echo "---" >> $RELEASE_NOTES
|
|
|
|
""")
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends the footer to the release notes file.
|
|
|
|
*/
|
|
|
|
def appendFooter() {
|
|
|
|
def now = new Date()
|
|
|
|
sh("""
|
|
|
|
echo "" >> $RELEASE_NOTES
|
|
|
|
echo "---" >> $RELEASE_NOTES
|
2020-06-06 22:14:37 +02:00
|
|
|
echo "*generated by the gCube-ReleaseNotes pipeline from report ${REPORT_NUMBER}*" >> $RELEASE_NOTES
|
2020-06-06 21:08:48 +02:00
|
|
|
echo "" >> $RELEASE_NOTES
|
|
|
|
echo "*last update $now*" >> $RELEASE_NOTES
|
|
|
|
""")
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends the new notes to the release notes file.
|
|
|
|
*
|
|
|
|
* @param repo_notes the notes for the repository to append
|
|
|
|
*/
|
|
|
|
def appendNotes(repo_notes) {
|
|
|
|
sh("""
|
|
|
|
echo "### ${repo_notes}" >> $RELEASE_NOTES
|
|
|
|
""")
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends heading to the release notes file.
|
|
|
|
*
|
|
|
|
* @param name the name of the repository
|
|
|
|
* @param version the version of the component
|
|
|
|
*/
|
|
|
|
def appendHeading(name, version) {
|
|
|
|
sh("""
|
|
|
|
echo "## ${name} ${version}" >> $RELEASE_NOTES
|
|
|
|
""")
|
|
|
|
}
|
|
|
|
|
|
|
|
//a non CPS method is necessary for the usage of splitEachLine()
|
|
|
|
@NonCPS
|
|
|
|
def parseBuildCommits(def text) {
|
|
|
|
def components = []
|
|
|
|
"${text}".splitEachLine(',') { columns ->
|
|
|
|
if (columns[0].startsWith('#') || columns[0].startsWith('GroupID'))
|
|
|
|
return
|
|
|
|
components.add([
|
|
|
|
name : columns[1],
|
|
|
|
version : columns[2],
|
|
|
|
gitRepo : columns[3],
|
|
|
|
commitID: columns[4]
|
|
|
|
]
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return components
|
|
|
|
}
|