将整个Jenkins阶段提取到共享库?

时间:2018-11-08 04:42:04

标签: jenkins groovy jenkins-pipeline

是否可以采用整个stage('foo') {...}定义并将其提取到Jenkins中的共享库中?文档非常清楚如何拉出单个步骤,但是我找不到任何方法可以进行整个阶段,对其进行参数化并在全球范围内重复使用。我以为也许return stage...可以工作,但是它会错误地认为是无效的返回值。

1 个答案:

答案 0 :(得分:4)

这取决于您使用脚本还是声明性管道。

脚本化管道更灵活,例如,根据某些条件创建阶段(每个管道运行可以具有不同数量和种类的阶段)。在这种管道中,您可以将整个阶段提取到共享库类中,并将其提取到node {}块中。考虑以下示例:

// src/ScriptedFooStage.groovy
class ScriptedFooStage {
    private final Script script

    ScriptedFooStage(Script script) {
        this.script = script
    }

    // You can pass as many parameters as needed
    void execute(String name, boolean param1) {
        script.stage(name) {
            script.echo "Triggering ${name} stage..."
            script.sh "echo 'Execute your desired bash command here'"

            if (param1) {
                script.sh "echo 'Executing conditional command, because param1 == true'"
            }
        }
    }
}

然后 Jenkinsfile 可能看起来像这样:

node {
    new ScriptedFooStage(this).execute('Foo', true)
}

您可以看到整个阶段都封装在ScriptedFooStage.execute()方法中。它的名称也来自参数name-脚本化管道允许您执行此操作。


另一方面,

声明性管道更为严格和自以为是。如果涉及到阶段数及其名称,则此问题是固定的(您无法动态建模每个构建中存在的阶段及其名称)。您仍然可以利用共享库类,但是只能在script {}块内的stage('Name') { steps {} }块内执行它们。这意味着您不能将整个阶段提取到单独的类中,而只能将某些部分提取到步骤级别。考虑以下示例:

// src/DeclarativeFooStage.groovy
class DeclarativeFooStage {
    private final Script script

    DeclarativeFooStage(Script script) {
        this.script = script
    }

    // You can pass as many parameters as needed
    void execute(String name, boolean param1) {
        script.echo "Triggering script with name == ${name}"
        script.sh "echo 'Execute your desired bash command here'"

        if (param1) {
            script.sh "echo 'Executing conditional command, because param1 == true'"
        }
    }
}

Jenkinsfile 可能看起来像这样:

// Jenkinsfile
pipeline {
    agent any

    stages {
        stage('Foo') {
            steps {
                script {
                    new DeclarativeFooStage(this).execute('something', false)
                }
            }
        }
    }
}

如果我们尝试在声明性管道的new DeclarativeFooStage(this).execute('something', false)块外执行script {},则会出现编译错误。

结论

脚本式还是声明式管道之间的选择取决于特定的用例。如果要在对管道业务逻辑进行建模时获得最大的灵活性,则脚本化管道可能是不错的选择。但是,它附带一些价格。例如,脚本化管道不支持从特定阶段重新启动管道构建-仅声明性管道支持。 (假设您在管道中有10个阶段,而第7阶段由于一些愚蠢的错误而失败,并且您想从第7阶段重新开始构建-在脚本化管道中,您必须从头开始重新运行,而声明性管道可以重新启动记住前6个阶段的结果)。