跳至主要內容

Jenkins Pipeline插件十大最佳实践

王志宇架构运维DevOpsJenkins大约 5 分钟

Jenkins Pipeline 插件对于 Jenkins 用户来说可以让用户能够改变游戏规则。基于 Groovy 中的领域特定语言(DSL),Pipeline 插件使 Pipelines 可以有脚本来定义,并且提供了非常强大的方法来开发复杂的、多步 DevOps Pipeline 。本文记录了编写 Jenkins Pipeline 的一些的最佳实践和不推荐的代码示例和说明。

1. 要使用真正的 Jenkins Pipeline

不要使用像 Build Pipeline 插件或者 Buildflow 插件这样的旧插件。而是使用真正的 Jenkins Pipiline 插件套装。

这是因为 Pipeline 插件是底层工作自身的一个改变和提升的 Step。与 Freestyle 任务不同,Pipeline 对 Jenkins 主机重新启动具有适应能力,并且有可以替代以前用于构建多步、复杂交付 Pipeline 的许多旧插件的内置功能。

有关入门的更多信息,请访问 https://jenkins.io/solutions/pipeline/

2. 就像写代码一样开发你的 Pipeline

使用这个功能可以让你像做其他软件一样将 Pipeline 描述代码以 Jenkinsfile 方式存储在 SCM 中,然后进行版本测试。

这样做可以将 Pipeline 作为代码看待,强制执行良好的规范,并开辟了一个新的功能领域,如多分支、拉请求检测和组织扫描 GitHub 和 BitBucket。

还应该将流水线脚本称为默认名称:Jenkinsfile ,并且以 #!groovy 脚本开头,以便 IDE ,GitHub 和其他工具将其识别为 Groovy 并启用代码高亮。

3. 要在 Stage 块内进行作业

Pipeline 内的任何非安装作业都应该在某一个 Stage 块内执行。

这是因为 Stage 是 Pipeline 的逻辑分割。 可以将工作分为几个 Stage,可以将 Pipeline 分成清晰的几个步骤。

例如:

stage 'build'

//build

stage 'test'

//test

更好的是:Pipeline Stage View 插件将各个 Stage 看作 Pipeline 的唯一分段。

4. 在节点内执行实际作业

Pipeline 里的实质性作业都应该发生在一个 Node 块内。

因为在默认情况下,Jenkinsfile 脚本本身在 Jenkins 主机上运行,使用一个预期使用很少资源的轻量级执行器。 在任何实质性作业过程中,例如从 Git 服务器克隆代码或编译 Java 应用程序,都应该利用 Jenkins 分布式构建能力, 在代理节点中运行。

例如:

stage 'build'

node{

    checkout scm

    sh 'mvn clean install'

}

5. 做一个并行的 Step

Pipeline 提供了一个很直接的语法,用于将你的 Pipeline 分为并行的 Step。

这是因为并行分配工作将使你的 Pipeline 运行更快,并更快地获得开发人员和团队其他成员的反馈。

例如:

parallel 'shifting':{

    //everything

}, 'left':{

    //I can

}

提示:使用 Parallel Test Executor 插件让 Jenkins 自动确定如何在最佳并行池中运行 xUnit 兼容测试!您可以在 CloudBees 博客上阅读有关并行测试执行的更多信息。

6. 在并行 Step 中的使用 Node

为什么我们要在并行 Step 中获取并使用一个 Node? 这是因为并行化有一个主要的优势是:可以同时进行更多的实质性工作(参见最佳实践4)! 通常,我们应该想在 Pipeline 的并行分支中获取一个 Node 来提高并发构建速度。

例如:

parallel 'integration-tests':{

    node('mvn-3.3'){ ... }

}, 'functional-tests':{

    node('selenium'){ ... }

}

7. 在 Step 的 Timeout 代码块内进行 Input

Pipeline 有一个简单的机制,那就是可以将 Pipeline 中的任何 Step 定时。 作为最佳实践,我们应该总是计划使用 Timeout 块内 使用 Input。

这是为了健康的 Pipeline 的清理。如果在给定的窗口内没有出现批准,则在超时时间中的 Input 将允许被清理(即中止)。

例如:

timeout(time:5, unit:'DAYS') {

    input message:'Approve deployment?', submitter: 'it-  ops'

}

8. 文件暂存优先于存档

在将暂存能力添加到流水线 DSL 之前,存档是在 Pipeline 中的 Node 或 Stage 之间共享文件的最佳方式。 如果只需要在流水线的 Stage 和 Node 之间共享文件,则应该使用暂存/提取而不是存档。

这是因为暂存和提取被设计用于在 Stage 和 Node 之间共享文件,例如应用程序的源代码。另一方面,存档被设计用于长期文件存储(例如,你构建的中间二进制文件)。

例如:

stash excludes: 'target/', name: 'source'

unstash 'source'

9. 不要在 Node 块内使用 Input

虽然可以在节点块中使用一个 Input 语句,但我们绝对不应该这样做。

因为 Input 元素会暂停 Pipeline 执行而去等待批准——无论是自动还是手动。 这些批准自然需要一些时间。 另一方面,当因为 Input 停下来的时候,节点元素会获取并保持锁定工作空间和耗资源的任务,这将是一个昂贵的资源。

因此,要在 Node 之外创建 Input。

例如:

stage 'deployment'

input 'Do you approve deployment?'

node{

    //deploy the things

}

10. 不要使用 Env 全局变量设置环境变量

尽管你可以编辑 Env 全局变量中来定义某些环境设置,但我们应该使用 withEnv 语法。

Env 变量是全局变量,所以我们不鼓励去直接改变它,因为样就改变了全局环境,所以建议使用 withEnv 语法。

例如:

withEnv(["PATH+MAVEN=${tool 'm3'}/bin"]) {

    sh "mvn clean verify"

}

本译文转载自:公众号【JFrog杰蛙DevOPs】

上次编辑于:
贡献者: 程序猿DD