跳到主要内容

03 流水线基础:Jenkinsfile 语法

本章学会读写 Jenkinsfile。语法点不少,但常用的就那么一小撮,配着例子过一遍就够用了。

1. 声明式 vs 脚本式​

Jenkinsfile 有两种写法:

  • 声明式(Declarative):pipeline { ... } 开头,结构固定、好读好学,新项目一律用这种
  • 脚本式(Scripted):node { ... } 开头,纯 Groovy 代码,灵活但难维护,见到能看懂就行

本教程只写声明式。

2. 最小骨架​

Jenkinsfile
pipeline {
agent any // 在哪跑:any = 随便找个可用节点

stages { // 流水线主体:一串阶段
stage('构建') { // 一个阶段
steps { // 阶段里的具体步骤
sh 'echo "hello jenkins"' // 执行 shell 命令
}
}
}
}

三层结构记住就行:pipeline → stages → stage → steps。

3. 常用配置块​

3.1 agent:在哪里跑​

agent any // 任意节点

agent { label 'linux' } // 指定打了 linux 标签的节点

agent { // 在 Docker 容器里跑(推荐!)
docker {
image 'node:20-alpine' // 用这个镜像当构建环境
args '-v /root/.npm:/root/.npm' // 挂缓存目录加速
}
}

docker agent 是最值得掌握的:构建环境即镜像。要 Node 20 就用 node:20,要 Go 1.22 就用 golang:1.22,宿主机上什么都不用装,也不会出现「这台机器 Node 版本不对」的问题。

3.2 environment:环境变量​

environment {
DEPLOY_DIR = '/opt/app' // 普通变量
GIT_CRED = credentials('git-cred') // 从凭据取值(自动脱敏)
}

用 credentials() 取出的值在日志里会显示成 ****,不怕泄露。

3.3 options:流水线选项​

options {
timeout(time: 15, unit: 'MINUTES') // 超时强制失败,防止卡死
disableConcurrentBuilds() // 禁止同一任务并行跑
buildDiscarder(logRotator(numToKeepStr: '20')) // 只保留最近 20 次构建记录
timestamps() // 日志带时间戳
}

3.4 triggers:触发器​

triggers {
githubPush() // GitHub Webhook 触发(需装 GitHub 插件)
// pollSCM('H/2 * * * *') // 或者:每 2 分钟轮询一次仓库
}

3.5 when:条件执行​

stage('部署生产') {
when { branch 'master' } // 只有 master 分支才执行这个阶段
steps { sh './deploy.sh' }
}

3.6 post:收尾动作​

post {
success { echo '构建成功' } // 成功时
failure { echo '构建失败,快去看日志' } // 失败时(常用来发通知)
always { cleanWs() } // 无论成败都清理工作目录
}

4. 常用步骤(steps 里能写什么)​

步骤作用
sh '命令'执行 shell 命令,最常用
checkout scm按任务配置拉取代码
echo '文本'打印日志
archiveArtifacts 'dist/**'归档构建产物,可在页面下载
sshagent(['deploy-server']) { ... }块内可用指定 SSH 凭据连服务器
withCredentials([...]) { ... }块内把凭据注入为环境变量

sshagent 是部署的核心,先看个眼熟:

sshagent(['deploy-server']) { // 'deploy-server' 是上一章配的凭据 ID
sh '''
ssh -o StrictHostKeyChecking=no root@1.2.3.4 "mkdir -p /opt/app"
scp dist.tar.gz root@1.2.3.4:/opt/app/
'''
}

-o StrictHostKeyChecking=no 是跳过首次连接的指纹确认——CI 里没人能敲 yes。更严谨的做法是提前把服务器指纹放进 Jenkins 容器的 ~/.ssh/known_hosts。

5. 一个完整例子​

把上面的零件拼成一条真实的流水线(不用逐行背,后面三章都是它的变体):

Jenkinsfile
pipeline {
agent {
docker { image 'node:20-alpine' }
}

options {
timeout(time: 15, unit: 'MINUTES')
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '20'))
}

triggers {
githubPush()
}

environment {
SERVER = 'root@1.2.3.4'
}

stages {
stage('拉取代码') {
steps { checkout scm }
}

stage('安装依赖') {
steps { sh 'npm ci' }
}

stage('构建') {
steps { sh 'npm run build' }
}

stage('部署') {
when { branch 'master' }
steps {
sshagent(['deploy-server']) {
sh 'scp -o StrictHostKeyChecking=no -r dist/* $SERVER:/usr/share/nginx/html/'
}
}
}
}

post {
failure { echo '构建失败!' }
always { cleanWs() }
}
}

6. 在 Jenkins 里创建流水线任务​

  1. 首页 → New Item → 输入任务名 → 选 Pipeline(单分支)或 Multibranch Pipeline(自动为每个分支建流水线)
  2. 配置里找到 Pipeline 部分,选 Pipeline script from SCM
  3. SCM 选 Git,填仓库地址、凭据(git-cred)、分支(如 */master)
  4. Script Path 保持默认 Jenkinsfile(就是仓库根目录那个文件)
  5. 保存,点 Build Now 手动跑一次验证

以后 Jenkinsfile 改动跟着代码 push 走,Jenkins 页面不用再动。

小结​

  • 只写声明式:pipeline → stages → stage → steps 四层结构
  • agent docker 用镜像当构建环境,宿主机零安装、版本永远对
  • 敏感信息走 credentials() / sshagent() / withCredentials(),日志自动脱敏
  • when { branch 'master' } 控制只有主分支才部署
  • post 里做失败通知和 cleanWs() 清理

语法备齐了,开始实战第一战——前端项目:04-部署前端项目