Jenkinsfile - use Global properties in post - jenkins

Here is my Jenkinsfile for multi-branch pipeline project:
pipeline {
agent any
stages {
stage('MASTER build') {
when {
branch 'master'
}
steps {
sh 'mvn -P x clean deploy'
}
}
stage('BRANCH build') {
when {
not { branch 'master' }
}
steps {
sh 'mvn -P x clean package'
}
}
}
post {
failure {
emailext "${EMAIL_TEMPLATE}"
}
}
}
When I build my project in Jenkis following error occurs:
WorkflowScript: 26: Step does not take a single required parameter - use named parameters instead # line 26, column 13.
emailext "${EMAIL_TEMPLATE}"
Why I cant use EMAIL_TEMPLATE global variable containing all emailext definition?

Related

How make dynamic change stage name in Jenkinsfile Declarative pipeline?

I have Jenkinsfile (Scripted Pipeline)
def template1 = "spread_sshkeys"
node {
// Clean before build
stage('Checkout') {
deleteDir()
checkout scm
sh "git submodule foreach --recursive git pull origin master";
}
stage("import template ${template1}") {
script{
sh "ls -las; cd jenkins-ci-examples; ls -las";
jenkins_ci_examples.sub_module = load "jenkins-ci-examples/${template1}"
}
}
stage("run template ${template1}") {
sh "echo ${jenkins_ci_examples.sub_module}";
}
}
after want to Converting to Declarative
def template1 = "spread_sshkeys"
pipeline {
agent any
stages {
stage ("Checkout") {
steps {
deleteDir()
checkout scm
sh "git submodule foreach --recursive git pull origin master"
}
}
stage("import template ${template1}") {
steps {
script {
sh "ls -las; cd jenkins-ci-examples; ls -las";
jenkins_ci_examples.sub_module = load "jenkins-ci-examples/${template1}"
}
}
}
stage("run template ${template1}") {
steps {
sh "echo ${jenkins_ci_examples.sub_module}";
}
}
}
}
After start Jenkins Job stop and return Error
WorkflowScript: 22: Expected string literal # line 22, column 19.
stage("import template ${template1}") {
^
WorkflowScript: 30: Expected string literal # line 30, column 19.
stage("run template ${template1}") {
^
Try to use
stage('run template ${template1}')
and else
stage('run template '+template1)
returned error too.
How solve this problem?
You can create dynamic stages using sequential stages as below:
def template1 ="spread_sshkeys"
pipeline {
agent any
stages {
stage('Dynamic Stages') {
steps {
script {
stage("import template ${template1}"){
println("${env.STAGE_NAME}")
}
stage("run template ${template1}"){
println("${env.STAGE_NAME}")
}
}
}
}
}
}

Error WorkflowScript: 8: Expected one of "steps", "stages", or "parallel" for stage "check out scm" when need to run a pipeline

I write this pipeline for run that after push on the develop branch or master branch and doing some workers related to that branch.
I want to check the repository and run pipeline after push on the any branches
pipeline {
triggers {
pollSCM('*/1 * * * * ')
}
agent any
stages {
stage('Check out scm') {
when {
branch 'master'
}
checkout scm
}
stage('Install npm') {
steps {
sh 'npm install'
}
}
stage('Build Project Develop') {
when {
branch 'develop'
}
steps {
sh 'ng build --prod '
}
}
stage('Build Project Realase')
{
when {
branch 'master'
}
steps {
sh 'ng build --prod '
}
}
stage('Move to Var') {
steps {
sh 'chown -R root:jenkins /var/lib/jenkins/workspace/Angular-CI-CD--Test_master/dist/ang-CICD/. && /var/www/html'
}
}
}
}
But it shows me this error:
Branch indexing
Connecting to https://api.github.com using kiadr9372/****** (GitHub Access Token)
Obtained Jenkinsfile from d57840a79c46a88969381cc978f378c7d6804cec
Running in Durability level: MAX_SURVIVABILITY
GitHub has been notified of this commit’s build result
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 8: Unknown stage section "checkout". Starting with version 0.5, steps in a stage must be in a ‘steps’ block. # line 8, column 9.
stage('check out scm') {
^
WorkflowScript: 8: Expected one of "steps", "stages", or "parallel" for stage "check out scm" # line 8, column 9.
stage('check out scm') {
^
What is the problem?
Solution
You need to place checkout scm within a step closure. You also have an additional closing bracket.
pipeline {
triggers {
pollSCM('*/1 * * * * ')
}
agent any
stages {
stage('check out scm') {
when {
branch 'master'
}
steps {
checkout scm
}
}
stage('Install npm') {
steps {
sh 'npm install'
}
}
stage('Build Project Develop') {
when {
branch 'develop'
}
steps {
sh 'ng build --prod '
}
}
stage('Build Project Realase') {
when {
branch 'master'
}
steps {
sh 'ng build --prod '
}
}
stage('Move to Var') {
steps {
sh 'chown -R root:jenkins /var/lib/jenkins/workspace/Angular-CI-CD--Test_master/dist/ang-CICD/. && /var/www/html'
}
}
}
}

Is it possible to check if checked out from a specific repository in a Jenkins declarative pipeline?

I would like to have a release stage in my Jenkinsfile that only runs when it's checked out from the original repository. This is to avoid error messages on cloned repositories, because of missing keys etc. there.
stage('Release')
{
when
{
allOf
{
// TODO Check for repository url https://github.com/PowerStat/TemplateEngine.git
branch 'master'
}
}
steps
{
script
{
if (isUnix())
{
sh 'mvn --batch-mode release:clean'
sh 'mvn --batch-mode release:prepare'
sh 'mvn --batch-mode release:perform'
}
else
{
bat 'mvn --batch-mode release:clean'
bat 'mvn --batch-mode release:prepare'
bat 'mvn --batch-mode release:perform'
}
}
}
}
I have studied Pipeline Syntax: when but have no idea how to do the test I would like to have.
Also I thought about using an environment variable Global Variable Reference, but found non with the repository URL in it.
So my question is: how to implement this check in a decalarative pipeline?
You can get remote repository URL from git config remote.origin.url command. You can execute this command using expression directive inside the when block - it defines a closure that returns a boolean value.
Consider the following example:
def expectedRemoteUrl = "https://github.com/PowerStat/TemplateEngine.git"
pipeline {
agent any
stages {
stage("Release") {
when {
allOf {
branch 'tmp'
expression {
def remoteUrl = isUnix() ?
sh(script: "git config remote.origin.url", returnStdout: true)?.trim() :
bat(script: "git config remote.origin.url", returnStdout: true)?.trim()
return expectedRemoteUrl == remoteUrl
}
}
}
steps {
echo "Do your release steps here..."
}
}
}
}
Alternatively, if git command is not available in the node that runs the pipeline, you can get the remote repository URL with scm.userRemoteConfigs?.first()?.url. Consider the following example:
def expectedRemoteUrl = "https://github.com/PowerStat/TemplateEngine.git"
pipeline {
agent any
stages {
stage("Release") {
when {
allOf {
branch 'tmp'
expression {
def remoteUrl = scm.userRemoteConfigs?.first()?.url
return expectedRemoteUrl == remoteUrl
}
}
}
steps {
echo "Do your release steps here..."
}
}
}
}

Declarative pipeline when condition in post

As far as declarative pipelines go in Jenkins, I'm having trouble with the when keyword.
I keep getting the error No such DSL method 'when' found among steps. I'm sort of new to Jenkins 2 declarative pipelines and don't think I am mixing up scripted pipelines with declarative ones.
The goal of this pipeline is to run mvn deploy after a successful Sonar run and send out mail notifications of a failure or success. I only want the artifacts to be deployed when on master or a release branch.
The part I'm having difficulties with is in the post section. The Notifications stage is working great. Note that I got this to work without the when clause, but really need it or an equivalent.
pipeline {
agent any
tools {
maven 'M3'
jdk 'JDK8'
}
stages {
stage('Notifications') {
steps {
sh 'mkdir tmpPom'
sh 'mv pom.xml tmpPom/pom.xml'
checkout([$class: 'GitSCM', branches: [[name: 'origin/master']], doGenerateSubmoduleConfigurations: false, submoduleCfg: [], userRemoteConfigs: [[url: 'https://repository.git']]])
sh 'mvn clean test'
sh 'rm pom.xml'
sh 'mv tmpPom/pom.xml ../pom.xml'
}
}
}
post {
success {
script {
currentBuild.result = 'SUCCESS'
}
when {
branch 'master|release/*'
}
steps {
sh 'mvn deploy'
}
sendNotification(recipients,
null,
'https://link.to.sonar',
currentBuild.result,
)
}
failure {
script {
currentBuild.result = 'FAILURE'
}
sendNotification(recipients,
null,
'https://link.to.sonar',
currentBuild.result
)
}
}
}
In the documentation of declarative pipelines, it's mentioned that you can't use when in the post block. when is allowed only inside a stage directive.
So what you can do is test the conditions using an if in a script:
post {
success {
script {
if (env.BRANCH_NAME == 'master')
currentBuild.result = 'SUCCESS'
}
}
// failure block
}
Using a GitHub Repository and the Pipeline plugin I have something along these lines:
pipeline {
agent any
stages {
stage('Build') {
steps {
sh '''
make
'''
}
}
}
post {
always {
sh '''
make clean
'''
}
success {
script {
if (env.BRANCH_NAME == 'master') {
emailext (
to: 'engineers#green-planet.com',
subject: "${env.JOB_NAME} #${env.BUILD_NUMBER} master is fine",
body: "The master build is happy.\n\nConsole: ${env.BUILD_URL}.\n\n",
attachLog: true,
)
} else if (env.BRANCH_NAME.startsWith('PR')) {
// also send email to tell people their PR status
} else {
// this is some other branch
}
}
}
}
}
And that way, notifications can be sent based on the type of branch being built. See the pipeline model definition and also the global variable reference available on your server at http://your-jenkins-ip:8080/pipeline-syntax/globals#env for details.
Ran into the same issue with post. Worked around it by annotating the variable with #groovy.transform.Field. This was based on info I found in the Jenkins docs for defining global variables.
e.g.
#!groovy
pipeline {
agent none
stages {
stage("Validate") {
parallel {
stage("Ubuntu") {
agent {
label "TEST_MACHINE"
}
steps {{
sh "run tests command"
recordFailures('Ubuntu', 'test-results.xml')
junit 'test-results.xml'
}
}
}
}
}
post {
unsuccessful {
notify()
}
}
}
// Make testFailures global so it can be accessed from a 'post' step
#groovy.transform.Field
def testFailures = [:]
def recordFailures(key, resultsFile) {
def failures = ... parse test-results.xml script for failures ...
if (failures) {
testFailures[key] = failures
}
}
def notify() {
if (testFailures) {
... do something here ...
}
}

Chained multiple pipeline based on 'post' jenkins block

I'm beginner to Jenkins. I have code pipeline structure like this
Repo1 -> Repo2 -> Repo3 -> Deploy
I already created such hierarchy via GUI but I want to create it via pipeline as code.I want to create chain of pipelines where I clone different repos and perform tests on it and then continue to another repo based on current pipeline post result.
This is my jenkinsfile - (psuedo code like as it gives me error to build)
pipeline {
agent any
stages {
stage('Build Repo1') {
steps {
sh 'echo "repo1 build!"'
}
}
stage('Test Repo1') {
steps {
sh 'echo "repo success!"'
}
}
}
post {
success {
pipeline {
agent any
stages {
stage('Build Repo2') {
steps {
sh 'echo "build repo2!"'
}
}
stage('Test Repo2') {
steps {
sh 'echo "test repo2!"'
}
}
}
post {
success {
# continue to generate pipeline for repo3
echo 'This will always run'
}
failure {
echo 'This will run only if failed'
}
}
}
}
failure {
echo 'This will run only if failed'
}
unstable {
echo 'This will run only if the run was marked as unstable'
}
changed {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
}
}
Please help!

Resources