Jenkinsfile流水线构建教程

news/2025/2/27 9:45:57

前言

Jenkins 是目前使用非常广泛的自动化流程的执行工具, 我们目前的一些自动化编译, 自动化测试都允许在 Jenkins 上面. 在 Jenkins 的术语里面, 一些自动化工作联合起来称之为流水线, 比如拉取代码, 编译, 运行自动化测试等.

本文的主要目的是引导你快速熟悉 Jenkinsfile 结构和语义, 让你读完之后可以自己写出一个 Jenkinsfile.

Jenkins 流水线分为脚本式的和声明式的. 脚本式流水线比较灵活, 可以嵌入一些 groovy 语言编程,功能比较强大, 但是对于新手而言上手比较困难, 有一定的学习门槛. 声明式流水线更具结构化, 简单直白, 减少了对 groovy 语言的依赖, 对新用户更友好.

Jenkinsfile__8">Jenkinsfile 是什么

Jenkins 2 中, 流水线配置可以从 Jenkins 中分离出来. Jenkinsfile 允许你将配置文件和执行步骤以代码的形式保存, 这样就可以做到像管理 源代码一样管理 Jenkins 任务, 支持历史追溯, 差异对比等.

Jenkins2 推荐使用名为 'Jenkinsfile’的文件保存任务配置和流水线信息, 不同的项目和分支都有自己 的 Jenkinsfile, 其内容各不相同.

Jenkinsfile__14">Jenkinsfile 基本功能

让我们先从一个简单的 Jenkinsfile 开始, 逐步了解 Jenkinsfile 的功能和用法.

Jenkinsfile_Hello_world_18">Jenkinsfile Hello world

pipeline {
    agent any

    stages {
        stage('Source') {
            steps {
                echo 'hello world'
            }
        }
    }
}
  • 第 1 行声明这是一个流水线.
  • 第 2 行指定了执行该流水线的 agent, agent 可以理解为一个执行环境, 可以是 docker, k8s, 也可以是当前机器环境
  • 第 4 行指定了执行该流水线所需要的步骤, stages 里面可以保护多个 stage
  • 第 5 行指定了一个名字叫做'Source'stage
  • 第 6 行指定了该 stage 内需要执行的 steps
  • 第 7 行调用 echo 内置函数打印了一句'hello world'

执行 shell 脚本

