4、持续集成入门:CI/CD概念、Jenkins安装与配置、Jenkins Pipeline基础、第一个CI任务

好,咱们进入第四章。这一章可以说是整个自动更新体系的「发动机」——持续集成。说白了,就是让代码从提交到部署,中间那堆繁琐的编译、测试、打包工作,全部自动化跑起来。你想想看,如果每次更新都要手动登录服务器敲命令,那跟原始人有什么区别?

4.1 CI/CD 到底是什么?

先别急着装 Jenkins,咱们得先搞清楚 CI/CD 到底在解决什么问题。

CI(持续集成),核心就一句话:频繁地把代码合并到主干,并且每次合并都自动验证。我见过太多团队,开发各自写各自的,一两个月才合并一次,结果合并那天就是灾难日——冲突几百个,编译直接挂掉。嗯,这种痛,经历过的人都懂。

CD(持续交付/持续部署),则是在 CI 的基础上,把验证通过的代码自动部署到目标环境。持续交付是「一键部署」,持续部署是「自动部署」。我个人习惯,生产环境用持续交付,留个人工确认的按钮,心里踏实。

核心价值:

  • 尽早发现问题:代码提交后几分钟就知道有没有编译错误、测试失败
  • 减少重复劳动:编译、测试、打包这些脏活累活,交给机器干
  • 保证交付质量:每次构建都是可追溯、可复现的

4.2 Jenkins 安装与配置

Jenkins 是目前最主流的 CI/CD 工具,没有之一。虽然现在 GitLab CI、GitHub Actions 也很火,但 Jenkins 的灵活性和插件生态,在复杂场景下依然无可替代。

4.2.1 安装方式

我推荐用 Docker 安装,干净利落,不污染宿主机环境。当然,如果你非要直接装到系统里,用 apt 或 yum 也行,但升级维护会麻烦一些。

# 拉取 Jenkins LTS 版本(长期支持版,稳定)
docker pull jenkins/jenkins:lts

# 启动容器,映射端口和持久化目录
docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v /data/jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

启动后,访问 http://你的服务器IP:8080。第一次登录需要解锁密码,在容器日志里就能找到:

docker logs jenkins 2>&1 | grep "Initial admin password"

注意:我曾经遇到过 Jenkins 容器重启后数据丢失的情况,就是因为忘了挂载 /var/jenkins_home 目录。记住,Jenkins 的所有配置、任务、构建记录都在这个目录里,一定要持久化!

4.2.2 初始配置

解锁后,Jenkins 会引导你安装插件。新手建议选「安装推荐的插件」,里面包含了 Git、Pipeline、Blue Ocean 等常用插件。如果你对网络环境没信心,可以选「选择插件来安装」,只勾选必要的,减少下载时间。

创建管理员用户时,我建议用强密码,因为 Jenkins 一旦暴露在外网,很容易成为攻击目标。嗯,这个坑我也踩过。

4.3 Jenkins Pipeline 基础

Pipeline 是 Jenkins 的核心能力,它把构建过程用代码的方式描述出来。说白了,就是把「点击按钮」变成「写脚本」,好处是版本可控、可复用、可审计。

4.3.1 两种语法

语法类型 特点 适用场景
Declarative(声明式) 结构清晰,容易上手 大多数场景,推荐新手使用
Scripted(脚本式) 灵活强大,可编程 复杂逻辑、条件分支多的场景

我个人习惯,90% 的场景用声明式就够了。脚本式虽然灵活,但写起来容易失控,维护成本高。

4.3.2 一个最简单的 Pipeline

咱们先写一个 Hello World 级别的 Pipeline,感受一下:

pipeline {
    agent any

    stages {
        stage('拉取代码') {
            steps {
                echo '正在从 Git 仓库拉取代码...'
                // 实际项目中这里会写 git clone 命令
            }
        }
        stage('编译') {
            steps {
                echo '正在编译项目...'
                // 比如 mvn compile 或 npm run build
            }
        }
        stage('测试') {
            steps {
                echo '正在运行单元测试...'
                // 比如 mvn test 或 npm test
            }
        }
        stage('打包') {
            steps {
                echo '正在打包产物...'
                // 比如 mvn package 或 npm run build
            }
        }
    }

    post {
        success {
            echo '恭喜!构建成功!'
        }
        failure {
            echo '构建失败,请检查日志。'
        }
    }
}

