I have a pipeline roughly below (largely borrowed from this) and I need to stop and remove it from the history if it aborts. I'm trying to avoid a plugin. Is there an easy way to delete it from the history?
node {
checkout scm
result = sh (script: "git log -1 | grep '\\[release\\]'", returnStatus: true)
if (result == 0) {
currentBuild.result = 'ABORTED'
}
}
you can add BUILD HISTORY MANAGER(https://plugins.jenkins.io/build-history-manager/) plugin and do it .
then you add this code in pipeline . by this code the history was deleted from 1 to countBuildRemain .
def buildNum = BUILD_ID as Integer
def num = countBuildRemain as Integer
def result = (buildNum) - (num)
options {
buildDiscarder BuildHistoryManager([[actions: [DeleteBuild()],
conditions: [BuildResult(matchAborted: true),
BuildNumberRange(maxBuildNumber: "${result}", minBuildNumber: 1) ]]])
}
Use this script, the current job will be deleted.
(use with caution, not a best practice)
node {
checkout scm
result = sh (script: "git log -1 | grep '\\[release\\]'", returnStatus: true)
if (result == 0) {
currentBuild.result = 'ABORTED'
Run.fromExternalizableId(currentBuild.externalizableId).delete()
}
}
or declarative syntax
post {
success {
}
aborted{
script{
Run.fromExternalizableId(currentBuild.externalizableId).delete()
}
}
}
Related
This repo has three Jenkinsfile in different path. I want to call Jenkinsfiles in different directories in the Jenkinsfile of the root directory and execute them in the same Job. Is there any way can do this? The code is the Jenkinsfile of the root directory.
pipeline{
agent { label "x86_64" }
stages {
stage('Build') {
steps {
dir('python3/python3.6.8')
script {
def Changes6 = sh(returnStdout: true, script: "git diff --name-only ${env.GIT_COMMIT} ${GIT_PREVIOUS_SUCCESSFUL_COMMIT} | grep servicelayer | wc -l").trim()
if (Changes6=="0") {
//TODO: How to trigger the python3/python3.6.8/centos_7.7_1908/build/Jenkinsfile and run in this Job?
}
}
dir('python3/python3.7.9') {
script {
def Changes7 = sh(returnStdout: true, script: "git diff --name-only ${env.GIT_COMMIT} ${GIT_PREVIOUS_SUCCESSFUL_COMMIT} | grep servicelayer | wc -l").trim()
if (Changes7=="0") {
//TODO: How to trigger the python3/python3.7.9/centos_7.7_1908/build/Jenkinsfile and run in this Job?
}
}
}
}
}
}
}
You can create second job for the second jenkinsfile and trigger it from the first pipeline.
build(job: 'foo', parameters: [password('parameter-name', 'secret-value')])
i have a jenkins pipeline witch triggers another pipeline. is it possible to save the result from this triggerd job pipeline in the first pipeline?
Example pipelie 1:
stage('do something') {
when { expression { params.true == true } }
steps {
script {
env.var = build job: 'jenkinsjob2',
parameters: [
]
print(env.var)
}
}
}
jenkinsjob2 pipeline:
stage('do something else') {
when { expression { params.false == false } }
steps{
script {
my_new_result = sh( returnStdout: true, script: 'python script.py')
println my_new_result // echo 12345
I now want to use the result 12345 from the second job in env.var from the first pipeline.
is this possible?
i got for env.var = org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper#6c4ddc63 and not 12345
KR
Marvin
You can check this pipeline to get an idea of what to do.
stage('do something') {
steps
{
script {
def job = build job: "jenkinsjob2",parameters: []
env.my_new_result = job.buildVariables.my_new_result
}sh "echo ${env.my_new_result}"
}
}
I am conducting some tests in my pipeline. My aim is that if an error file exists the build should fail. But if for some reason the tests experienced an exception and didn't write either an error or successful file, the pipeline should also fail. If neither of the conditions for failure are met, I would like the an upstream job to execute.
I wrote it in stage and initially it looked like this:
stage('system tests') {
steps {
dir(project_root) {
def error_exists = sh(
script: 'ls error.txt', returnStatus: true
)
if (error_exists == 0) {
currentBuild.result = 'FAILED'
return
}
build job: 'my-job;
}
}
}
The above code works. When the tests being executed wrote an error file, the pipeline fails. I then tried to modify the code to cater for the outcome where neither error or success files are written.
stage('system tests') {
steps {
dir(project_root) {
def error_exists = sh(
script: 'ls error.txt', returnStatus: true
)
def success_exists = sh(
script: 'ls success.txt', returnStatus: true
)
if (error_exists == 0) {
currentBuild.result = 'FAILED'
return
} else if (success_exists == 1 && error_exists == 1) {
currentBuild.result = 'FAILED'
return
}
build job: 'my-job;
}
}
}
I simulated a situation where neither file was written and the pipeline didn't fail, and instead it triggered the upstream build. Why am I not entering the else if clause` if the result of both shell scripts is false? I took the logical operators from here and I think they should be met (The code below is output from the shell scripts in the new-job pipeline)
[new-job] Running shell script
+ ls error.txt
ls: cannot access error.txt: no such file or directory
[new-job] Running shell script
+ ls success.txt
ls: cannot access success.txt: no such file or directory
If these files do not exist then sh jenkins step returns error code 2. You should rewrite your 'if condition' like that:
success_exists == 2 && error_exists == 2
But, I think that in your case this code is more suitable:
stage('system tests') {
steps {
dir(project_root) {
def error_exists = sh(
script: 'ls error.txt', returnStatus: true
)
def success_exists = sh(
script: 'ls success.txt', returnStatus: true
)
if (error_exists == 0) {
currentBuild.result = 'FAILED'
return
} else if (success_exists != 0 && error_exists != 0) {
currentBuild.result = 'FAILED'
return
}
build job: 'my-job;
}
}
Because there may be other reasons for not being able to find the file (lack of access, etc).
I tried to get the git commit message in jenkinsfile and prevent the build based on commit message.
env.GIT_COMMIT doesn't return the commit details in jenkinsfile.
How to get the git latest commit message and prevent the jenkins build if the commit message contains [ci skip] in it?
I had the same issue. I'm using pipelines. I solved this issue by implementing a shared library.
The code of the library is this:
// vars/ciSkip.groovy
def call(Map args) {
if (args.action == 'check') {
return check()
}
if (args.action == 'postProcess') {
return postProcess()
}
error 'ciSkip has been called without valid arguments'
}
def check() {
env.CI_SKIP = "false"
result = sh (script: "git log -1 | grep '.*\\[ci skip\\].*'", returnStatus: true)
if (result == 0) {
env.CI_SKIP = "true"
error "'[ci skip]' found in git commit message. Aborting."
}
}
def postProcess() {
if (env.CI_SKIP == "true") {
currentBuild.result = 'NOT_BUILT'
}
}
Then, in my Jenkinsfile:
pipeline {
stages {
stage('prepare') { steps { ciSkip action: 'check' } }
// other stages here ...
}
post { always { ciSkip action: 'postProcess' } }
}
As you can see, the build is marked as NOT_BUILT. You can change it to ABORTED if you prefer, but it cannot be set to SUCCESS because a build result can only get worse
The build will pass when [ci skip] is provided in the last git log, but will not run the actual build code (the replacement to the first echo statement)
node {
checkout scm
result = sh (script: "git log -1 | grep '\\[ci skip\\]'", returnStatus: true)
if (result != 0) {
echo "performing build..."
} else {
echo "not running..."
}
}
As for declarative pipeline one can use 'changelog' in 'when' directive to skip a stage:
when {
not {
changelog '.*^\\[ci skip\\] .+$'
}
}
See: https://jenkins.io/doc/book/pipeline/syntax/#when
I think you could easily do that in multi branch pipeline job configuration
Branch Sources > Additional Behaviours > Polling ignores commits with certain messages
As of today, it's quite easy to achieve. The interesting line is the extension named MessageExclusion where excludedMessage accepts a regular expression.
checkout([ $class: 'GitSCM',
branches: [[name: '*/master']],
doGenerateSubmoduleConfigurations: false,
extensions: [[
$class: 'MessageExclusion', excludedMessage: '.*skip-?ci.*'
]],
submoduleCfg: [],
userRemoteConfigs: [[
credentialsId: 'xxx', url: 'git#github.com:$ORG/$REPO.git'
]]
])
I'm trying to use Jenkins file for all our builds in Jenkins, and I have following problem.
We basically have 3 kind of builds:
pull-request build - it will be merged to master after code review, and if build works
manual pull-request build - a build that does the same as above, but can be triggered manually by the user (e.g. in case we have some unstable test)
an initial continuous deliver pipeline - this will build the code, deploy to repository, install artifacts from repository on the target server and start the application there
How should I contain all of the above builds into a single Jenkinsfile.
Right now the only idea I have is to make a giant if that will check which branch it is and will do the steps.
So I have two questions:
1. Is that appropriate way to do it in Jenkinsfile?
How to get the name of currently executing branch in multi-branch job type?
For reference, here's my current Jenkinsfile:
def servers = ['server1', 'server2']
def version = "1.0.0-${env.BUILD_ID}"
stage 'Build, UT, IT'
node {
checkout scm
env.PATH = "${tool 'Maven'}/bin:${env.PATH}"
withEnv(["PATH+MAVEN=${tool 'Maven'}/bin"]) {
sh "mvn -e org.codehaus.mojo:versions-maven-plugin:2.1:set -DnewVersion=$version -DgenerateBackupPoms=false"
sh 'mvn -e clean deploy'
sh 'mvn -e scm:tag'
}
}
def nodes = [:]
for (int i = 0; i < servers.size(); i++) {
def server = servers.get(i)
nodes["$server"] = {
stage "Deploy to INT ($server)"
node {
sshagent(['SOME-ID']) {
sh """
ssh ${server}.example.com <<END
hostname
/apps/stop.sh
yum -y update-to my-app.noarch
/apps/start.sh
END""".stripIndent()
}
}
}
}
parallel nodes
EDIT: removed opinion based question
You can add If statement for multiple stages if you want to skip multiple stages according to the branch as in:
if(env.BRANCH_NAME == 'master'){
stage("Upload"){
// Artifact repository upload steps here
}
stage("Deploy"){
// Deploy steps here
}
}
or, you can add it to individual stage as in:
stage("Deploy"){
if(env.BRANCH_NAME == 'master'){
// Deploy steps here
}
}
Using this post, this worked for me:
stage('...') {
when {
expression { env.BRANCH_NAME == 'master' }
}
steps {
...
}
}
1) I don't know if it is appropriate, but if it resolves your problem, I think is appropriate enough.
2) In order to know the name of the branch you can use BRANCH_NAME variable, its name is taken from the branch name.
${env.BRANCH_NAME}
Here is the answer:
Jenkins Multibranch pipeline: What is the branch name variable?
We followed the model used by fabric8 for builds, tweaking it as we needed, where the Jenkinsfile is used to define the branch and deployment handling logic, and a release.groovy file for build logic.
Here's what our Jenkinsfile looks like for a pipeline that continuously deploys into DEV from master branch:
#!groovy
import com.terradatum.jenkins.workflow.*
node {
wrap([$class: 'TimestamperBuildWrapper']) {
checkout scm
echo "branch: ${env.BRANCH_NAME}"
def pipeline = load "${pwd()}/release.groovy"
if (env.DEPLOY_ENV != null) {
if (env.DEPLOY_ENV.trim() == 'STAGE') {
setDisplayName(pipeline.staging() as Version)
} else if (env.DEPLOY_ENV.trim() == 'PROD') {
setDisplayName(pipeline.production() as Version)
}
} else if (env.BRANCH_NAME == 'master') {
try {
setDisplayName(pipeline.development() as Version)
} catch (Exception e) {
hipchatSend color: 'RED', failOnError: true, message: "<p>BUILD FAILED: </p><p>Check console output at <a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a></p><p><pre>${e.message}</pre></p>", notify: true, room: 'Aergo', v2enabled: false
throw e; // rethrow so the build is considered failed
}
} else {
setDisplayName(pipeline.other() as Version)
}
}
}
def setDisplayName(Version version) {
if (version) {
currentBuild.displayName = version.toString()
}
}
Note: you can find the code for our global pipeline library here.
Don't know if this what you want..
I prefer because it's look more structured.
Jenkinsfile
node {
def rootDir = pwd()
def branchName = ${env.BRANCH_NAME}
// Workaround for pipeline (not multibranches pipeline)
def branchName = getCurrentBranch()
echo 'BRANCH.. ' + branchName
load "${rootDir}#script/Jenkinsfile.${branchName}.Groovy"
}
def getCurrentBranch () {
return sh (
script: 'git rev-parse --abbrev-ref HEAD',
returnStdout: true
).trim()
}
Jenkinsfile.mybranch.Groovy
echo 'mybranch'
// Pipeline code here
for questions 2 you may be able to do
sh 'git branch > GIT_BRANCH'
def gitBranch = readFile 'GIT_BRANCH'
since you're checking out from git
In my scenarium, I have needed run a stage Deploy Artifactory only if the branch was master(webhook Gitlab), otherwise I couldn't perform the deploy.
Below the code of my jenkinsfile:
stages {
stage('Download'){
when{
environment name: 'gitlabSourceBranch', value: 'master'
}
steps{
echo "### Deploy Artifactory ###"
}
}
}