多分支流水线

https://jenkins.io/zh/doc/tutorials/build-a-multibranch-pipeline-project/

多分支流水线项目是 Jenkins 的一种功能,可以为代码仓库中的每个分支自动创建单独的流水线,并根据分支执行相应的构建和部署。

多分支流水线项目的工作流程如下:

  1. 创建多分支流水线项目:在 Jenkins 中创建一个多分支流水线项目,并配置与源代码管理工具(如 Git)的连接。
  2. 自动创建流水线:当有新的分支被推送到源代码仓库时,Jenkins 会自动检测到新的分支,并为每个分支创建一个独立的流水线。
  3. 流水线配置:每个分支都有自己的流水线配置,可以在 Jenkinsfile 中定义不同的构建、测试和部署步骤。
  4. 自动触发构建:当新的提交或分支更新被检测到时,Jenkins 会自动触发相应分支的流水线构建。
  5. 并行构建:多分支流水线项目可以同时执行多个分支的构建,以提高整体构建效率。
  6. 状态和日志记录:Jenkins 会记录每个分支的构建状态、日志和结果,并提供可视化的界面来查看和监控各个分支的构建状态。

通过多分支流水线项目,您可以更好地组织和管理多个分支的构建和部署过程,使每个分支都具有独立的构建流程,并自动触发构建和部署操作。这样可以加快开发和测试过程,并提供更高的可靠性和可扩展性。

插件支持

我们简化一下流程,假如使用develop分支作为开发分支,master分支作为集成测试分支,看一下如何使用多分支流水线来管理。

插件支持

image-20230511134328690

git仓库分支创建

# 创建分支且推到远程
Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (master)
$ git checkout -b dev
Switched to a new branch 'dev'

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$ git branch
* dev
  master

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$ git push origin -u dev
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for dev, visit:
remote:   http://gitlab.yuchaoit.cn/elamin-ops/eladmin-api/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To http://gitlab.yuchaoit.cn/elamin-ops/eladmin-api.git
 * [new branch]      dev -> dev
branch 'dev' set up to track 'origin/dev'.

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$

image-20230511134648236

创建多分支job

先禁用旧的pipeline

在 Jenkins 中创建多分支流水线项目的步骤如下:

  1. 登录到 Jenkins 管理界面。
  2. 点击 "New Item" 或 "创建新任务" 创建一个新的 Jenkins 项目。
  3. 在 "Item Name" 或 "项目名称" 输入框中给项目起一个名称,并选择 "Multibranch Pipeline" 或 "多分支流水线" 作为项目类型。
  4. 点击 "OK" 或 "确定" 继续创建项目。
  5. 在项目配置页面中,找到 "Branch Sources" 或 "分支源" 部分,选择 "Git" 或其他适用的版本控制工具。
  6. 在 "Repository URL" 或 "仓库 URL" 输入框中填入代码仓库的 URL。
  7. 增加分支源:点击 "Add Source" 或 "添加源",然后选择 "Git" 或其他适用的版本控制工具。
  8. 在分支源配置中,设置以下参数:
    • "Discover branches" 或 "发现分支":勾选此选项,Jenkins 会自动发现新的分支。
    • "Discover tags" 或 "发现标签":勾选此选项,Jenkins 会自动发现新的标签。
    • "Filter by name" 或 "根据名称过滤":输入一个正则表达式,用于过滤要添加到多分支构建视图中的分支和标签。例如,使用正则表达式 develop|master|v.* 可以匹配以 developmasterv 开头的标签。
    • "Advanced clone behaviors" 或 "高级克隆行为":在此部分可以进行更高级的克隆配置,如设置浅克隆。
  9. 完成分支源配置后,点击 "Save" 或 "保存" 保存项目配置。
  10. Jenkins 将自动检索代码仓库中所有存在 Jenkinsfile 文件的分支和标签,并将符合过滤条件的分支和标签添加到多分支构建视图中。
  11. 默认情况下,添加到视图中的分支和标签将会触发一次构建任务。

通过以上步骤,您可以在 Jenkins 端创建一个多分支流水线项目,并配置相应的分支源和过滤规则,以便自动检索和构建符合条件的分支和标签。

image-20230511134948497

分支源

image-20230511135153967


"Periodically if not otherwise run" 是 Jenkins 中用于配置定期构建任务的选项。

这个选项的含义是,如果没有其他条件触发构建任务,那么定期按照指定的时间间隔运行构建。

具体而言,您可以在 Jenkins 项目的配置中找到这个选项,并设置一个时间间隔。Jenkins 将会在每个时间间隔到达时检查是否有触发构建任务的条件,如果没有其他条件满足,则会自动运行构建。