你看,整个流程一目了然:拉代码 → 编译 → 测试 → 打包。每个阶段做什么,失败了怎么办,都写得清清楚楚。

小技巧:在 Jenkins 中新建任务时,选择「流水线(Pipeline)」,然后把上面的代码粘贴到「Pipeline 脚本」框中,保存后点击「立即构建」,就能看到效果了。

4.4 第一个 CI 任务

好,理论讲完了,咱们动手做一个真正的 CI 任务。假设你有一个 Java 项目(用 Maven 管理),每次提交代码后,自动编译、跑测试、打包成 JAR 文件。

4.4.1 准备工作

首先,确保 Jenkins 里安装了以下插件:

  • Git Plugin:拉取代码
  • Pipeline Plugin:使用 Pipeline 语法
  • Maven Integration Plugin:调用 Maven 命令

然后,在 Jenkins 系统配置里,设置 JDK 和 Maven 的路径。如果你用 Docker 安装的 Jenkins,容器里可能没有 JDK 和 Maven,需要手动安装或者使用 Jenkins 的「自动安装」功能。

4.4.2 编写 Pipeline 脚本

pipeline {
    agent any

    tools {
        maven 'Maven-3.8.6'  // 这里填你在 Jenkins 里配置的 Maven 名称
        jdk 'JDK-11'         // 这里填 JDK 名称
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main',
                    url: 'https://github.com/你的用户名/你的项目.git'
            }
        }
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                }
            }
        }
        stage('Package') {
            steps {
                sh 'mvn package -DskipTests'
            }
        }
        stage('Archive') {
            steps {
                archiveArtifacts artifacts: 'target/*.jar'
            }
        }
    }

    post {
        failure {
            emailext(
                subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: "请查看构建日志: ${env.BUILD_URL}",
                to: 'team@example.com'
            )
        }
    }
}

关键点解析:

  • tools 块:指定使用的 Maven 和 JDK 版本,确保环境一致
  • junit 命令:收集测试报告,Jenkins 会生成漂亮的测试趋势图
  • archiveArtifacts:把打包好的 JAR 文件保存到 Jenkins 服务器,方便下载
  • emailext:构建失败时自动发邮件通知团队

4.4.3 触发方式

任务建好了,怎么让它自动跑?有两种常用方式:

  • 定时触发:比如每天凌晨跑一次,适合对实时性要求不高的项目
  • Webhook 触发:代码推送到 Git 仓库时,自动触发构建,这才是真正的「持续集成」

配置 Webhook 很简单:在 Jenkins 任务配置里,勾选「GitHub hook trigger for GITScm polling」,然后在 GitHub 仓库的 Settings → Webhooks 里,添加 Jenkins 的地址(格式:http://你的Jenkins地址/github-webhook/)。

我曾经踩过的坑:Webhook 触发后,Jenkins 一直报 403 错误。查了半天,发现是 Jenkins 的 CSRF 保护没关。如果你遇到类似问题,可以在 Jenkins 系统配置里,找到「全局安全配置」,把「防止跨站点请求伪造」暂时关掉测试一下。当然,生产环境建议用 API Token 的方式解决。

4.5 小结

这一章咱们从 CI/CD 的概念讲起,到 Jenkins 的安装配置,再到 Pipeline 的编写,最后亲手跑通了第一个 CI 任务。你想想看,以前每次提交代码都要手动编译、测试、打包,现在只要 push 一下,Jenkins 全自动搞定,是不是爽多了?

下一章,咱们会深入 Pipeline 的高级用法,比如并行构建、环境变量、参数化构建等。嗯,到时候你会发现自己写的 Pipeline 越来越像「真正的程序」了。