在现代最佳实践中,强烈推荐将 Jenkins 脚本写成 Jenkinsfile并保存在项目的根目录下。​ 这被称为 “Pipeline as Code”。

下面我为你详细解释两种方式的区别和推荐理由。

目录

两种方式的对比

详细理由阐述

1. 为什么 Jenkinsfile是绝对的主流和最佳实践?

2. 什么时候可能还需要在 Jenkins 界面上定义?

实践示例:如何工作?

结论



两种方式的对比

特性

在 Jenkins Web 界面上定义(脚本式管道)

Jenkinsfile保存在项目根目录(声明式管道为主)

版本控制​

不支持。脚本保存在 Jenkins master 的文件系统中,容易丢失,难以追踪变更。

支持。Jenkinsfile 和代码一起进行版本控制(如 Git),行查看谁、在何时、为何修改了流水线。

代码复用性​

差。脚本与特定的 Jenkins 任务绑定,难以在其他项目间复用。

强。可能经过共享库(Shared Libraries)将通用步骤抽象出来,供多个项目复用。

协作与审查​

困难。修改流水线需要进入 Jenkins 控制台,无法进行代码评审(Code Review)。

容易。像对待应用程序代码一样,行对 Jenkinsfile 的修改发起合并请求(Pull Request),进行团队评审。

一致性​

差。不同工程的流水线配置可能分散,难以统一管理和维护。

强。可以强制所有工程遵循相同的流水线模板和标准。

故障恢复​

脆弱。如果 Jenkins master 发生故障或需要迁移,这些脚本的备份和恢复比较麻烦。

健壮。Jenkins master 许可高效重建,只需重新指向包含 Jenkinsfile 的代码仓库即可恢复流水线。

调试与开发​

不便。需要在 Web 编辑器中编写和调试,体验较差。

便捷。开发者许可在熟悉的 IDE(如 VS Code, IntelliJ)中编写,享受语法高亮、自动完成等功能。


详细理由阐述

1. 为什么 Jenkinsfile是绝对的主流和最佳实践?

这主要源于“基础设施即代码”和“Pipeline as Code”的理念。其核心思想是:将流水线的定义也视为应用程序代码的一部分。

带来的巨大好处:

  • 单一数据源:应用程序的代码和构建、部署它的流水线定义在同一个地方。当你切换分支或回滚到某个历史版本时,你所启用的流水线定义正是当时构建这个版本所用的那一个,完美避免了因流水线脚本变更导致的构建失败问题。

  • 真正的持续交付:自动化测试和部署流程本身也被自动化、版本化和测试了。任何对流水线的修改都需要经过代码评审和自动化验证,确保了流程本身的可靠性。

  • 赋能制作团队:开发团队无需向运维或 DevOps 工程师申请修改 Jenkins 任务,他们行自主管理和迭代自己方案的构建流程,实现更高效的协作。

2. 什么时候可能还需要在 Jenkins 界面上定义?

虽然 Jenkinsfile是主流,但在 Jenkins Web 界面上定义脚本(通常是通过“脚本式管道”语法)仍有其场景:

  1. 快速原型和测试:当你需要飞快测试一个插件或一个简单的脚本逻辑时,在 Jenkins 的“脚本命令行”或一个临时任务中编写会更快。

  2. 遗留或简单任务:对于一些非常简单的、一次性的或遗留的任务,可能没有必要为其创建 Jenkinsfile。

  3. 共享库开发:在创建和调试共享库(Shared Libraries)时,时常需要在 Jenkins 任务中编写测试脚本来验证库函数。

但请注意,这些通常是例外情况,而不是常规做法。


实践示例:如何工作?

当一个项目使用 Jenkinsfile后,Jenkins 任务的配置会变得非常简单。

  1. 在 Jenkins 上创建一个 “Pipeline” 类型的任务。

  2. 在任务配置中,选择 “Pipeline script from SCM”。

  3. 指定你的代码仓库地址(如 Git)和凭证。

  4. 指定 Jenkinsfile的路径(默认为根目录下的 Jenkinsfile)。

此后,每当有代码推送(或定时触发等),Jenkins 会:

  1. 从仓库拉取代码(包括 Jenkinsfile)。

  2. 读取并执行 Jenkinsfile中定义的整个流水线流程。

结论

对于任何严肃的、需要协作的、希望实现真正 CI/CD 的项目,都应该毫无保留地选择将流水线脚本定义为 Jenkinsfile并保存在项目根目录中。

在 Jenkins Web 界面上定义脚本的方式,只应作为临时性、实验性的用途。将流水线作为代码管理,是提升工程效率、保证流程可靠性和实现 DevOps 文化的关键一步。