如何在本地测试对 Jenkinsfile 所做的更改?

How can I test a change made to Jenkinsfile locally?

在编写 jenkins 管道时,提交每个新更改以查看它是否有效似乎非常不方便。

有没有办法在不提交代码的情况下在本地执行这些?

据我所知,Pipeline Plugin 是新 Jenkinsfile 机制的 "Engine",所以我非常肯定您可以使用它来本地测试您的脚本。

我不确定将其复制到 Jenkinsfile 时是否需要任何其他步骤,但是语法等应该完全相同。

编辑: 在 "engine" 上找到参考,检查 this 功能描述,最后一段,第一个条目。

您不能在本地执行管道脚本,因为它的全部目的是为 Jenkins 编写脚本。 (这就是为什么最好让你的 Jenkinsfile 简短并且仅限于实际处理 Jenkins 功能的代码的原因之一;你的实际构建逻辑应该由外部进程或构建工具处理,你可以通过一行调用shbat 步骤。)

如果您想测试对 Jenkinsfile 的更改但没有 提交 ,请使用 1.14

中添加的 the Replay feature

JENKINS-33925 跟踪所需的自动化测试框架。

TL;DR

长版
Jenkins Pipeline 测试变得越来越痛苦。不同于 classic 声明式作业配置方法,在这种方法中,用户仅限于 UI 公开的内容,新的 Jenkins Pipeline 是一种用于构建过程的完整编程语言,您可以在其中混合声明式与您自己的代码分开。作为优秀的开发人员,我们也希望对此类代码进行一些单元测试。

开发 Jenkins 管道时应遵循三个步骤。 步骤 1. 应涵盖 80% 的用例。

  1. 尽可能多地使用构建脚本(例如 Maven、Gradle、Gulp 等)。然后在您的管道脚本中以正确的顺序调用构建任务。构建管道只是编排和执行构建任务,但没有任何需要特殊测试的主要逻辑。
  2. 如果不能完全应用之前的规则,则转到 Pipeline Shared libraries,您可以在其中自行开发和测试自定义逻辑,并将它们集成到管道中。
  3. 如果以上所有方法都无法满足您的要求,您可以尝试最近(2017 年 3 月)出现的其中一个库。 Jenkins Pipeline Unit testing frameworkpipelineUnit(示例)。自 2018 年以来,还有 Jenkinsfile Runner,一个从命令行工具执行 Jenkins 管道的包。

示例

pipelineUnit GitHub 存储库包含一些关于如何使用 Jenkins Pipeline Unit testing framework

的 Spock 示例

在我的开发设置中——缺少合适的 Groovy 编辑器——大量的 Jenkinsfile 问题源于简单的语法错误。要解决此问题,您可以针对您的 Jenkins 实例验证 Jenkinsfile(运行 在 $JENKINS_HTTP_URL):

curl -X POST -H $(curl '$JENKINS_HTTP_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)') -F "jenkinsfile=<Jenkinsfile" $JENKINS_HTTP_URL/pipeline-model-converter/validate

以上命令是从 https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Validating-(or-linting)-a-Declarative-Jenkinsfile-from-the-command-line

除了其他人已经提到的 Replay 功能(同样有用!),我发现以下功能也很有用:

  1. 创建一个测试管道作业,您可以在其中键入管道代码或指向 Jenkins 文件的 repo/branch 以快速测试某些内容。为了更准确的测试,使用指向您自己的分支的多分支管道,您可以在其中快速进行更改和提交而不影响生产。 BRANCH_NAME env 之类的东西仅在 Multibranch 中可用。
  2. 由于 Jenkinsfile 是 Groovy 代码,只需使用 "groovy Jenkinsfile" 调用它即可验证基本语法。

在撰写本文时 (2017 年 7 月末) 使用 Blue Ocean 插件,您可以直接在 视觉管道编辑器。当您单击 "configure" 时,编辑器从蓝海 UI 开始工作,仅适用于 git 中心项目 (这是一个已知问题,他们正在工作使其也适用于 git 等)。

但是,如 this question 中所述,您可以打开编辑器浏览至:

