是否可以获取整个
stage('foo') {...}
定义并将其提取到 Jenkins 内的共享库中?文档非常清楚如何提取单个步骤,但我找不到任何方法来获取整个阶段、对其进行参数化并在全局范围内重新使用它。我认为也许只是 return stage...
可以工作,但它会错误地显示为无效的返回值。
这取决于您是否使用脚本化或声明式管道。
脚本化管道更加灵活,它允许您例如根据某些条件创建阶段(每个管道运行可以有不同数量和类型的阶段)。在这种管道中,您可以将完整阶段提取到共享库类并从
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 阶段重新启动构建 - 在脚本化管道中,您必须从头开始重新运行,而声明式管道可以重新启动从第 7 阶段开始,记住前 6 个阶段的结果)。
要完成 Szymon Stepniak 的回答,我将在此处留下注意,在声明式管道中,您也可以共享整个管道:
// vars/myDeliveryPipeline.groovy
def call(Map pipelineParams) {
pipeline {
agent any
stages {
stage('build') {
...
}
stage ('test') {
...
}
...
}
}
}
然后调用它
@Library(['my-shared-library-name'])_
// (...)
// Jenkinsfile
myDeliveryPipeline(foo: 'FOO', bar: 'BAR')
但请记住,您可能只在 Jenkins 文件中调用一个管道,这使得它不太可定制。
*my-shared-library-name 是 Jenkins 共享库详细信息中配置的库的名称。
来源