如何处理Jenkins声明性管道中的每晚构建

时间:2017-04-20 09:50:11

标签: jenkins jenkins-pipeline

我的repo中有一个带有Jenkinsfile的多分支管道,我可以拥有我的CI工作流程(构建和单元测试 - > deploy-dev - >批准 - > deploy-QA - >批准 - > deploy-prod)每次提交。 我想做的是在第一阶段构建和安装中添加SonarQube分析夜间构建。单元测试。 由于我的构建是由Gitlab触发的,我已经定义了我的管道触发器如下:

pipeline {
    ...
    triggers {
        gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
    }
    ...
}

要设置我的夜间构建,我已添加

triggers {
    ...
    cron('H H * * *')
}

但是现在,如果我们只是在晚上构建由cron表达式触发的作业,如何执行分析步骤?

我的简化构建阶段如下所示:

stage('Build & Tests & Analysis') {
    // HERE THE BEGIN SONAR ANALYSIS  (to be executed on nightly builds)
    bat 'msbuild.exe ...'
    bat 'mstest.exe ...'
    // HERE THE END SONAR ANALYSIS (to be executed on nightly builds)
}

6 个答案:

答案 0 :(得分:5)

有如何获取构建触发器信息的方法。这里描述: https://jenkins.io/doc/pipeline/examples/#get-build-cause

你也可以检查这个: how to get $CAUSE in workflow

对您的案例非常好的参考是https://hopstorawpointers.blogspot.com/2016/10/performing-nightly-build-steps-with.html。以下是该来源的功能,完全符合您的需求:

// check if the job was started by a timer
@NonCPS
def isJobStartedByTimer() {
    def startedByTimer = false
    try {
        def buildCauses = currentBuild.rawBuild.getCauses()
        for ( buildCause in buildCauses ) {
            if (buildCause != null) {
                def causeDescription = buildCause.getShortDescription()
                echo "shortDescription: ${causeDescription}"
                if (causeDescription.contains("Started by timer")) {
                    startedByTimer = true
                }
            }
        }
    } catch(theError) {
        echo "Error getting build cause"
    }

    return startedByTimer
}

答案 1 :(得分:2)

您可以像这样检查构建原因:

stage('Build & Tests & Analysis') {
    when {
        expression {
            for (Object currentBuildCause : script.currentBuild.rawBuild.getCauses()) {
                return currentBuildCause.class.getName().contains('TimerTriggerCause')
            }
        }
        steps {
            bat 'msbuild.exe ...'
            bat 'mstest.exe ...'
        }
    }
}

但是,这需要script-approval.xml中的以下条目:

<approvedSignatures>
  <string>method hudson.model.Run getCauses</string>
  <string>method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild</string>
</approvedSignatures>

这也可以通过https://YOURJENKINS/scriptApproval/批准 希望在JENKINS-41272修复后不需要这样做。

在此之前,解决方法可能是检查when表达式中的小时(请记住,这些时间是指Jenkins的时区)

when { expression { return Calendar.instance.get(Calendar.HOUR_OF_DAY) in 0..3 } }

答案 2 :(得分:2)

对我来说,最简单的方法是在构建触发器中定义一个cron并使用when expression验证每晚的小时:

pipeline {
    agent any
    triggers {
        pollSCM('* * * * *') //runs this pipeline on every commit
        cron('30 23 * * *') //run at 23:30:00 
    }

    stages {
        stage('nightly') {
            when {//runs only when the expression evaluates to true
                expression {//will return true when the build runs via cron trigger (also when there is a commit at night between 23:00 and 23:59)
                    return Calendar.instance.get(Calendar.HOUR_OF_DAY) in 23
                }
            }

            steps {
                echo "Running the nightly stage only at night..."
            }
        }
    }
}

答案 3 :(得分:1)

这适用于声明性管道

when {
    triggeredBy 'TimerTrigger'
}

答案 4 :(得分:0)

我找到了一种不使用受限的“ currentBuild.rawBuild”的方法。开始您的管道:

startedByTimer = false
def buildCauses = "${currentBuild.buildCauses}"
if (buildCauses != null) {
    if (buildCauses.contains("Started by timer")) {
        startedByTimer = true
    }
}

在需要的地方测试布尔值,例如:

stage('Clean') {
   when {
      anyOf {
         environment name: 'clean_build', value: 'Yes'
         expression { (startedByTimer == true) }
     }
  }
  steps {
      echo "Cleaning..."
      ...

答案 5 :(得分:0)

感谢this,您现在可以执行此操作,而无需使用非白名单的currentBuild.getRawBuild().getCauses()函数,该函数可以根据您的设置为您提供Scripts not permitted to use method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild

@NonCPS
def isJobStartedByTimer() {
    def startedByTimer = false
    try {
        def buildCauses = currentBuild.getBuildCauses()
        for ( buildCause in buildCauses ) {
            if (buildCause != null) {
                def causeDescription = buildCause.shortDescription
                echo "shortDescription: ${causeDescription}"
                if (causeDescription.contains("Started by timer")) {
                    startedByTimer = true
                }
            }
        }
    } catch(theError) {
        echo "Error getting build cause"
    }

    return startedByTimer
}