[Jenkins URL]/blue/organizations/jenkins/pipeline-editor/

然后单击页面中间,然后按 Ctrl+S,这将打开一个文本区域,您可以在其中粘贴管道声明脚本。当你点击更新的时候,如果有语法错误,编辑器会让你知道语法错误在哪里。就像这个截图:

如果没有语法错误,文本区域将关闭,页面将显示您的管道。不要担心它不会保存任何东西(如果它是一个 github 项目,它会提交 Jenkinsfile 更改)。

我是 Jenkins 的新手,这很有帮助,如果没有这个,我不得不多次提交 Jenkinsfile,直到它起作用(非常烦人!)。希望这可以帮助。干杯。

我有一个适合我的解决方案。它由 docker 中的本地 jenkins 运行 和 git 网络挂钩组成,用于在每次提交时触发本地 jenkins 中的管道。您不再需要推送到 github 或 bitbucket 存储库来测试管道。

这只在 linux 环境中测试过。

虽然这条指令有点长,但完成这项工作相当简单。大多数步骤都在那里。

这就是你需要的

  • Docker installed 正在工作。 这不是本指令的一部分。
  • Jenkins 运行 在 docker 本地。 解释如下。
    • 本地 Jenkins docker 用户从本地 git 存储库中提取的正确权限(ssh 访问密钥)。 解释如下。
    • 从本地 git 存储库中提取的 Jenkins 管道项目。 解释如下。
    • 本地 Jenkins 中的 git 用户,权限最低。 解释如下。
  • 一个 git 项目,带有触发管道项目的 post-commit 网络挂钩。 解释如下。

这就是你的做法

詹金斯Docker

创建一个名为 Dockerfile 的文件来代替您的选择。我将它放在 /opt/docker/jenkins/Dockerfile 中,用这个填充它:

FROM jenkins/jenkins:lts
USER root
RUN apt-get -y update && apt-get -y upgrade
# Your needed installations goes here
USER jenkins

构建 local_jenkins 图像

您只需执行一次,或者在您向 Docker 文件添加内容后执行此操作。

$ docker build -t local_jenkins /opt/docker/jenkins/

启动和重启local_jenkins

有时您想轻松启动和重新启动 jenkins。例如。重启机器后。为此,我在我的主文件夹中创建了一个别名 .bash_aliases

$ echo "alias localjenkinsrestart='docker stop jenkins;docker rm jenkins;docker run --name jenkins -i -d -p 8787:8080 -p 50000:50000 -v /opt/docker/jenkins/jenkins_home:/var/jenkins_home:rw local_jenkins'" >> ~/.bash_aliases
$ source .bash_aliases  # To make it work

确保 /opt/docker/jenkins/jenkins_home 文件夹存在并且您有用户读写权限。

要启动或重新启动你的詹金斯,只需输入:

$ localjenkinsrestart

您在本地 jenkins 中所做的一切都将存储在文件夹 /opt/docker/jenkins/jenkins_home 中并在重新启动之间保留。

在您的 docker jenkins

中创建一个 ssh 访问密钥

这是实现此功能的一个非常重要的部分。首先我们启动docker容器并为它创建一个bashshell:

$ localjenkinsrestart
$ docker exec -it jenkins /bin/bash

您现在已经进入了 docker 容器,您可以在终端中通过类似 jenkins@e7b23bad10aa:/$ 的内容看到这一点。 @ 之后的哈希肯定会有所不同。

创建密钥

jenkins@e7b23bad10aa:/$ ssh-keygen

在所有问题上按回车键,直到您收到提示

将密钥复制到您的计算机。在 docker 容器中,您的计算机是 172.17.0.1,您是否想知道。

jenkins@e7b23bad10aa:/$ ssh-copy-id user@172.17.0.1

user = 您的用户名,172.17.0.1 是您计算机在 docker 容器中的 IP 地址。

此时您必须输入密码。

现在让我们尝试通过从 docker 容器内连接到您的计算机来完成循环。

jenkins@e7b23bad10aa:/$ ssh user@172.17.0.1

