Files
pygitversionhelper/Jenkinsfile
2023-03-23 22:37:45 +00:00

640 lines
33 KiB
Groovy

// pyChaChaDummyProject (c) by chacha
//
// pyChaChaDummyProject is licensed under a
// Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License.
//
// You should have received a copy of the license along with this
// work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
import groovy.xml.XmlUtil
import static javax.xml.xpath.XPathConstants.*
import javax.xml.xpath.*
import groovy.xml.DOMBuilder
import groovy.xml.dom.DOMCategory
import java.math.RoundingMode
// configurable settings:
// use to send email if workflow problem
def _MaintainerName = "CHACHA"
def _MaintainerEmail = "1000CHACHA0001@gmail.com"
// SCM credential ID
def _SCMCredentials = "7fbf4db8-eb36-447c-b2e4-44da4535295f"
// toogle PreRelease flag on Gitea release system
def _bPreRelease = false
// toogle Draft flag on Gitea release system => If False, TAG is not created
def _bDraft = false
// release content / changelog management
def _bAutoChangelog = true //Not supported yet
def _ReleaseContent_Title = "_CI/CD Automatic Release_"
def bPushMasterOnPypi = true
// full rebuild toogle
def _bFullRebuilt = true
def _MkDocsWebURL = "dabauto--mkdocs-web.dmz.chacha.home/mkdocs-web/"
def _MkDocsWebCredentials = "2c5b684e-3787-4b37-8aca-b3dd4a383fe2"
def _PypiCredentials = "Pypi"
def badge_coverage = addEmbeddableBadgeConfiguration(id: "coverage", subject: "unit-test coverage")
def badge_complexity = addEmbeddableBadgeConfiguration(id: "complexity", subject: "code complexity")
// commands Helper: /!\ Made for GITEA /!\
String determineRepoUserName() {
return scm.getUserRemoteConfigs()[0].getUrl().tokenize('/')[3].split("\\.")[0]
}
// commands Helper: /!\ Made for GITEA /!\
String determineRepoName() {
return scm.getUserRemoteConfigs()[0].getUrl().tokenize('/')[4].split("\\.")[0]
}
// commands Helper: /!\ Made for GITEA /!\
String ExtractGiteaBaseUrl(inUrl) {
def pattern = ~/(.*)((?<=\/)[^\/]+\/)([^\/\.]+(?:\.git)?)\/?$/
assert pattern instanceof java.util.regex.Pattern
def matcher = inUrl =~ pattern
assert matcher instanceof java.util.regex.Matcher
assert matcher.find()
assert matcher.size() == 1
return matcher[0][1]
}
String ExtractBaseVersion(inVersion) {
def pattern = ~/^(?<version>[0-9]+\.[0-9]+\.[0-9]+)(?<prerelease>(?:(?:a|b|rc)[0-9]*)?[\.\-_](?:dev|post)\d*)?$/
assert pattern instanceof java.util.regex.Pattern
def matcher = inVersion =~ pattern
assert matcher instanceof java.util.regex.Matcher
assert matcher.find()
assert matcher.size() == 1
return matcher[0][1]
}
int GetCoverageValue(String CoverageFilePath,String XPath)
{
//File file = new File(CoverageFilePath)
//coverageReportRaw = file.getText('UTF-8')
coverageReportRaw = readFile(CoverageFilePath)
coverageReport = DOMBuilder.parse(new StringReader(coverageReportRaw), false, false)
coverageReportRoot = coverageReport.documentElement
def xpath = XPathFactory.newInstance().newXPath()
res = xpath.evaluate(XPath,coverageReportRoot,NUMBER)
return res
}
int GetCoverageValue_lines_valid(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@lines-valid") }
int GetCoverageValue_lines_covered(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@lines-covered") }
int GetCoverageValue_line_rate(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@line-rate") }
int GetCoverageValue_branches_valid(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@branches-valid") }
int GetCoverageValue_branches_covered(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@branches-covered") }
int GetCoverageValue_branch_rate(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@branch-rate") }
int GetCoverageValue_complexity(String CoverageFilePath) { return GetCoverageValue(CoverageFilePath,"/coverage/@complexity") }
pipeline {
// for Docker based build (preferable)
agent { dockerfile true }
// other builds might fall back to generic mode
//agent { any }
// or even require a specific machine
//agent {node {label 'FOO-CIAgent' }}
options {
// enable if the build is using external resource
// or any other reason needing it to be exclusive
// => enabled by default, disable is if more performance needed
disableConcurrentBuilds()
}
environment {
// TERM env variable is needed to make processses think we are on a real terminal
TERM="xterm"
// HOME env variable is needed to allow pip install packages as users
HOME="$env.WORKSPACE"
// _GIT_BRANCH env variable is needed to get the branch only (and not origin/XXXX), without fetching it
_GIT_BRANCH=sh (
script: "echo ${GIT_BRANCH} | sed -e 's|origin/||g'",
returnStdout: true
).trim()
// those 2 env var are for conveniance, get from scm url (which **NEED TO BE GITEA**)
_PROJECT_USER_NAME=determineRepoUserName()
_PROJECT_NAME=determineRepoName()
_GITEA_BASE_URL=ExtractGiteaBaseUrl("$GIT_URL")
PY_PROJECT_NAME = "__NOTSET__"
PY_PROJECT_VERSION = "__NOTSET__"
PY_PROJECT_VERSION_STRIPPED = "__NOTSET__"
}
stages {
stage("Prepare") {
steps {
script {
if (_bFullRebuilt) {
// start by cleaning the workspace (not using cleanWs() because we want to keep the directory itself)
// => this is needed to fetch it again with custom options
sh("find ~/. -name . -o -prune -exec rm -rf -- {} +")
}
else {
sh("find ~/. -name . ! -path './TEST_ENV/*' ! -path './BUILD_ENV/*' -o -prune -exec rm -rf -- {} +")
}
if(_GIT_BRANCH!="master") {
_bPreRelease = true
}
}
// displaying env vars, mainly for debugging purpose
echo("GIT_BRANCH:. . . . . . . . . . . $GIT_BRANCH")
echo("_GIT_BRANCH: . . . . . . . . . . $_GIT_BRANCH")
echo("GIT_URL: . . . . . . . . . . . . $GIT_URL ")
echo("_GITEA_BASE_URL: . . . . . . . . $_GITEA_BASE_URL")
echo("GIT_COMMIT:. . . . . . . . . . . $GIT_COMMIT ")
echo("_PROJECT_USER_NAME:. . . . . . . $_PROJECT_USER_NAME")
echo("_PROJECT_NAME: . . . . . . . . . $_PROJECT_NAME")
echo("_MaintainerEmail:. . . . . . . . $_MaintainerEmail")
echo("_MaintainerName:. . . . . . . . $_MaintainerName")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python BUILD_ENV")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TEST_ENV")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TOOLS_ENV")
sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade setuptools build pip copier jinja2-slug toml")
sh(". ~/TOOLS_ENV/bin/activate && pip install simple_rest_client requests twine")
script {
if(_PROJECT_NAME!="pygitversionhelper") {
sh(". ~/TOOLS_ENV/bin/activate && pip install pygitversionhelper")
}
else
{
//TODO: need to install pygitversionhelper deps from a better way...
sh(". ~/TOOLS_ENV/bin/activate && pip install packaging")
}
}
sh("git config --global user.email $_MaintainerEmail")
sh("git config --global user.name $_MaintainerName")
sh("git config --global init.defaultBranch master")
}
}
stage("GetCode") {
steps {
dir("gitrepo") {
// manually checkout the repository, with All branches and tags
// => because we might need them for version and changelog computing
checkout([ $class: "GitSCM",
branches: [[name: GIT_BRANCH]],
extensions: [[$class: "CloneOption", noTags: false, shallow: false, depth: 0, reference: '']],
userRemoteConfigs: [[credentialsId: _SCMCredentials, url: GIT_URL]]])
script {
withCredentials([usernamePassword(credentialsId: _SCMCredentials, passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh("git remote set-url origin https://${GIT_USERNAME}:${GIT_PASSWORD}@chacha.ddns.net/gitea/${_PROJECT_USER_NAME}/${_PROJECT_NAME}.git")
}
if(_GIT_BRANCH=="master") {
if(sh(returnStdout: true, script: "git tag --points-at HEAD").trim().isEmpty()) {
BUMPED_VERSION = sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import re
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|lastcommit=gitversionhelper.commit.getLast(same_branch=True)
|msg=gitversionhelper.commit.getMessage(lastcommit)
|
|_match=re.search(r"\\s*(?:#)?\\s*(?<=new-tag:)(?:\\s*)(?P<TAG>\\S*)",msg)
|print(_match.group("TAG"),end="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true).trim()
if(BUMPED_VERSION.isEmpty()) {
echo "master push/merge must have an explicit tag release number, stopping pipeline"
currentBuild.getRawBuild().getExecutor().doStop()
}
else {
echo "new-tag requested in commit message: $BUMPED_VERSION"
sh("git tag $BUMPED_VERSION")
sh("git push origin --tags")
}
}
}
latestTag = sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|print(gitversionhelper.tag.getLastTag(same_branch=True),end ="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true)
echo("latestTag:. . . . . . . . . . . . $latestTag ")
// get current (or bumped) version number from git history
PY_PROJECT_VERSION = sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|print(gitversionhelper.version.getCurrentVersion(formated_output=True,version_std="PEP440",bump_type="dev",bump_dev_strategy="post"),end ="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true)
echo("PY_PROJECT_VERSION: . . . . . . . . . $PY_PROJECT_VERSION")
PY_PROJECT_VERSION_STRIPPED=ExtractBaseVersion(PY_PROJECT_VERSION)
// Manually pushing a new tag with version string guessed by gitversionhelper
// because setuptools-git-versioning / setuptools_scm cant fing tag on other branches, so will guess a wrong version without this tag.
if(latestTag!=PY_PROJECT_VERSION) {
sh("git tag $PY_PROJECT_VERSION")
sh("git push origin --tags")
}
// specific handling to test the template itself
// => little hacky... creating a new git repo with a commit/tag corresponding to HEAD of the official one
if(_PROJECT_NAME=="pyChaChaDummyProject") { //specific case to test the template itself
sh("rm -Rf ~/_gitrepo || true")
sh(script: """#!/bin/sh -
|. ~/BUILD_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import dunamai
|
|# override default dunamai version pattern to make leading 'v' optionnal
|dunamai.VERSION_SOURCE_PATTERN = r'''
| (?x) (?# ignore whitespace)
| ^v?((?P<epoch>\\d+)!)?(?P<base>\\d+(\\.\\d+)*) (?# v1.2.3 or v1!2000.1.2)
| ([-._]?((?P<stage>[a-zA-Z]+)[-._]?(?P<revision>\\d+)?))? (?# b0)
| (\\+(?P<tagged_metadata>.+))?\$ (?# +linux)
|'''.strip()
|
|import copier
|copier.run_auto("./", "../_gitrepo",vcs_ref="HEAD",use_prereleases=True,defaults=True,cleanup_on_error=False)
|
|__EOWRAPPER__
""".stripMargin())
// we can not remove the directory because Jenkins is inside...
// => so we painfully remove the inside stuff
sh("find ~/gitrepo/ -mindepth 1 -type f -exec rm {} \\;")
sh("find ~/gitrepo/ -mindepth 1 -type d -empty -delete")
sh("cp -a ~/_gitrepo/. ~/gitrepo")
sh("git init")
sh("git add .")
sh("git commit -m \"init repo\"")
sh("git tag ${PY_PROJECT_VERSION}")
}
PY_PROJECT_NAME = sh(script: """#!/bin/sh -
|. ~/BUILD_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import toml
|
|with open("pyproject.toml") as pyproject:
| pyproject_data = toml.load(pyproject)
| print(pyproject_data["project"]["name"], end ="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true)
echo("PY_PROJECT_NAME: . . . . . . . . . $PY_PROJECT_NAME")
}
}
}
}
stage("BuildPackage") {
steps {
// no need for a build-env: setuptools is already creating one
dir("gitrepo") {
script {
// actually doing the package build
sh(". ~/BUILD_ENV/bin/activate && python -m build .")
}
}
}
}
stage("Install") {
steps {
dir("gitrepo") {
script {
// searching for the built package
def wheelPath = findFiles(glob: "**/dist/*.whl")[0]
echo "wheel artifact path: $wheelPath"
// install the package, with *test* optionnal packages, as user
sh(". ~/TEST_ENV/bin/activate && pip install --find-links dist/ ${PY_PROJECT_NAME} .[test,coverage-check,quality-check,type-check,doc-gen]")
}
}
}
}
stage("CheckCode") {
steps {
dir("gitrepo") {
sh(". ~/TEST_ENV/bin/activate && python -m helpers --type-check --quality-check")
}
}
post {
always {
dir("gitrepo") {
publishHTML([
reportDir: "helpers-results/quality_check",
reportFiles: "report.html",
reportName: "quality-report",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
}
}
}
}
stage("PlotMetrics") {
steps {
plot([ csvFileName: 'plot-df7f03dc-8146-11ed-a1eb-0242ac120002.csv',
csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_GlobalScore.csv', inclusionFlag: 'OFF', url: '']],
group: 'metrics',
title: 'code quality score',
style: 'line',
keepRecords: true,
numBuilds: '',
yaxisMaximum: '10',
yaxisMinimum: '0'])
plot([ csvFileName: 'plot-c731cc84-8145-11ed-a1eb-0242ac120002.csv',
csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_rawpercent.csv', inclusionFlag: 'OFF', url: '']],
group: 'metrics',
title: 'code composition (%)',
style: 'stackedArea',
keepRecords: true,
numBuilds: '',
yaxisMaximum: '1',
yaxisMinimum: '0'])
plot([ csvFileName: 'plot-cac33982-8145-11ed-a1eb-0242ac120002.csv',
csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_Statistics.csv', inclusionFlag: 'OFF', url: '']],
group: 'metrics',
title: 'general statistics',
style: 'line',
keepRecords: true,
numBuilds: ''])
plot([ csvFileName: 'plot-cddaced2-8145-11ed-a1eb-0242ac120002.csv',
csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_MessagesCat.csv', inclusionFlag: 'OFF', url: '']],
group: 'metrics',
title: 'quality warnings',
style: 'stackedArea',
keepRecords: true,
numBuilds: ''])
}
}
stage("RunUnitTests") {
steps {
dir("gitrepo") {
sh(". ~/TEST_ENV/bin/activate && python -m helpers --unit-test --coverage-check")
script {
unit_test_full_name__html=findFiles(glob: "helpers-results/unit_test_full/*.html")[0].getName()
println unit_test_full_name__html
unit_test_full_name__xml=findFiles(glob: "helpers-results/unit_test_full/*.xml")[0].getName()
println unit_test_full_name__xml
coverage_report_path = "helpers-results/unit_test_coverage/test_coverage.xml"
println GetCoverageValue_lines_valid(coverage_report_path)
println GetCoverageValue_lines_covered(coverage_report_path)
println GetCoverageValue_line_rate(coverage_report_path)
println GetCoverageValue_branches_valid(coverage_report_path)
println GetCoverageValue_branches_covered(coverage_report_path)
println GetCoverageValue_branch_rate(coverage_report_path)
println GetCoverageValue_branches_complexity(coverage_report_path)
full_rate = 1.0 * (GetCoverageValue_line_rate(coverage_report_path) + GetCoverageValue_branch_rate(coverage_report_path)) / 2
sz_full_rate =Float.toString(full_rate.setScale(2, RoundingMode.HALF_EVEN))
badge_coverage.setStatus(sz_full_rate)
complexity = 1.0 * GetCoverageValue_complexity(coverage_report_path)
sz_complexity =Float.toString(complexity.setScale(2, RoundingMode.HALF_EVEN))
badge_complexity.setStatus(sz_complexity)
}
}
}
post {
always {
dir("gitrepo") {
junit 'helpers-results/unit_test/*.xml'
// using cobertura format (= coverage xml format)
publishCoverage adapters: [cobertura(mergeToOneReport: true, path: "helpers-results/unit_test_coverage/test_coverage.xml")]
publishHTML([
reportDir: "helpers-results/unit_test_coverage",
reportFiles: "index.html",
reportName: "coverage-report-html",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
publishHTML([
reportDir: "helpers-results/unit_test_full",
reportFiles: unit_test_full_name__html,
reportName: "test-reports-full",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
}
}
}
}
stage("GenDOC") {
steps {
dir("gitrepo") {
//--doc-gen-pdf
sh(". ~/TEST_ENV/bin/activate && python -m helpers --doc-gen --doc-gen-pdf")
}
}
post {
always {
dir("gitrepo") {
publishHTML([
reportDir: "helpers-results/doc_gen/site",
reportFiles: "index.html",
reportName: "doc-html",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
}
}
}
}
stage("PostRelease") {
environment {
def GITEA_LOGIN_TOKEN=credentials("GiteaCHACHAPush")
}
steps {
dir("gitrepo") {
script {
def CurrentDateTime=java.time.LocalDateTime.now()
withCredentials([string( credentialsId: _MkDocsWebCredentials,variable: 'MKDOCSTOKEN' )]) {
sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import json
|import glob
|import requests
|import shutil
|
|from simple_rest_client.api import API
|from simple_rest_client.resource import Resource
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|from urllib.parse import urljoin
|
|class GiteaRepoCommits(Resource):
| actions = {
| 'get': {'method': 'GET', 'url': '/repos/{}/{}//git/commits/{}'},
|}
|
|class GiteaRepoReleases(Resource):
| actions = {
| 'get': {'method': 'GET', 'url': '/repos/{}/{}/releases'},
| 'post': {'method': 'POST', 'url': '/repos/{}/{}/releases'},
|}
|
|class GiteaRepoReleaseAssets(Resource):
| actions = {
| 'get': {'method': 'GET', 'url': '/repos/{}/{}/releases/{}/assets'},
| 'post': {'method': 'POST', 'url': '/repos/{}/{}/releases/{}/assets'},
|}
|
|class GiteaRepoReleaseAssetAttachments(Resource):
| actions = {
| 'get': {'method': 'GET', 'url': '/repos/{}/{}/releases/{}/assets/{}'},
|}
|
|class _GiteaApi(API):
| def __init__(self,**args):
| super().__init__(**args)
| self.add_resource(resource_name="commits", resource_class = GiteaRepoCommits)
| self.add_resource(resource_name="releases", resource_class = GiteaRepoReleases)
| self.add_resource(resource_name="assets", resource_class = GiteaRepoReleaseAssets)
| self.add_resource(resource_name="attachments", resource_class = GiteaRepoReleaseAssetAttachments)
|
|GiteaApi = _GiteaApi(
| api_root_url=urljoin('${_GITEA_BASE_URL}','api/v1/'),
| headers={"Authorization":"token ${GITEA_LOGIN_TOKEN_PSW}"},
|)
|
|
|ReleaseContent = "${_ReleaseContent_Title}" + "\\n" \\
| + "\\n" \\
| + "Reference documentation: [mkdocs page](https://chacha.ddns.net/mkdocs-web/${_PROJECT_USER_NAME}/${PY_PROJECT_NAME}/${_GIT_BRANCH}/${PY_PROJECT_VERSION_STRIPPED}/) "
|
|data={
| "body": ReleaseContent,
| "draft": bool("${_bDraft}"=="true"),
| "name": "${PY_PROJECT_NAME}_${CurrentDateTime}",
| "prerelease": bool("${_bPreRelease}"=="true"),
| "tag_name": "${PY_PROJECT_VERSION}",
| "target_commitish": "${GIT_COMMIT}",
|}
|new_release_id = GiteaApi.releases.post("${_PROJECT_USER_NAME}","${PY_PROJECT_NAME}",json=data).body['id']
|
|data = {
| "name": "Wheel Package",
| 'attachment': (glob.glob('dist/*.whl')[0], open(glob.glob('dist/*.whl')[0], 'rb')),
|}
|GiteaApi.assets.post("${_PROJECT_USER_NAME}","${PY_PROJECT_NAME}",new_release_id,files=data)
|
|data = {
| "name": "Documentation (pdf)",
| 'attachment': ("${PY_PROJECT_NAME}_${PY_PROJECT_VERSION}_UserManual.pdf", open("helpers-results/doc_gen/site/pdf/manual.pdf", 'rb')),
|}
|GiteaApi.assets.post("${_PROJECT_USER_NAME}","${PY_PROJECT_NAME}",new_release_id,files=data)
|
|shutil.make_archive("doc", 'zip', "helpers-results/doc_gen/site")
|reqData={
| "SECRET": "${MKDOCSTOKEN}",
| "USER": "${_PROJECT_USER_NAME}",
| "PACKAGE": "${PY_PROJECT_NAME}",
| "BRANCH": "${_GIT_BRANCH}",
| "VERSION": "${PY_PROJECT_VERSION}",
|}
|files = {'DATA': open('doc.zip','rb')}
|response=requests.post("http://${_MkDocsWebURL}/API.php?REQ=pushDoc",data=reqData,files=files)
|if response.status_code != 200:
| raise RuntimeError(f"Wrong server response: {response.status_code}")
|
|__EOWRAPPER__
""".stripMargin())
}
if((_GIT_BRANCH=="master") && (bPushMasterOnPypi)) {
withCredentials([usernamePassword( credentialsId: _PypiCredentials, passwordVariable: 'PYPI_PASSWORD', usernameVariable: 'PYPI_USERNAME')]) {
sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec twine upload -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --non-interactive --disable-progress-bar dist/*
""".stripMargin())
}
}
}
}
}
}
}
post {
failure {
emailext body: 'Check console output at $BUILD_URL to view the results. \n\n ${CHANGES} \n\n -------------------------------------------------- \n${BUILD_LOG, maxLines=100, escapeHtml=false}',
to: _MaintainerEmail,
subject: 'Build failed in Jenkins: $PROJECT_NAME - #$BUILD_NUMBER'
}
unstable {
emailext body: 'Check console output at $BUILD_URL to view the results. \n\n ${CHANGES} \n\n -------------------------------------------------- \n${BUILD_LOG, maxLines=100, escapeHtml=false}',
to: _MaintainerEmail,
subject: 'Unstable build in Jenkins: $PROJECT_NAME - #$BUILD_NUMBER'
}
changed {
emailext body: 'Check console output at $BUILD_URL to view the results.',
to: _MaintainerEmail,
subject: 'Jenkins build is back to normal: $PROJECT_NAME - #$BUILD_NUMBER'
}
}
}