12

We were having 2 FreeStyle projects on Jenkins:

One to generate builds(daily builds+manual builds), one other to execute tests.

We are moving to a Multibranch pipeline on jenkins, so my understanding is that we have one project per repository, and that we should use options to have different behavior.

So I can create parameters, to indicate if we want to run the tests, if we want to build the setups, that part I'm ok with it.

My issue is that I need that by default, the tests are NOT executed(because they take a lot of time to generate, and I don't want that developers can by mistake just let the "Execute tests" option checked.

And I need that this option is checked when executing the daily build in the night.

So 2 questions:

  1. How to schedule?
  2. How to provide the parameters value used for this schedule?
4

4 回答 4

8

您可以创建一个单独的多分支作业,该作业将按计划运行并触发您的主作业,覆盖所有必要的参数。它看起来像这样

pipeline {
    agent any
    triggers {
        pollSCM('0 0 * * *')
    }
    stages {
        stage('Triggering the main job') {
            steps {
                build job: "main/${BRANCH_NAME.replace('/', '%2F')}", 
                      parameters: [string(name: 'RUN_TESTS', value: 'true')]
            }
        }
    }
}

您应该将此文件与您的主文件一起放在Jenkinsfile存储库中,并配置一个单独的多分支管道作业以使用此文件。

于 2018-06-27T21:52:02.307 回答
5

为了在同一个工作中保持这一点,需要一些常规的编码。由于您使用 MultiBranch 管道,这一切都可以存在于您的Jenkinsfile

首先,按照 Vitalii 所述设置您的 cron,这将按计划启动工作。

properties([
    pipelineTriggers([cron('0 0 * * *')])
])

接下来,当这个作业被调度触发时,我们要调整它的运行参数。所以首先我们需要检查是什么导致了构建。这可能需要安全脚本批准。

List causes = currentBuild.rawBuild.getCauses().collect { it.getClass().getCanonicalName().tokenize('.').last() }

如果这包含'TimerTriggerCause',那么我们要更新参数。

if (causes.contains('TimerTriggerCause') { 
    setBooleanParam("EXECUTE_TESTS", true)
}

为此,我们在共享库中编写了一个函数,如果您愿意,可以将它放在同一个 Jenkinsfile 中(在管道逻辑之外的底部):

/**
 * Change boolean param value during build
 *
 * @param paramName new or existing param name
 * @param paramValue param value
 * @return nothing
 */
Void setBooleanParam(String paramName, Boolean paramValue) {
    List<ParameterValue> newParams = new ArrayList<>();
    newParams.add(new BooleanParameterValue(paramName, paramValue))
    try {
        $build().addOrReplaceAction($build().getAction(ParametersAction.class).createUpdated(newParams))
    } catch (err) {
        $build().addOrReplaceAction(new ParametersAction(newParams))
    }
}

让工作照常进行。当它开始评估 params.EXECUTE_TESTS 时,这将是 true(而不是默认的 false)。

注意:可能需要为值导入模型

import hudson.model.BooleanParameterValue

把这些放在一起(只是快速拼凑出一个整体的画面),你的 jenkinsfile 最终会是这样的

#!groovy
import hudson.model.BooleanParameterValue


List paramsList = [
    choice(name: 'ACCOUNT_NAME', choices: ['account1', 'account2'].join('\n'), description: 'A choice param'),
    string(name: 'PARAM', defaultValue: 'something', description: 'A string param'),
    booleanParam(defaultValue: false, name: 'EXECUTE_TESTS', description: 'Checkbox'),
]

properties([
    buildDiscarder(logRotator(numToKeepStr: '20')),
    pipelineTriggers([cron('0 18 * * *')]), // 4am AEST/5am AEDT
    disableConcurrentBuilds(),
    parameters(paramList)
])


ansiColor {
    timestamps {
        node {
            try {
                causes = currentBuild.rawBuild.getCauses().collect { it.getClass().getCanonicalName().tokenize('.').last() }
                if (causes.contains('TimerTriggerCause') { 
                    setBooleanParam("EXECUTE_TESTS", true)
                }
                stage('Do the thing') {
                    // Normal do the things like build
                }
                stage('Execute tests if selected') {
                    if (params.EXECUTE_TESTS == true) {
                        // execute tests
                    } else {
                        echo('Tests not executed (Option was not selected/False)')
                    }
                }
            } catch (err) {
                throw err
            } finally {
                deleteDir()
            }
        }
    }
}

/**
 * Change boolean param value during build
 *
 * @param paramName new or existing param name
 * @param paramValue param value
 * @return nothing
 */
Void setBooleanParam(String paramName, Boolean paramValue) {
    List<ParameterValue> newParams = new ArrayList<>();
    newParams.add(new BooleanParameterValue(paramName, paramValue))
    try {
        $build().addOrReplaceAction($build().getAction(ParametersAction.class).createUpdated(newParams))
    } catch (err) {
        $build().addOrReplaceAction(new ParametersAction(newParams))
    }
}
于 2018-06-28T03:17:41.553 回答
0

请允许我提出一个更简单的方法。这适用于声明性管道。

我建议将测试(与应用程序代码一起视为一流代码)和应用程序源代码保存在同一个存储库中。

当 Jenkins 从您的 SCM 签出时,将它们放在一个存储库中,这将允许您在测试套件通过时应用标签(标签)。标签是你最好的朋友,应该尽可能地应用于成功。不幸的是,在撰写本文时,多 SCM 结账似乎不支持标签的应用。

我目前有一个由 5 名开发人员组成的团队,目前正在使用多分支管道来处理他们生成的所有功能分支。我们还有一个“master”和“integration”分支。Master 用于干净的版本。集成是我的关键分支。

声明式管道中的调度非常简单:

triggers { 
    cron('0 22 * * *') 
}

pollSCM 对于更复杂的 crontab 似乎并不可靠。

您可能希望考虑将条件引入声明性管道的一种方法是通过分支名称。

success {
    script {
        if( "${env.BRANCH_NAME}" == "integration" ) {
           //Create Package
           //Upload to Artifactory
           //Apply tag to Git
        }
    }
}

上述示例中的功能分支仅执行单元测试并向开发人员提供反馈。只有集成分支在成功时额外生成一个工件(用于以后的测试阶段)并标记存储库。

如果您不希望基于分支的分叉行为,我建议您在 Jenkins 中定义 2 个不同的作业(管道):一个在白天运行来自开发人员的每个提交,另一个在夜间运行,执行您的 long运行测试。

这就是我对单元测试和系统测试所做的。

单元测试作业是为企业 GitHub 存储库中的每个分支运行的多分支管道。每分钟轮询一次更改,只有集成分支创建工件和标记。单元测试需要 10 分钟才能运行。

系统测试作业是一个简单的管道,计划每晚运行,执行需要一个小时左右。

于 2018-06-29T02:45:51.577 回答
0

这并不能很好地映射到多分支管道中。我已经看到阶段依赖于分支,但没有阶段依赖于参数 - 它也会每天破坏阶段视图。

我推荐的是编写两个单独的 Jenkinsfiles,例如一个叫做Jenkinsfile,第二个可能是Jenkinsnightlyfile. 然后,您可以在同一个存储库上使用不同的 jenkins 文件名创建两个多分支管道项目。

将您的常规阶段放在第一个阶段,将所有测试放在另一个阶段(为了清楚起见,您也可以将这里的工作划分为多个阶段),确保让另一个阶段使用适当的触发器,例如 jenkins-pipeline:

properties([
    pipelineTriggers([cron('0 0 * * *')])
])

或对于声明性管道:

triggers { 
    cron('0 0 * * *') 
}
于 2018-07-02T13:21:23.357 回答