这次你应该不需要输入密码了。如果这样做,则说明出了点问题,您必须重试。

您现在将位于计算机的主文件夹中。试试ls看看

不要在这里停下来,因为我们有一个 ssh shell 链,我们需要退出。

$ exit
jenkins@e7b23bad10aa:/$ exit

对了!现在我们回来了,准备继续。

安装你的 Jenkins

您将在 http://localhost:8787 的浏览器中找到本地 Jenkins。

第一次将浏览器指向本地 Jenkins 时,安装向导会让您大吃一惊。 默认值很好,但请确保在安装过程中安装了管道插件。

设置你的詹金斯

非常重要您在 http://localhost:8787/configureSecurity 上激活基于矩阵的安全性并且 通过将自己添加到 赋予自己所有权利矩阵并勾选所有方框。 (最右边有一个全选图标)

  • Select Jenkins’ own user database 作为安全领域
  • Select Matrix-based security 在授权部分
  • 在字段 User/group to add: 中输入您的用户名,然后单击 [ Add ] 按钮
  • 在上面的 table 中,您的用户名旁边应该会弹出一个人物图标。 如果它被划掉了你输入的用户名不正确。
  • 转到 table 的最右侧,然后单击全选按钮或手动勾选您所在行中的所有框。
  • 请确认复选框 Prevent Cross Site Request Forgery exploits 未选中。 (因为这个 Jenkins 只能从您的计算机访问,所以这没什么大不了的)
  • 单击 [ Save ] 并退出 Jenkins,然后再次登录以确保其正常运行。 如果不是,则必须从头开始并在重新启动前清空 /opt/docker/jenkins/jenkins_home 文件夹

添加 git 用户

我们需要允许我们的 git 挂钩以最小权限登录到我们的本地 Jenkins。仅仅看到和创造就业机会就足够了。因此,我们创建了一个名为 git 的用户,密码为 login

将浏览器指向 http://localhost:8787/securityRealm/addUser 并添加 git 作为用户名和 login 作为密码。 单击 [ Create User ]

为 git 用户添加权限

在浏览器中转到 http://localhost:8787/configureSecurity 页面。将 git 用户添加到矩阵:

  • 在字段 User/group to add: 中写入 git,然后单击 [ Add ]

现在是时候选中 git 用户的最低权限复选框了。只需要这些:

  • 总体:阅读
  • 工作:建设
  • 工作:发现
  • 工作:阅读

确保取消选中 Prevent Cross Site Request Forgery exploits 复选框,然后单击 [ Save ]

创建管道项目

我们假设我们有用户名 user 和我们启用了 git 的项目,其中包含 Jenkinsfile,名为 project,位于 /home/user/projects/project

在您的 http://localhost:8787 Jenkins 中添加一个新的管道项目。我把它命名为hookpipeline以供参考

  • 在 Jenkins 菜单中点击 New Item
  • 为项目命名 hookpipeline
  • 点击管道
  • 点击[ OK ]
  • 勾选“构建触发器”部分中的复选框 Poll SCM。将时间表留空。
  • 在管道部分:
    • selectPipeline script from SCM
    • Repository URL 字段中输入 user@172.17.0.1:projects/project/.git
    • Script Path 字段中输入 Jenkinsfile
  • 保存 hookpipeline 项目
  • 手动构建 hookpipeline 一次,这是 Poll SCM 开始工作所必需的。

创建 git 挂钩

转到 /home/user/projects/project/.git/hooks 文件夹并创建一个名为 post-commit 的文件,其中包含以下内容:

#!/bin/sh
BRANCHNAME=$(git rev-parse --abbrev-ref HEAD)
MASTERBRANCH='master'

curl -XPOST -u git:login http://localhost:8787/job/hookpipeline/build
echo "Build triggered successfully on branch: $BRANCHNAME"

执行此文件table:

$ chmod +x /home/user/projects/project/.git/hooks/post-commit

测试 post-提交挂钩:

$ /home/user/projects/project/.git/hooks/post-commit

如果您的 hookpipeline 项目被触发,请检查 Jenkins。

