Attach latest build generated file (not log file) from Jenkins emailext? - jenkins

I am running a Jenkins pipline which is calling a script
In following example, running a script which is generating output file with issue_{datetime}.txt
I want to send this file as attachment. However, as file name is generated every time with separate date time stamps not able to find a way to attach file.
e.g.
pipeline {
agent any
stages{
stage('Start Build'){
steps{
python run.py
}
}
}
post {
always {
echo ("${email_id}")
emailext from: 'xyz#yahoo.com', attachmentsPattern: 'resources/*.xlsx',
to: "${email_id}",
}
}
}

You can do it like this try this,
emailext attachmentsPattern: '**/resources/*.xlsx', body: 'Find attachments', subject: 'Attachment', to: 'test#ab.org'

OUTPUT_FILE = sh(script: 'ls -t resources/issue*.xlsx | head -1', returnStdout: true)
emailext from: 'test#yahoo.com', attachmentsPattern:"${OUTPUT_FILE}"

Related

Can't attach the allure report to the Jenkins email

The Allure report is not attaching to the Jenkins email. I am using the Jenkins pipeline script and this is my script however this is the error i get in my email:
Groovy Template file [allure-report.groovy] was not found in $JENKINS_HOME/email-templates.
Also I am not able to find allure-report.groovy in my computer
Here is my Jenkins pipeline, I am not sure how to include the template:
pipeline {
agent {
label {
label ""
customWorkspace "/john/qa-end-to-end"
}
}
tools {nodejs "node"}
stages {
stage('Checkout App') {
steps {
dir("${env.HOME}/app") {
echo "Building.."
sh 'git reset --hard HEAD'
sh 'git clean -f -d'
sh 'git pull'
}
}
}
stage('Starting Tests') {
steps {
echo "Starting End to End Tests"
dir("${env.HOME}/qa-end-to-end/") {
sh './tests.sh'
}
}
}
}
post('Publish Report') {
always {
script {
allure([
includeProperties: false,
jdk: '',
properties: [],
reportBuildPolicy: 'ALWAYS',
results: [[path: '$WORKSPACE/${env.HOME}/app/target/allure-results']]
])
}
}
failure {
emailext(
attachmentsPattern: "$WORKSPACE/${env.HOME}/qa-end-to-end/allure-report/index.html",
body: '''${SCRIPT, template="allure-report.groovy"}''',
subject: "Failure in End to End Tests -> Build Number: ${env.BUILD_NUMBER}",
from: "john#gmail.com",
to: "mike#gmail.com"
)
}
}
}
$JENKINS_HOME/email-templates is used to place email body template, generally when you install Jenkins plugin like email, it which includes some pre-defined templates and those templates will be extracted into $JENKINS_HOME/email-templates after plugin installed.
And when you use send email in job's Post Action, you can choose to use one of template of plugin and Jenkins will try to get the template from folder $JENKINS_HOME/email-templates
If you want to use self template, you need to put it into $JENKINS_HOME/email-templates too.
Using custom scripts (those not packaged with email-ext) requires the cooperation of your Jenkins administrator. The steps are relatively simple:
Create the script/template. The name of the script end in the standard extension for the language (.groovy). The template can be named anything
Have your Jenkins administrator place the script inside $JENKINS_HOME\email-templates.
Use the script token with the template parameter equal to your template filename, or in addition the script parameter equal to the custom script name. For example, if the template filename is foobar.template, the email content would look like this ${SCRIPT, template="foobar.template"}.
More detail

How to export a variable from sh step to outside sh step in jenkins

