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

Posted

技术标签:

【中文标题】如何在本地测试对 Jenkinsfile 所做的更改?【英文标题】:How can I test a change made to Jenkinsfile locally? 【发布时间】:2016-07-18 11:17:09 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

据我所知,Pipeline Plugin 是新 Jenkinsfile 机制的“引擎”,所以我非常肯定您可以使用它在本地测试您的脚本。

我不确定当你将它复制到 Jenkinsfile 时是否需要任何额外的步骤,但是语法等应该完全相同。

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

【讨论】:

【参考方案2】:

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

如果您想实时测试对Jenkinsfile 的更改但没有提交,请使用1.14 中添加的the Replay feature

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

【讨论】:

博文说有一个“重播”按钮。知道在哪里吗?我似乎找不到它。 @BoltzmannBrain,转到构建作业的 Jenkins 页面。在左侧,您应该会看到先前构建运行的列表。当您将鼠标悬停在构建运行 ID(例如“#123”)或构建运行日期上时,会出现一个小向下箭头。单击它会显示一个上下文菜单,其中包含“重播”选项。该选项在构建运行的页面上也可用。 Concourse 允许您针对目标构建服务器执行本地脚本,因此您可以在提交更改之前验证它是否实际上也可以在远程服务器上运行。 concourse.ci/fly-cli.html。 Jenkins 重放功能有点类似于此,只是它有一些限制,您必须先创建一个构建才能重放它。 你可以看看this project,它旨在提供你正在寻找的东西。 看看 JenkinsPipelineUnit (github.com/jenkinsci/JenkinsPipelineUnit)【参考方案3】:

TL;DR

Jenkins Pipeline Unit testing framework Jenkinsfile Runner

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

在开发 Jenkins Pipelines 时,您应该遵循三个步骤。 步骤 1. 应涵盖 80% 的用例。

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

示例

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

【讨论】:

您能否还包括这两个库的简要比较?【参考方案4】:

在我的开发设置中——缺少合适的 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

【讨论】:

这正是我一直在寻找的东西——不幸的是它只适用于 declarative 管道而不是脚本管道:(【参考方案5】:

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

    创建一个测试流水线作业,您可以在其中输入流水线代码或指向 Jenkinsfile 的存储库/分支以快速测试某些内容。要进行更准确的测试,请使用指向您自己的 fork 的多分支管道,您可以在其中快速进行更改和提交,而不会影响 prod。 BRANCH_NAME env 之类的东西仅在 Multibranch 中可用。 由于 Jenkinsfile 是 Groovy 代码,只需使用“groovy Jenkinsfile”调用它即可验证基本语法。

【讨论】:

使用可以隐藏且不会混淆用户的单独作业是最重要的事情之一。我用 IntelliJ 编辑 Jenkins 文件。它非常擅长显示语法错误。但是,回复按钮是关键。我创建了一个带有基本更改运行的分支 - 它通常会出错。然后我编辑 Jenkinsfile 并将其复制并粘贴到 Replay 窗口,然后再次运行 - 我重复这个直到它工作正常,然后提交工作版本。【参考方案6】:

在编写 (2017 年 7 月末) 时使用 Blue Ocean 插件,您可以直接在 可视化管道编辑器 中检查声明性管道的语法。当您单击“配置”时,编辑器在 Blue Ocean UI 中工作,仅适用于 github 项目(这是一个已知问题,他们正在努力使其在 git 等上也能工作)。

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

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

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

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

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

【讨论】:

那是因为截至 2017 年,Jenkins 仍然致力于解决点击式软件工程师的问题 ;) .... 至少 Atom 有一个不错的 Groovy linter。只是 Groovy,但它有帮助。 带有语法高亮的编辑器也是经典jenkins UI的一部分。【参考方案7】:

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

这只是在linux环境下测试过。

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

这就是你需要的

Docker installed 和工作。 这不是本说明的一部分。 在 docker 本地运行的 Jenkins。 解释如下。 本地 Jenkins docker 用户从本地 git 存储库中提取的正确权限(ssh 访问密钥)。 解释如下。 从本地 git 存储库中提取的 Jenkins 管道项目。 解释如下。 本地 Jenkins 中具有最低权限的 git 用户。 解释如下。 一个 git 项目,带有一个触发管道项目的提交后 Web 挂钩。 解释如下。

这就是你的做法

詹金斯码头工人

创建一个名为 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 镜像

您只需执行一次或在向 Dockerfile 添加内容之后执行此操作。

$ 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 容器并为其创建一个 bash shell:

$ 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 容器中通过 ssh-ing 到您的计算机来完成循环。

jenkins@e7b23bad10aa:/$ ssh user@172.17.0.1

这一次您不需要输入密码。如果你这样做了,那就是出了点问题,你必须再试一次。

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

不要停在这里,因为我们需要摆脱一系列 ssh shell。

$ exit
jenkins@e7b23bad10aa:/$ exit

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

安装您的 Jenkins

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

当您第一次将浏览器指向本地 Jenkins 时,您会很高兴看到安装向导。 默认值很好,但请确保在设置期间安装管道插件。

设置您的詹金斯

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

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

添加 git 用户

我们需要允许我们的 git hook 以最少的权限登录到我们的本地 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 复选框。将计划留空。 在管道部分: 选择Pipeline script from SCMRepository URL 字段中输入user@172.17.0.1:projects/project/.gitScript Path 字段中输入Jenkinsfile 保存 hookpipeline 项目 手动构建一次 hookpipeline,轮询 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"

使这个文件可执行:

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

测试提交后挂钩:

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

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

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

快乐的日子!

【讨论】:

我不得不将 docker build -t local_jenkins /opt/docker/jenkins/Dockerfile 替换为 docker build -t local_jenkins /opt/docker/jenkins,因为 Docker 抱怨“无法准备上下文:上下文必须是目录”。 我在 Mac 中遇到此错误。有人可以帮我吗? >> 错误:ssh:连接到主机 172.17.0.1 端口 22:连接被拒绝 - @ManojShrestha:ip 172.17.0.1 是运行 docker 容器的机器的默认 ip。您可以改用您的机器 (MAC:s) ip。 @ManojShrestha:您也可以尝试找出您设置的网关 IP,如下所示:$ docker inspect jenkins | grep Gateway 如果您的 docker 主机安装在 macOS 上,并且您希望从 docker 容器中通过 ssh 登录到它,那么您应该ssh user@docker.for.mac.localhost 而不是使用 IP 地址。还要确保您从 macOS 系统偏好设置 -> 共享文件夹菜单中启用了远程登录功能【参考方案8】:

将您的 SSH 密钥放入您的 Jenkins 配置文件,然后使用 declarative linter,如下所示:

ssh jenkins.hostname.here declarative-linter < Jenkinsfile

这将对您的 Jenkinsfile 进行静态分析。在您选择的编辑器中,定义自动运行该命令的键盘快捷键。在我使用的 Visual Studio Code 中,转到 Tasks > Configure Tasks,然后使用以下 JSON 创建 Validate Jenkinsfile 命令:


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

【讨论】:

【参考方案9】:

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

【讨论】:

没有冒犯,但除非你不断更新你的东西,否则它将非常无用,因为管道语法目前似乎处于不断变化的状态。 未拍摄。从我目前所见,流水线语法对于基本流水线步骤(jenkins.io/doc/pipeline/steps/workflow-basic-steps)来说几乎是标准化的。我已经使用它大约 2 年了,没有遇到任何向后不兼容的更改。恕我直言,不应该使用 Jenkins 插件,并且可以使用共享库中的自定义命令来抽象不断变化的 API,在那里您将获得 API 保证。如果您在谈论声​​明性语法,那可能是正确的。我在管道中只使用编程 API,这就是 Jenny 所支持的。坚如磐石:)【参考方案10】:

我正在使用 replay future 进行一些更新并快速运行。

【讨论】:

您能否提供更多关于您如何完成这项工作的信息? 我使用 Bit-bucket 作为源管理器,然后我在 Jenkins 上创建了一个项目希望自动发现我的存储库,我推荐这篇文章。每次推送我的 repo Jenkins 都会自动播放我的 Jenkins 文件,如果它失败,在左侧菜单上有一个名为 Replay 的按钮,==> 这个按钮打开一个包含你的 Jenkins 文件的编辑器,你可以编辑它并重播工作,【参考方案11】:

Jenkins 具有“重播”功能,可让您在不更新源的情况下快速重播作业:

【讨论】:

请注意,它显示在构建页面上,而不是项目或分支页面上。【参考方案12】:

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

    带有内联 groovy 脚本的管道作业:

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


    用于测试的 Jenkinsfile 与 lesfurets 具有相同的结构:

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

execute()

【讨论】:

【参考方案13】:

为简单起见,您可以在 git 存储库的根目录下创建一个 Jenkinsfile,类似于下面基于声明式管道的 groovy 语法的示例“Jenkinsfile”。

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

您现在可以在 Jenkins 中将新项目设置为流水线作业。 选择Definition 作为Pipeline script from SCMGit 作为SCM 选项。 将项目的 git repo 链接粘贴到存储库 URL 中,并将 Jenkinsfile 粘贴到脚本名称框中。 然后单击lightweight checkout 选项并保存项目。 因此,每当您将提交推送到 git 存储库时,您始终可以每次在 Jenkins 中测试运行 Build Now 的更改。

请按照以下视觉效果中的说明轻松设置 Jenkins 流水线的作业。

【讨论】:

【参考方案14】:

您可以验证您的管道以找出语法问题。 Jenkins 为 Jenkisfile validation 提供了很好的 API - https://jenkins_url/pipeline-model-converter/validate

使用 curl 并传递您的 .Jenkinsfile,您将立即获得语法检查

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

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

VS Code Sublime Text

【讨论】:

【参考方案15】:

这是一个简短的解决方案,让我可以非常快速地测试管道代码:

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
    skipDefaultCheckout true 因为我们不需要这个工具 git 仓库中的文件。 defaultValue: params.SCRIPT 将默认设置为最新执行。如果仅由一个用户使用,它可以实现非常快速的短期测试周期。 将给定脚本写入文件,并使用load 加载。

通过此设置,我可以测试 一切 我可以在其他 Jenkinsfile 中执行的操作,包括使用共享库。

【讨论】:

以上是关于如何在本地测试对 Jenkinsfile 所做的更改?的主要内容,如果未能解决你的问题,请参考以下文章

自动重新加载对 React 所做的更改,使用 Electron 的 Express Webpack

如何在本地组策略对象中为特定用户应用软件限制策略?

如何让自己走的更远

在 iPhone 关闭时继续发出本地通知的声音/振动警报,就像在时钟应用程序中所做的那样

如何在 Python 中使用 BeautifulSoup 保存对 HTML 文件所做的更改?

我如何知道对分支所做的最新更改是啥?