在 steps 块中使用sh来执行. 多行命令可以用"""(三个双引号) 或者 "'(三个单引号). 区别在于双引号里面引用 的变量会被计算展开. 例如:

steps {
    // 单行shell命令
    sh 'echo "Hello world"'

    // 多行shell命令, 以连续的三个'或者"包围
    sh '''#!/bin/bash
    # multi line shell script
    cd project
    mkdir build && cd build
    cmake .. && cmake --build .
    '''
}

指定工作目录

dir指令的功能是设定命令执行时的工作目录, 如果该目录不存在则创建它.

steps {
    dir('project/build') {
        sh "echo `pwd`"
    }
}

拉取 GitHub/Bitbucket 代码

声明式流水线的 git 检出代码非常简单直白. 如下:

steps {
    dir('code_repo') {
        git credentialsId: "${BITBUCKET_CREDENTIALS_ID}",
            url: 'ssh://git@git.company.com/code_repo.git',
            branch: 'master'
    }
}

需要说明几点:

  1. git指令会检出到当前的目录. 如果你需要检出到子目录则需要使用dir指令.
  2. credentialsId这块引用了一个环境变量, 该变量保存着仓库服务器的 credential. 定义环境变量的方法见后.
  3. branch 指定使用该仓库的哪个分支, 如果是 master 那可以省略.

定义环境变量

环境变量在 pipeline 的environment块中定义.

pipeline {
    agent none

    environment {
        // credentials for other service, you can find it at
        BITBUCKET_CREDENTIALS_ID = 'bitbucket.company.com'
        REGISTRY_CREDENTIALS_ID = 'jenkins-harbor'
    }
}

使用 docker 容器

这里有两种办法.

docker 插件提供的方法

在 agent 中指定 docker 环境. 这种方法适合安装了 docker 的 Jenkins.

stage ('SetupEnv') {
    agent {
        docker {
            alwaysPull true
            image 'hub.company.com/jenkins/ubuntu:24_04'
            registryCredentialsId "${REGISTRY_CREDENTIALS_ID}"
            registryUrl 'https://hub.company.com'
            reuseNode true
        }
    }

    steps {
        // 这里的代码运行在上面的docker container环境
        sh '''#!/bin/bash
            set -xeu
            cd code_repo
            ./setup_env.sh 64
        '''
    }
}

此时 steps 块中的命令都是在 docker 环境中执行的.

Docker Template

本方法适用于在 k8s 集群上面部署的 Jenkins, 并且已经设置了全局的 Docker Template 文件. 如果想使用 自己设定的 yaml 文件, 请参考下一节. label 是指定 k8s 有相应标签属性的 pod, 而container 则是指定选取特定的 docker images.

pipeline {
    agent {
        kubernetes {
            label 'jenkins-streaming'
        }
    }

    stages {
        stage('stage1') {
            steps{
                container('ubuntu'){
                    sh 'lsb_release -a'
                }
            }
        }
    }
}

指定自己的 k8s yaml 文件

本方法适用于 k8s 环境下部署的 Jenkins. 特点在于可以由使用者配置 Docker Template.

pipeline {
    agent {
        kubernetes {
            yaml libraryResource('co/company/project_pod.yaml')
        }
    }

    stages {
        stage('show') {
            steps{
                container('ubuntu'){
                    sh 'lsb_release -a'
                }
            }
        }
    }
}

yaml 文件如果在本地仓库, 则可以使用

yamlFile 'path/to/local/pod/file.yaml'

指定 agent

一个 pipeline 可以指定一个或者多个agent. 指定一个全局通用 agent 的方法是在 pipeline 开始的地方指定.

pipeline {
    agent any
}

pipeline {
    agent {
        docker {
            // docker images settings
        }
    }
}

pipeline {
    agent {
        kubernetes {
            // k8s settings
        }
    }
}

如果需要在不同的 stage 使用不同的 agent, 则在开始处指定为none, 然后在各个 stage 分别指定.

pipeline {
    agent none

    stages {
        stage('Source') {
            agent any
        }

        stage('Compile') {
            agent {
                image: 'hub.company.com/jenkins/ubuntu:2404'
            }
        }
    }
}

Artifactory 上传下载

中间产物文件需要上传到 Artifactory 的, 可以参考下面步骤:

stage ('Upload Files to Artifactory') {
    steps {
        rtUpload (
            serverId: "${ARTIFACTORY_SERVER_ID}",

            spec: """
            {
                "files": [
                    {
                        "pattern": "/build/library.a",
                        "target": "your_repo",
                        "props": "gcc_version=4.8;branch=your_branch_name"
                    },
                    {
                        "pattern": "/build/executable.a",
                        "target": "your_repo",
                        "props": "gcc_version=4.8;branch=your_branch_name"
                    }
                ]
            }
            """
        )
    }
}

关于 spec 的详细信息可以参考: Upload

SonarQube 集成

SonarQube 提供了代码审计, 漏洞检查的功能. 目前可以集成 clang-tidy, cppcheck 静态检查结果, 以及 gcov 的覆盖率分析结果.
同时能提供新增代码的质量检查, 确保新 merge 的代码符合质量要求.

stage('Analysis') {
    steps {
        withSonarQubeEnv('SonarQubeServerID') {
            container("sonar-scanner-image") {
                sh '''#!/bin/bash
                set -eu
                cd your/project
                sonar-scanner -X \
                    -Dsonar.projectKey=ProjectName
                '''
            }

        }
    }
}

一般而言, 我们会在执行 sonar-scanner 的目录里面存放一个名为sonar-project.properties
的文件, 用以指定更多的 sonar 配置. 示例的配置如下:

sonar.projectVersion=3.0.0
sonar.language=c++
# 指定源文件目录
sonar.sources=.
sonar.sourceEncoding=UTF-8
# 指定排除的文件/目录
sonar.exclusions=\
    build/** \
    doc/** \
    script/** \
    libs/** \
    test/**
# 指定排除覆盖率的文件
sonar.coverage.exclusions=**/*_test.cpp
# cppcheck 报告文件
sonar.cxx.cppcheck.reportPath=./cppcheck_report.xml
# clang tidy报告文件
sonar.cxx.clangtidy.reportPath=./clang-tidy-report.txt
sonar.cxx.coverage.reportPath=./bullseye_report.xml

总结

在这篇文章中, 我们深入探讨了 Jenkinsfile 的基础与高级用法, 从最简单的"Hello World"示例到复杂的 Docker 容器集成, Kubernetes 部署, Artifactory 上传下载以及 SonarQube 代码质量检查. 通过这些内容的学习, 可以帮你掌握如何创建一个基本的流水线, 并且了解了如何扩展这个基础以适应更复杂的需求.

参考资料

Jenkins 2: Up and Running


http://www.niftyadmin.cn/n/5869903.html

相关文章

C++ Primer 初识泛型算法

欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…

《OpenCV》——光流估计

什么是光流估计? 光流估计的前提? 基本假设 亮度恒定假设:目标像素点的亮度在相邻帧之间保持不变。这是光流计算的基础假设,基于此可以建立数学方程来求解光流。时间连续或运动平滑假设:相邻帧之间的时间间隔足够小&a…

2025面试Go真题第一场

前几天参加了一场面试,GoLang 后端工程师,他们直接给了我 10 道题,我留了一个截图。 在看答案之前,你可以先简单做一下,下面我会对每个题目做一个说明。 文章目录 1、golang map 是否并发安全?2、协程泄漏的原因可能是…

Linux 文字转语音包 eSpeak 的使用方法详解

一、安装 eSpeak 1. 更新软件包列表 在终端中运行以下命令,确保系统中的软件包列表是最新的: sudo apt-get update2. 安装 eSpeak 运行以下命令安装 eSpeak: sudo apt-get install espeak3. 验证安装 安装完成后,可以通过以…

Neo4j使用neo4j-admin导入csv数据方法

在neo4j desktop里创建project,创建dbms,创建database。 将csv文件放入如下import路径中,然后就可以使用相对路径来使用csv了。 在neo4j desktop中打开Terminal 键入导入数据语句: neo4j-admin database import full --nodes&qu…

对 flask 框架中的全局变量 request 探究

在 Python 的 Web 开发框架 flask 中有这样的四个全局变量,我们经常会使用它们来存取数据,在处理请求过程中它们是非常方便的,因为它们的实现方法是相同的,所以这里我们重点探究一下 request 的使用,其它的都是类似的。…

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷(四)

2024-2025 学年广东省职业院校技能大赛 “信息安全管理与评估”赛项 技能测试试卷(四) 第一部分:网络平台搭建与设备安全防护任务书第二部分:网络安全事件响应、数字取证调查、应用程序安全任务书任务 1:应急响应&…

【Uniapp-Vue3】点击将内容复制到剪切板

具体使用方法在官网: uni-app官网https://uniapp.dcloud.net.cn/api/system/clipboard.html大致使用方法如下: // value是需要复制的值 function copyValue (value) { uni.setClipboardData({data: value,success: res>{// 复制成功逻辑},fail:err&…