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