这个选项非常适用于需要定期执行构建任务的情况,例如每天、每周或每个月都要进行构建。您可以根据自己的需求设置适当的时间间隔,确保构建任务按照期望的频率运行。

需要注意的是,如果项目已经设置了其他触发条件,例如代码提交或定时触发器,那么定期构建将在这些条件触发时被忽略。只有在没有其他触发条件满足时,定期构建才会生效。

因此,"Periodically if not otherwise run" 提供了一种默认的定期构建机制,以便在没有其他条件触发构建时,按照指定的时间间隔运行构建任务。

image-20230511135426957

查看多分支job

扫描分支结果,默认自动会构建,俩分支都会构建,给取消就行。

image-20230511135740400

jenkins会自动发现gitlab仓库里,有几个分支,于超老师设置的是1分钟扫描一次。

image-20230511135833763

生产下的git分之,可能一个仓库有十几个分支,我们这里配置的规则就是

  • jenkins会去扫描每一个分支,哪一个分支里有Jenkinsfile
  • 并且名字是符合正则表达式匹配到的
  • 则自动触发构建任务

Jenkins 在扫描每个分支时,会检查分支中是否存在 Jenkinsfile 文件,并且根据您配置的正则表达式来确定是否匹配。

如果分支满足以下两个条件:

  1. 分支中存在 Jenkinsfile 文件。
  2. Jenkinsfile 文件的名称与您配置的正则表达式匹配。

那么 Jenkins 将会自动触发相应的构建任务。

这种方式非常适用于管理大量分支的情况,Jenkins 可以自动识别和构建符合条件的分支,而无需手动配置每个分支的构建任务。

您只需要在 Jenkins 配置中设置好分支源和正则表达式,Jenkins 将根据这些配置自动扫描和触发构建任务。这样可以减少手动配置的工作量,并确保所有符合条件的分支都能够自动进行构建。

再次美化构建日志

构建日志的详细程度,决定了拍错,以及更好的运维。

这段代码是一个Jenkins Pipeline的脚本,用于定义一系列的构建阶段和后续处理。

以下是脚本的主要部分:

  1. agent { label '10.0.0.81' }: 指定构建运行的代理节点(agent)。在这个例子中,指定了一个具有标签为'10.0.0.81'的代理节点。
  2. environment { ... }: 定义了一些环境变量,供后续阶段使用。其中包括IMAGE_REPO(镜像仓库地址)、DINGTALK_CREDS(DingTalk凭据)、TAB_STR(用于缩进的字符串)等。
  3. stages { ... }: 定义了一系列的构建阶段。每个阶段包含一个或多个步骤(steps)。
    • stage('gitlog'): 这个阶段用于获取最新的Git提交日志,并将结果保存到gitlog.file文件中。
    • stage('checkout'): 这个阶段用于从源代码管理系统(scm)中检出代码,并设置BUILD_TASKS环境变量。
    • stage('mvn package'): 这个阶段用于运行Maven命令进行清理和打包,并更新BUILD_TASKS环境变量。
    • stage('build-image'): 这个阶段用于构建Docker镜像,使用docker build命令,并更新BUILD_TASKS环境变量。
    • stage('push-image'): 这个阶段用于将Docker镜像推送到远程仓库,使用docker push命令,并更新BUILD_TASKS环境变量。
    • stage('deploy'): 这个阶段用于部署应用程序,包括替换部分文件内容和执行kubectl apply命令,并更新BUILD_TASKS环境变量。
  4. post { ... }: 定义了构建后的处理步骤,根据构建结果执行相应的操作。
    • success { ... }: 如果构建成功,则发送一条Markdown格式的消息到指定的DingTalk机器人,包含构建的相关信息。
    • failure { ... }: 如果构建失败,则发送一条Markdown格式的消息到指定的DingTalk机器人,包含构建的相关信息。
    • always { ... }: 无论构建结果如何,始终执行该步骤,并输出一条消息。

这段代码的作用是在Jenkins中定义了一个包含多个阶段的构建流水线,涵盖了代码获取、打包、构建镜像、推送镜像和部署等步骤,并在构建完成后发送构建结果通知到DingTalk机器人。

