jenkins与持续集成
In the first part of this article I presented the case for Continuous Integration. Now we’ll install and set Jenkins up to monitor the automatic building of a simple demonstration PHP application. We’ll begin with the demo project, then address Jenkins’ installation, and finally set it up and watch it running.
在本文的第一部分中,我介绍了持续集成的案例。 现在,我们将安装并设置Jenkins来监视简单演示PHP应用程序的自动构建。 我们将从演示项目开始,然后处理Jenkins的安装,最后进行设置并观看其运行情况。
The demo project is based on the User class and its test script used by Michelle Sanver in her article Getting Started with PHPUnit. To keep things organized, I created a directory called workspace in my home directory and set it up like this:
该演示项目基于User类及其测试脚本,该类由Michelle Sanver在她的文章PHPUnit入门中使用 。 为了使事情井井有条,我在主目录中创建了一个名为workspace目录,并将其设置如下:
workspace has two subdirectories: .git which is automatically created and used by Git, and builds, the stable version folder.
workspace有两个子目录: .git由Git自动创建和使用,并builds稳定版本文件夹。
The development file is User.php under workspace whereas the stable file has the same name but is in workspace/builds. The goal is to be able to make changes to workspace/User.php, test those changes, and if they pass then copy that file to workspace/builds.
开发文件是在workspace下的User.php ,而稳定文件具有相同的名称,但是在workspace/builds 。 目标是能够对workspace/User.php进行更改,测试这些更改,如果更改通过,则将该文件复制到workspace/builds 。
The following lines create directories workspace and workspace/builds and initializes the Git repository:
以下几行创建目录workspace和workspace/builds并初始化Git存储库:
jajeronymo@desktop:~$ mkdir -p workspace/builds jajeronymo@desktop:~$ cd workspace jajeronymo@desktop:~/workspace$ git init Initialized empty Git repository in /home/jajeronymo/workspace/.git/For convenience, I’ll reproduce Michelle’s classes that are to be respectively saved as workspace/User.php and workspace/UserTest.php here:
为了方便起见,我将在此处重现米歇尔的类,分别将它们保存为workspace/User.php和workspace/UserTest.php :
<?php class User { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function talk() { return "Hello world!"; } } <?php require_once "User.php"; class UserTest extends PHPUnit_Framework_TestCase { public function testTalk() { $user = new User(); $expected = "Hello world!"; $actual = $user->talk(); $this->assertEquals($expected, $actual); } }To start a PHPUnit test:
要开始PHPUnit测试:
jajeronymo@desktop:~/workspace$ phpunit UnitTest UserTest.php PHPUnit 3.6.10 by Sebastian Bergmann. . Time: 0 seconds, Memory: 3.25Mb OK (1 test, 1 assertion)As you know, the dot in the second line of the output means that the User.php passed the test.
如您所知,输出第二行中的点表示User.php通过了测试。
And this line adds User.php to the Git repository:
此行将User.php添加到Git存储库:
jajeronymo@desktop:~/workspace$ git add User.phpAdding a file merely tells Git it exists. To record it as the the latest version we must commit it:
添加文件只是告诉Git它存在。 要将其记录为最新版本,我们必须提交它:
jajeronymo@desktop:~/workspace$ git commit -m "First Version." User.phpSince the initial version of User.php passed the test, it is currently the stable one so we have to copy it to the builds folder. This can be done manually, using either a windowed file manager, or on the command line like this, but really it’d be better if it were done by some automated means, especially for large projects where copying files can be tedious and error prone.
由于User.php的初始版本通过了测试,因此它目前是稳定的版本,因此我们必须将其复制到builds文件夹中。 可以使用窗口式文件管理器手动完成此操作,也可以在这样的命令行中完成操作,但如果通过某些自动化方式完成操作确实会更好,特别是对于大型项目而言,复制文件可能很繁琐且容易出错。
Apache Ant looks for a file called build.xml on the project home folder and runs a series of operations described in XML format, like this example that copies the latest User.php to the builds folder:
Apache Ant在项目主文件夹中寻找一个名为build.xml的文件,并运行以XML格式描述的一系列操作,例如将最新的User.php复制到builds文件夹的示例:
<project name="user"> <copy file="User.php" tofile="builds/User.php"/> </project>Save the above to workspace/build.xml and run:
将以上内容保存到workspace/build.xml并运行:
jajeronymo@desktop:~/workspace$ ant -vAnt should return an output that ends similarly to:
Ant应该返回类似于以下内容的输出:
[copy] Copying 1 file to /home/prospero/workspace/builds [copy] Copying /home/jajeronymo/workspace/User.php to /home/jajeronymo/workspace/builds/User.phpAt this stage, a verified copy of User.php is at the stable version folder ready to be sent to a production server. To further automate the process, we can add the test to the Ant script:
在此阶段,已验证的User.php副本位于稳定版本文件夹中,可随时发送到生产服务器。 为了进一步实现流程自动化,我们可以将测试添加到Ant脚本中:
<project name="user"> <exec executable="phpunit" failonerror="true"> <arg line=" UnitTest UserTest.php" /> </exec> <copy file="User.php" tofile="builds/User.php"/> </project>Save the above again and run Ant:
再次保存以上内容并运行Ant:
jajeronymo@desktop:~/workspace$ ant -vNow we’ve ended up with two simple tasks for our simplified Continuous Integration: committing versions to Git and running Ant to test code which if approved will be copied to the current stable build folder. So, why do we need Jenkins after all?
现在,我们为简化的持续集成完成了两个简单的任务:将版本提交到Git并运行Ant来测试代码,如果批准,这些代码将被复制到当前的稳定构建文件夹中。 那么,为什么我们毕竟需要詹金斯?
To answer that, I’ll use an IDE or text editor to make a small change in User.php, say, add a few extra exclamation marks to “Hello World!”. As soon as I’m through, I’ll commit the new version to Git repository:
为了回答这个问题,我将使用IDE或文本编辑器对User.php进行少量更改,例如,在“ Hello World!”中添加一些额外的感叹号。 完成后,我会将新版本提交到Git存储库:
jajeronymo@desktop:~/workspace$ git commit -m "Added a few bangs." User.php [master d2c96bb] Added a few bangs. 1 files changed, 1 insertions(+), 1 deletions(-) jajeronymo@desktop:~/workspace$ ant -vBut wait a minute! Wasn’t I supposed to test the change before committing the changes? Sure I was! Let’s do that now before someone grabs an untested commit!
但是请稍等! 我不应该在提交更改之前测试更改吗? 当然可以! 在有人抓住未经测试的提交之前,现在就开始做吧!
Since the test expects User.php output string to be exactly “Hello World!”, it will return an error:
由于测试期望User.php输出字符串恰好是“ Hello World!”,因此将返回错误:
[exec] [exec] There was 1 failure: [exec] [exec] 1) UserTest::testTalk [exec] Failed asserting that two strings are equal. [exec] --- Expected [exec] +++ Actual [exec] @@ @@ [exec] -'Hello world!' [exec] +'Hello world!!!' [exec] [exec] /home/prospero/workspace/UserTest.php:15 [exec] /usr/bin/phpunit:46 [exec] [exec] FAILURES! [exec] Tests: 1, Assertions: 1, Failures: 1. BUILD FAILED /home/prospero/workspace/build.xml:4: exec returned: 1Not good… I’d better go back to User.php and removing those extra bangs! Once that’s done, I’ll run Ant again before committing. But that’s when the phone rings, an urgent matter requires my attention, and User.php slips out of my mind. That’s why we need Jenkins! People get distracted; computers don’t.
不好……我最好回到User.php并删除那些多余的刘海! 一旦完成,我将在提交之前再次运行Ant。 但这是电话响起的时候,紧急情况需要我的注意,而User.php不在我的脑海中。 这就是为什么我们需要詹金斯! 人们分心; 电脑没有。
Jenkins main job is not so much automating tasks as it is to monitor them. In fact, automation of builds is not much more than a cron job which any decent OS can handle. Jenkins of course makes it easy to set up such jobs, called “triggers”. But it has several other features related to identifying who is responsible for the changes that are causing test to fail, alerting project managers, showing reports on the possible problems and much more. That’s where its usefulness comes from.
詹金斯的主要工作不是自动化任务,而是监视任务。 实际上,构建自动化只不过是任何体面的OS都能处理的Cron工作。 詹金斯当然可以轻松地建立称为“触发器”的工作。 但是,它还有其他几个功能,这些功能与确定谁负责导致测试失败的更改,警告项目经理,显示可能出现的问题的报告等有关。 这就是它的用处。
Jenkins is available from their website as a Java web application archive file (.war) or as precompiled packages for several popular operating systems. Using the WAR, just put it onto a suitable folder, say ~/jenkins and run:
Jenkins可从其网站上以Java Web应用程序存档文件(.war)或几种流行操作系统的预编译包的形式获得。 使用WAR,只需将其放在合适的文件夹中,例如~/jenkins并运行:
jajeronymo@server:~/jenkins$ java -jar jenkins.warThat starts Winstone, a very light servlet container (a sort of server for Java apps that works with Java more or less the same way a webserver works with HTML and PHP). The terminal lists several actions until ending with:
这开始了Winstone,这是一个非常轻便的servlet容器(一种Java应用程序服务器,与Java差不多,与Web服务器与HTML和PHP相同的方式)一起使用。 终端列出了几个动作,直到以:
INFO: Jenkins is fully up and runningJenkins has a web interface that listens on port 8080. Pointing your browser to http://localhost:8080 you should see a screen like this:
Jenkins具有一个侦听端口8080的Web界面。将浏览器指向http://localhost:8080您应该看到如下屏幕:
To create our demonstration project, click on “New Job”. A form will appear. Enter a name for the job (I’ll enter “Demo”) and select “Build a free-style software project”.
要创建我们的示范项目,请单击“ New Job”。 将出现一个表格。 输入工作的名称(我将输入“ Demo”),然后选择“ Build a free-style software project”。
Then click on OK and a long list of options appear below on the same form.
然后单击“确定”,一长串选项将显示在同一表格的下方。
Look for Build Triggers and check Build periodically. A text box called “Schedule” will show up. Write “*/5 * * * *” in it. This tells Jenkins to run the build procedure every 5 minutes (the syntax used here is the same as used by cron).
查找构建触发器并定期检查构建。 将会出现一个名为“时间表”的文本框。 在其中写上“ * / 5 * * * *”。 这告诉Jenkins每5分钟运行一次构建过程(此处使用的语法与cron相同)。
Go to “Build” and click on “Add build step”. A list of options appear. Select “Invoke Ant” and click on the “Advanced” button that will appear. This button reveals four text boxes. In the second one, “Build file” write the absolute path to the build.xml file used by Ant. In my case, this is /home/jajeronymo/workspace/build.xml.
转到“构建”,然后单击“添加构建步骤”。 出现选项列表。 选择“调用Ant”,然后单击将出现的“高级”按钮。 此按钮显示四个文本框。 在第二个文件中,“构建文件”将Ant所使用的build.xml文件的绝对路径写入。 就我而言,这是/home/jajeronymo/workspace/build.xml 。
Navigate to the end of the options list and click on “Save”. That’s it! From now on, Jenkins will run the Ant script every 5 minutes which by its turn tests any changes to User.php and, if no errors are found, copies it over to the build folder.
导航到选项列表的末尾,然后单击“保存”。 而已! 从现在开始,Jenkins将每5分钟运行一次Ant脚本,然后依次测试对User.php所有更改,如果未发现错误,则将其复制到build文件夹。
From the list of jobs that now appears on Jenkin’s initial page, select our test job. On the left side of the window you can see the build list. (If it is still empty you can click on “Build now” on the menu above it to force the first build).
从现在出现在詹金(Jenkin)初始页面上的作业列表中,选择我们的测试作业。 在窗口的左侧,您可以看到构建列表。 (如果仍然为空,则可以单击其上方菜单上的“立即构建”以强制进行首次构建)。
If you have corrected the problem in User.php, it should pass the test. As soon as the build is over, Jenkins adds a link with its number and time of execution to the list, and beside the link you can see a ball – blue for success and red for failure.
如果您已纠正User.php的问题,则它应通过测试。 一旦构建结束,Jenkins就会在列表中添加一个链接及其执行时间和时间,在链接旁边您会看到一个球–蓝色代表成功,红色代表失败。
Clicking on the link shows a menu where you can elect to see the changes made and the user who requested the build. Clicking on the ball prints Ant’s console output. As time passes, builds accumulate. You can play with User.php, purposefully breaking and fixing and see how it reflects on the builds list and on the console’s output.
单击链接将显示一个菜单,您可以在其中选择查看所做的更改和请求构建的用户。 单击该球会打印Ant的控制台输出。 随着时间的流逝,建筑逐渐积累。 您可以使用User.php ,有意地对其进行破坏和修复,并查看它在构建列表和控制台输出中的反映方式。
As long as it is left running, Jenkins will relentlessly run the test and if no problems are found overwrite the file in build with the newest stable version of User.php.
只要它保持运行状态,Jenkins就会无情地运行测试,如果没有发现问题,请使用最新的稳定版本的User.php覆盖构建中的文件。
As said in the first part, the goal of this article was create an understanding of the operational CI problems Jenkins can solve for a development team. Our example was oversimplified but with this and the other mentioned articles, the interested reader have the tools to create much more sophisticate and useful Ant scripts. On this, please check out http://jenkins-php.org/ where a comprehensive template for multiple tasks related to PHP development can be found.
如第一部分所述,本文的目的是让人们理解Jenkins可以为开发团队解决的操作CI问题。 我们的示例过于简化,但是有了本文以及其他提到的文章,有兴趣的读者可以使用该工具来创建更加复杂和有用的Ant脚本。 关于这一点,请访问http://jenkins-php.org/ ,这里可以找到与PHP开发相关的多个任务的综合模板。
Image via Charles Taylor / Shutterstock
图片来自Charles Taylor / Shutterstock
翻译自: https://www.sitepoint.com/continuous-integration-with-jenkins-2/
jenkins与持续集成