最后对您的项目进行一些任意更改,添加更改并提交。现在,这将触发本地 Jenkins 中的管道。

快乐的日子!

将您的 SSH 密钥放入您的 Jenkins 配置文件,然后按如下方式使用 declarative linter

ssh jenkins.hostname.here declarative-linter < Jenkinsfile

这将对您的 Jenkinsfile 进行静态分析。在您选择的编辑器中,定义自动运行该命令的键盘快捷方式。在我使用的 Visual Studio 代码中,转到任务 > 配置任务,然后使用以下 JSON 创建一个 Validate Jenkinsfile 命令:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Validate Jenkinsfile",
      "type": "shell",
      "command": "ssh jenkins.hostname declarative-linter < ${file}"
    }
  ]
}

聚会有点晚了,但这就是我写 jenny 的原因,它是一些核心 Jenkinsfile 步骤的小规模重新实现。 (https://github.com/bmustiata/jenny)

我正在使用 replay future 来做一些更新,运行 很快。

Jenkins 有一个 'Replay' 功能,使您能够在不更新源的情况下快速重播作业:

由于一些限制和脚本管道我使用这个解决方案:

  1. 带有内联 groovy 脚本的流水线作业:

node('master') {
    stage('Run!') {
                def script = load('...you job file...')
    }
}

  1. 用于测试的 Jenkins 文件与 lesfurets 具有相同的结构:

def execute() {
 ... main job code here ...
}
execute()

For simplicity, you can create a Jenkinsfile at the root of the git repository, similar to the below example 'Jenkinsfile' based on the groovy syntax of the declarative pipeline.

pipeline {

    agent any

    stages {
        stage('Build the Project') {
            steps {
                git 'https://github.com/jaikrgupta/CarthageAPI-1.0.git'
                echo pwd()
                sh 'ls -alrt'
                sh 'pip install -r requirements.txt'
                sh 'python app.py &'
                echo "Build stage gets finished here"
            }
        }
        stage('Test') {
            steps {
                sh 'chmod 777 ./scripts/test-script.sh'
                sh './scripts/test-script.sh'
                sh 'cat ./test-reports/test_script.log'
                echo "Test stage gets finished here"
            }
        }
}

https://github.com/jaikrgupta/CarthageAPI-1.0.git

You can now set up a new item in Jenkins as a Pipeline job. Select the Definition as Pipeline script from SCM and Git for the SCM option. Paste the project's git repo link in the Repository URL and Jenkinsfile in the script name box. Then click on the lightweight checkout option and save the project. So whenever you pushed a commit to the git repo, you can always test the changes running the Build Now every time in Jenkins.

请按照下图中的说明轻松设置 Jenkins Pipeline 的作业。

您只需验证管道即可找出语法问题。 Jenkins 对 Jenkisfile validation 有很好的 API - https:///jenkins_url/pipeline-model-converter/validate

使用 curl 并传递您的 .Jenkins 文件,您将立即进行语法检查

curl --user username:password -X POST -F "jenkinsfile=<jenkinsfile" https://jenkins_url/pipeline-model-converter/validate

您可以将此工作流添加到编辑器中:

这是一个简短的解决方案,可以让我快速测试流水线代码:

pipeline {
    agent any
    options {
        skipDefaultCheckout true
        timestamps()
    }
    parameters {
        text(name: 'SCRIPT', defaultValue: params.SCRIPT,
            description: 'Groovy script')
    }
    stages {
        stage("main") {
            steps {
                script {
                    writeFile file: 'script.groovy', 
                        text: params.SCRIPT
                    def groovyScript = load 'script.groovy'
                    echo "Return value: " + groovyScript
                }
            } // steps
        } // stage
    } // stages
} // pipeline
  1. skipDefaultCheckout true 因为我们不需要此工具 git 存储库中的文件。
  2. defaultValue: params.SCRIPT 将默认设置为最新执行。如果只有一个用户使用,它允许一个非常快速的短测试周期。
  3. 给定的脚本被写入文件,并加载 load

通过此设置,我可以测试 一切 我可以在我的其他 Jenkinsfiles 中做的事情,包括使用共享库。