pipeline {
    agent { label '10.0.0.81'}

    environment {
        IMAGE_REPO = "10.0.0.66:5000/eladmin/eladmin-api"
        DINGTALK_CREDS = credentials('dingtalk')
        TAB_STR = "\n                    \n                    "
    }

    stages {
        stage('gitlog') {
            steps {
                script{
                    sh "git log --oneline -n 1 > gitlog.file"
                    env.GIT_LOG = readFile("gitlog.file").trim()
                }
                sh 'printenv'
            }
        }
        stage('checkout') {
            steps {
                checkout scm
                script{
                    env.BUILD_TASKS = env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('mvn package') {
            steps {
                sh 'mvn clean package'
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }       
        stage('build-image') {
            steps {
                retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('push-image') {
            steps {
                retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('deploy') {
            steps {
                timeout(time: 1, unit: 'MINUTES') {
                    sh "sed -i 's##${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
                    sh "kubectl apply -f manifests/"
                }
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
    }
    post {
        success { 
            echo 'Congratulations!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"eladmin-api",
                            "text": "😄👍 构建成功 👍😄  \n**项目名称**: www.yuchaoit.cn  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}   \n**构建地址**: ${RUN_DISPLAY_URL}  \n**构建任务**: ${BUILD_TASKS}"
                        }
                    }'
            """ 
        }
        failure {
            echo 'Oh no!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"eladmin-api",
                            "text": "😖❌ 构建失败 ❌😖  \n**项目名称**: www.yuchaoit.cn  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**: ${RUN_DISPLAY_URL}  \n**构建任务**: ${BUILD_TASKS}"
                        }
                    }'
            """
        }
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

dev分支推送

git commit -m 'k8s pretty jenkinfile'

git push origin -u dev

image-20230511150148575

项目会为什么会构建

多分支类型的项目,默认没有webhook功能,但是我们配置了1分钟的扫描,所以还是会自动构建。

image-20230511150218639

成功美化构建

image-20230511150323479

钉钉看到报警

image-20230511150339256

并且加入了一个git log版本信息,更清晰对比构建项目的版本

$ git log --oneline  -n 1
29340c7 (HEAD -> dev, origin/dev) k8s pretty jenkinfile 3

通知gitlab构建状态

我们刚才是基于dev分支的构建测试,确认无误后,可以通知给开发,可以合并到master,且更新生产环境。

在一个使用Jenkins进行构建的项目中,可以通过GitLab提供的API将构建状态通知发送到GitLab。这个通知可以作为开发人员发起Merge Request(合并请求)或合并Merge Request的依据之一。

具体来说,当Jenkins进行构建时,它可以获取构建的状态(成功或失败),然后使用GitLab的API将这个状态通知发送到相关的GitLab项目中。这个通知可以被开发人员用作触发他们发起新的Merge Request或合并已有Merge Request的决策依据之一。

通过将构建状态与GitLab中的Merge Request关联起来,开发人员可以更方便地了解构建的结果,并在需要时根据构建状态做出相应的操作。例如,如果构建成功,开发人员可以发起新的Merge Request,将其合并到主分支中。如果构建失败,开发人员可以检查失败的构建日志,并相应地修复问题或修改代码。

总之,通过将构建状态通知发送到GitLab,Jenkins可以与GitLab无缝集成,并为开发人员提供有关构建状态的重要信息,以便他们能够根据构建状态做出适当的决策。

Jenkins端做了构建,可以通过gitlab通过的api将构建状态通知过去,作为开发人员发起Merge Request或者合并Merge Request的依据之一。

注意一定要指定gitLabConnection('gitlab'),不然没法认证到Gitlab端

对比修改了哪些配置就行。

具体groovy脚本

image-20230511154917637

连接gitlab配置

下面是每个选项的解释:

  1. buildDiscarder(logRotator(numToKeepStr: '10')): 这个选项指定了构建日志的处理方式。logRotator是Jenkins中的一个构建日志管理器,numToKeepStr参数设置保留的构建日志数量为10个。这意味着只会保留最新的10个构建日志,旧的构建日志会被自动删除。
  2. disableConcurrentBuilds(): 这个选项禁用了并发构建。当这个选项设置为true时,Jenkins将确保同一个项目在同一时间只能执行一个构建。如果有其他构建正在进行,新的构建请求将被排队等待执行。
  3. timeout(time: 20, unit: 'MINUTES'): 这个选项设置了构建的超时时间。在本例中,构建的最长执行时间被设置为20分钟。如果构建超过了这个时间限制,Jenkins将终止该构建并标记为超时。
  4. gitLabConnection('gitlab'): 这个选项指定了与GitLab的连接名称。在Jenkins的全局配置中,你需要配置一个与GitLab的连接,其名称为'gitlab'。这样,Jenkins就可以使用这个连接来与GitLab进行通信,例如发送构建状态通知等操作。

通过在Pipeline的options部分配置这些选项,你可以自定义构建的行为和设置,以满足你的需求。

更新gitlab状态

updateGitlabCommitStatus是Jenkins Pipeline中的一个步骤,用于更新GitLab上某个提交的状态。

在这个特定的代码行中,updateGitlabCommitStatus步骤被用于更新当前的GitLab提交状态,以表明某个阶段(env.STAGE_NAME)的执行结果为成功(state: 'success')。

通过调用这个步骤,Jenkins可以通过GitLab API将状态更新发送到相应的GitLab提交。这个操作可以帮助开发人员和团队了解到某个特定阶段的执行结果,并在需要时采取相应的行动。

注意,为了能够使用updateGitlabCommitStatus步骤,你需要在Jenkins中配置正确的GitLab连接,并确保提供了适当的认证凭据。

pipeline {
    agent { label '10.0.0.81'}

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

    environment {
        IMAGE_REPO = "10.0.0.66:5000/eladmin/eladmin-api"
        DINGTALK_CREDS = credentials('dingtalk')
        TAB_STR = "\n                    \n                    "
    }

    stages {
        stage('gitlog') {
            steps {
                script{
                    sh "git log --oneline -n 1 > gitlog.file"
                    env.GIT_LOG = readFile("gitlog.file").trim()
                }
                sh 'printenv'
            }
        }
        stage('checkout') {
            steps {
                checkout scm
               updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS = env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('mvn package') {
            steps {
                sh 'mvn clean package'
              updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }       
        stage('build-image') {
            steps {
                retry(2) { sh 'docker build . -t ${IMAGE_REPO}:${GIT_COMMIT}'}
              updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('push-image') {
            steps {
                retry(2) { sh 'docker push ${IMAGE_REPO}:${GIT_COMMIT}'}
              updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
        stage('deploy') {
            steps {
                timeout(time: 1, unit: 'MINUTES') {
                    sh "sed -i 's##${IMAGE_REPO}:${GIT_COMMIT}#g' manifests/*"
                    sh "kubectl apply -f manifests/"
                }
              updateGitlabCommitStatus(name: env.STAGE_NAME, state: 'success')
                script{
                    env.BUILD_TASKS += env.STAGE_NAME + "√..." + env.TAB_STR
                }
            }
        }
    }
    post {
        success { 
            echo 'Congratulations!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"eladmin-api",
                            "text": "😄👍 构建成功 👍😄  \n**项目名称**: www.yuchaoit.cn  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}   \n**构建地址**: ${RUN_DISPLAY_URL}  \n**构建任务**: ${BUILD_TASKS}"
                        }
                    }'
            """ 
        }
        failure {
            echo 'Oh no!'
            sh """
                curl 'https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_CREDS_PSW}' \
                    -H 'Content-Type: application/json' \
                    -d '{
                        "msgtype": "markdown",
                        "markdown": {
                            "title":"eladmin-api",
                            "text": "😖❌ 构建失败 ❌😖  \n**项目名称**: www.yuchaoit.cn  \n**Git log**: ${GIT_LOG}   \n**构建分支**: ${GIT_BRANCH}  \n**构建地址**: ${RUN_DISPLAY_URL}  \n**构建任务**: ${BUILD_TASKS}"
                        }
                    }'
            """
        }
        always { 
            echo 'I will always say Hello again!'
        }
    }
}

提交git

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$ git add .
warning: in the working copy of 'Jenkinsfile', LF will be replaced by CRLF the next time Git touches it

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$ git commit -m 'update gitlab'
[dev 5e7b368] update gitlab
 1 file changed, 13 insertions(+), 1 deletion(-)

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)
$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 20 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 531 bytes | 531.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for dev, visit:
remote:   http://gitlab.yuchaoit.cn/elamin-ops/eladmin-api/-/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To http://gitlab.yuchaoit.cn/elamin-ops/eladmin-api.git
   29340c7..5e7b368  dev -> dev

Sylar@DESKTOP-G6C412R MINGW64 ~/Desktop/eladmin (dev)

查看构建结果

image-20230511160249989

钉钉

image-20230511160418314

查看gitlab通知

image-20230511161440813

查看gitlab 的pipeline

image-20230511161532991

可以更无缝的结合gitlab、和jenkins的构建结果,点击立即跳转到jenkins的构建日志。

此时开发可以去合并代码了(create merge)

image-20230511161821783

既然dev分支的构建没问题了,合并到master。

创建合并请求

image-20230511161955048

查看gitlab合并对应的pipeline

你代码是否可以合并,根据dev分支下的构建结果,确认无误可以合并。

image-20230511162143254

合并分支

image-20230511162633766

dev分支被删除

image-20230511162720452

master分支自动构建

image-20230511162829870


钉钉

image-20230511162901415

Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2024-03-31 19:39:54

results matching ""

    No results matching ""