I am trying to email the output of a file after a build. The build updates the file file1.json. Her is my problem. After build I am trying to create a variable which cat the file1.json ( this is working) , then I am trying to email that variable in emailext.
Stage {
stage('Build'){\
sh """
npm install // builds and update the value in json file
UUID="`cat file1.json`" //outputs the string inside file which is what I want
echo \$UUID //shows the value here
"""
emailext body: "$UUID", //need the value here
subject: "$currentBuild.currentResult-$JOB_NAME",
to: 'someone#test.com'
}
`
The error message is groovy.lang.MissingPropertyException: No such property: UUID for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at
You can use option returnStdout: true of sh() step to get the output of shell.
stage('Build'){
script {
sh 'npm install' // builds and update the value in json file
UUID = sh (script: 'cat file1.json', returnStdout: true).trim()
emailext body: "$UUID", subject: "$currentBuild.currentResult-$JOB_NAME", to: 'someone#test.com'
}
}

Jenkinsfile, prebuild script

I'm a using the jenkins pipeline. My usecase is that the developer are using a simple *.ini file that is parsed by a python script to add or remove stage within the jenkinsfile whenever they want. I don't want them to manually edit the jenkinsfile because they won't know how it works.
Expected behaviour is:
When a build is triggered I would like to first execute a python script which might write into the jenkinsfile to add/remove stage according to the *.ini file.
As far as I understand, when an event trigger a jenkins build, the first thing it does is opening the jenkinsfile. However I would like to know if it's possible to run some prebuild script before that ?
Thanks
Edit: here's a simple view of run of the pipeline (blue ocean UI)
The ini file might for example remove in the stage Compilation the step Building Plan C by removing the groovy code doing that in the jenkins file
Give an example for reference.
node {
git url: '', branch: '', credentialsId: ''
def parseStr = sh(script: 'python parser.py xxx.ini', returnStdout: true).trim()
// the python parser expect to return a JSON string like:
// {'run_stage1': false, 'run_stage2': true}
def parseObj = readJSON text: parseStr
stage('stage 1') {
if(parseObj.run_stage1) {
echo 'stage1'
...
}
}
stage('stage 1') {
if(parseObj.run_stage2) {
echo 'stage1'
....
}
}
}
Jenkins pipeline had supply apis: readJSON, readYaml, readProperties to read JSON, YAML and Properties files.
If you choose any of them to replace ini file, you can drop the python parser to make your pipeline more simple

How to change Email-ext plugin to load script from custom location

I like to commit my Jenkins email script to my working copy and use it with Email-ext.
So I wrote something like :
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building...'
}
}
}
post {
always {
echo 'Sending email...'
emailext body: '''${SCRIPT, template="${WORKSPACE}\\Src\\Scripts\\Jenkins\\groovy-html2.template"}''',
mimeType: 'text/html',
subject: "[Leeroy Jenkins] ${currentBuild.fullDisplayName}",
to: "user#company.com",
replyTo: "user#company.com",
recipientProviders: [[$class: 'CulpritsRecipientProvider']]
}
}
}
But I get the following mail:
Groovy Template file [${WORKSPACE}SrcScriptsJenkinsgroovy-html2.template] was not found in $JENKINS_HOME/email-templates.
Templates must live in the correct directory for security reasons. If you want to keep them in a SCM I suggest you create a Jenkins job that checks out that SCM to the correct directory. Technically though that directory shouldn't be writable but probably is. Alternatively you can use the groovy code in the pipeline itself
On Jenkins 2.190, using a local workspace file as a jelly template, works well. It is pulled with SCM step during the build, and the correct html content is received.
This is the Default Content of my email-ext configuration:
${JELLY_SCRIPT,template="${WORKSPACE}/some_dir/email_template.jelly"}
Solve it by manually overriding the file using command line:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building...'
}
}
}
post {
always {
echo 'Sending email...'
bat "copy /Y ${WORKSPACE}\\Src\\Scripts\\Jenkins\\groovy-html2.template \"${JENKINS_HOME}\\email-templates\\groovy-html2.template\""
emailext body: '''${SCRIPT, template="${WORKSPACE}\\Src\\Scripts\\Jenkins\\groovy-html2.template"}''',
mimeType: 'text/html',
subject: "[Leeroy Jenkins] ${currentBuild.fullDisplayName}",
to: "user#company.com",
replyTo: "user#company.com",
recipientProviders: [[$class: 'CulpritsRecipientProvider']]
}
}
}
A bit crude, but it works.

Jenkins Pipeline - Reading previous stage log

Consider a Jenkins Pipeline with two stages, Stage A then Stage B.
In Stage B, is it possible to parse the logs of Stage A for some particular text?
Use tee to split the output to both stdout and file. Next parse the file for your text.
STAGE_A_LOG_FILE = 'stage_a.log'
pipeline {
agent any
stages {
stage('Stage A') {
steps {
script {
// tee log into file
tee(STAGE_A_LOG_FILE) {
echo 'print some Stage_A log content ...'
}
}
}
}
stage('Stage B') {
steps {
script {
// search log file for 'Stage_A'
regex = java.util.regex.Pattern.compile('some (Stage_A) log')
matcher = regex.matcher(readFile(STAGE_A_LOG_FILE))
if (matcher.find()) {
echo "found: ${matcher.group(1)}"
}
}
}
}
}
}
Pipeline output:
print some Stage_A log content ...
found: Stage_A
Finished: SUCCESS
There's been an update since July 28th !
As mentionned in this answer, as of version 2.4 of Pipeline: Nodes and Processes you can use:
def out = sh script: 'command', returnStdout: true
At least it's much more simple and clean than outputting to a file and reading the file afterwards.
What I finally did was, as suggested, to write to a file (and stdout) using tee.
sh "command | tee <filename>"
Then parse the file as needed, using readFile <filename> to read the file from the workspace.
If you want to search for the first occurrance of a pattern, you can also use manager.logContains(regexp) or manager.getLogMatcher(regexp). See my other answer for more details: https://stackoverflow.com/a/39873765/4527766

Resources