{"id":91,"date":"2015-08-30T23:06:05","date_gmt":"2015-08-31T03:06:05","guid":{"rendered":"https:\/\/mberlove.com\/blog\/?p=91"},"modified":"2015-08-31T00:46:18","modified_gmt":"2015-08-31T04:46:18","slug":"learning-jenkins-example-projects","status":"publish","type":"post","link":"https:\/\/mberlove.com\/blog\/learning-jenkins-example-projects\/","title":{"rendered":"Learning Jenkins: Example Projects"},"content":{"rendered":"<h2>Learning Jenkins?<\/h2>\n<p><a href=\"https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/Meet+Jenkins\">Jenkins, a free continuous integration tool,<\/a> is fantastic for handling large projects, and its abilities within its domain are practically limitless. But this benefit is a hindrance, too &#8212; getting started can be befuddling!<\/p>\n<p>&nbsp;<\/p>\n<p>The fundamentals of Jenkins are straightforward, but there&#8217;s a significant gap between basics and practical, real-life use. Little material exists to bridge that gap.<\/p>\n<p>&nbsp;<\/p>\n<p>Here, then, are two examples meant for that exact purpose. You can skim them for the general idea or you can follow along line by line.<\/p>\n<p>&nbsp;<\/p>\n<h3><\/h3>\n<h3>Project 1: Version Control &amp; Email Feedback<\/h3>\n<p>This example demonstrates some of Jenkins&#8217; fine controls. It uses the <strong>Email Extension Plugin<\/strong>, which allows customization of Jenkins&#8217; existing email abilities, along with some standard plugins such as the Git plugin.<\/p>\n<p>&nbsp;<\/p>\n<p>We&#8217;ll assume you have Git set up on your machine; if not, here&#8217;s <a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-install-git-on-centos-7\">some info on getting it set up<\/a>. The link is for CentOS 7 as that is what this example uses (if you&#8217;re using a different system, only minor adaptations should be necessary).<\/p>\n<p>&nbsp;<\/p>\n<p>Let&#8217;s set up a Git repository, and associate it with source code already existing in version control. To parallel this exact example, <a href=\"https:\/\/confluence.atlassian.com\/display\/BITBUCKET\/Create+a+repository\">set up a repository on BitBucket<\/a>, a popular source control website (it&#8217;s free).<\/p>\n<p>&nbsp;<\/p>\n<p>On your machine, first install Apache server.<\/p>\n<blockquote>\n<pre>sudo yum -y install httpd\r\nsudo service httpd restart<\/pre>\n<\/blockquote>\n<p>Then, install Git, replacing &lt;name&gt; and &lt;email&gt; with your name and email, respectively. The latter lines of this section simply set information in Git&#8217;s internal system so it knows who is writing what code.<\/p>\n<blockquote>\n<pre>sudo yum -y install git\r\nsudo git config --global user.name \"&lt;name&gt;\"\r\nsudo git config --global user.email \"&lt;email&gt;\"<\/pre>\n<\/blockquote>\n<p>Then, create a directory in the public webserve location and initialize a repository.<\/p>\n<blockquote>\n<pre>cd \/var\/www\/html\r\nsudo mkdir jenkinscontroltest<\/pre>\n<\/blockquote>\n<p>Depending on your user, you may now need to run the following to give yourself control of the location:<\/p>\n<blockquote>\n<pre>sudo chown -R &lt;user&gt; jenkinscontroltest<\/pre>\n<\/blockquote>\n<p>Now, let&#8217;s setup the code repository. Replace &lt;remote code location&gt; with the location of your repository. If you created a BitBucket repo, yours will follow a format of https:\/\/&lt;username&gt;@bitbucket.org\/&lt;repo owner&gt;\/&lt;repo name&gt;.git.<\/p>\n<blockquote>\n<pre>cd jenkinscontroltest\r\ngit init\r\ngit remote add origin &lt;remote code location&gt;\r\necho \"Martin Berlove\" &gt;&gt; contributors.txt\r\ngit add -A\r\ngit commit -am 'Initial commit.'\r\ngit push -u origin master<\/pre>\n<\/blockquote>\n<p>The <strong>echo<\/strong> command writes to a file, in this case contributors.txt. The <strong>git add<\/strong> command says to add all new files to the file tracking system that Git employs, <strong>git commit<\/strong> says you are done writing for now and the files you have edited are ready to be sent to the remote location, the central repo. <strong>Git push<\/strong> is what actually sends the files.<\/p>\n<p>&nbsp;<\/p>\n<p>So now our local code is linked up to the code on BitBucket (or wherever you have chosen to place your remote code).<\/p>\n<p>&nbsp;<\/p>\n<p>Next, create the new project! This follows the same basic steps as before, only this time, on the configuration page, we add a few changes. First, we select Git as our version control, which is available to us due to the plugin we previously installed. Specify your repo URL; in this case, mine is https:\/\/mberlove@bitbucket.org\/mberlove\/jenkinscontroltest.git.<\/p>\n<p>&nbsp;<\/p>\n<p>You will need to add credentials; for BitBucket, this is a simple user\/password pair.<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/kGckHUA.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/kGckHUA.png\" alt=\"Setting up credentials to connect Jenkins to source control.\" width=\"745\" height=\"209\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>We also want to create a build trigger to tell Jenkins when to run &#8212; i.e. not just manually! In the <strong>Build Triggers<\/strong> section we check <strong>Poll SCM<\/strong> (that&#8217;s <a href=\"http:\/\/en.wikipedia.org\/wiki\/Software_Configuration_Management\">software configuration management<\/a>, meaning that Jenkins is going to check on the source control system to see if there are changes according to a schedule we&#8217;re about to specify).<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/agAw3VT.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/agAw3VT.png\" alt=\"Setting up source control polling in Jenkins\" width=\"745\" height=\"248\" \/><\/a><\/p>\n<p>In the <strong>Schedule<\/strong> box, we enter <strong>H\/5 * * * *<\/strong>. This means that Jenkins will poll the system every five minutes (the little question mark next to this box contains useful information on this field). We&#8217;ll add an &#8220;execute shell&#8221; build script to run<\/p>\n<blockquote>\n<pre>git status<\/pre>\n<\/blockquote>\n<p>and then add a single post-build action: <strong>Editable E-mail Notification<\/strong>. If you&#8217;re following along, you can see that the fields here are auto-populated with default representative variables.<\/p>\n<p>&nbsp;<\/p>\n<p>Next, add yourself as a recipient in the project recipient list, replacing the existing variable. Click on <strong>Advanced Settings<\/strong> to reveal a number of new options, including the <strong>Triggers<\/strong> area, where you can control when and why an email gets sent. Add a new trigger and select <strong>Always<\/strong>, indicating Jenkins will send this email any time it runs this job, then save the configuration.<\/p>\n<p>&nbsp;<\/p>\n<p>Now, we can make a change in the code repository to trigger the Jenkins job. We&#8217;ll run the following to make a new file and then add it, commit it, and push it to the repo:<\/p>\n<blockquote>\n<pre>touch file1\r\ngit add -A\r\ngit commit -am \"Added a new file.\"\r\ngit push -u origin master<\/pre>\n<\/blockquote>\n<p>Wait a few minutes for the poll to happen&#8230;and sure enough, the following email is sent:<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/qSwCim9.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/qSwCim9.png\" alt=\"Email from Jenkins with build results\" width=\"745\" height=\"56\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Clicking on the link in the email brings us to the job run information page, which conveniently contains the record of my most recent commit!<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/DMYgkKg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/DMYgkKg.png\" alt=\"Build results in Jenkins, with source control information\" width=\"542\" height=\"268\" \/><\/a><\/p>\n<p>And as always you can go to <strong>Console Output<\/strong> from here to see more details.<\/p>\n<p>&nbsp;<\/p>\n<p>You can also see the broad results of this and other jobs on the dashboard (Jenkins home):<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/dnS7EYb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/dnS7EYb.png\" alt=\"Overview of new project on Jenkins dashboard\" width=\"745\" height=\"35\" \/><\/a><\/p>\n<h3><\/h3>\n<h3><\/h3>\n<h3>Project 2: TODO Comment Monitor<\/h3>\n<p>&nbsp;<\/p>\n<p>This next example has a good deal of grounding in the practical. It monitors specified files for comments marked &#8220;TODO.&#8221; This kind of comment pops up commonly in software projects, and it can indicate incomplete work, so even if a project compiles and functions, you may not want it considered &#8220;complete&#8221;, so you can set Jenkins to watch for this, and change the status of a build based on whether TODO comments are found in a file.<\/p>\n<p>&nbsp;<\/p>\n<p>As previously, start off with a new project. We&#8217;ll link it in to the same BitBucket project as before and give it the same polling schedule. However, this requires a new plugin, <strong>Jenkins Text Finder<\/strong>, which you can install the same way as previously shown. This provides the ability to search through files using regular expressions, and modify the outcome of a build based on the results of the search.<\/p>\n<p>&nbsp;<\/p>\n<p>Now add a new post-build step, selecting the<strong> Jenkins Text Finder<\/strong> option, which exposes a new form. Here you can set what files to search, the pattern for which to search, and what to do if they are found. We&#8217;ll set Jenkins to check just the <strong>file1<\/strong> file in the jenkinscontroltest directory, to look for &#8220;TODO&#8221;, and to set the build to <strong>unstable<\/strong> if this pattern is found.<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/UdGufN4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/UdGufN4.png\" alt=\"Setting up the Jenkins Text Finder\" width=\"745\" height=\"236\" \/><\/a><\/p>\n<p>The location of your file must be specified <em>relative<\/em> to the Jenkins workspace for this job. In the example, it was necessary to ascend several levels in the directory from the user folder where Jenkins was operating.<\/p>\n<p>&nbsp;<\/p>\n<p>When this is configured, save the job configuration, and then make a change to the file and push:<\/p>\n<blockquote>\n<pre>cd \/var\/www\/html\/jenkinscontroltest\/\r\n echo \"TODO something to do\" &gt;&gt; file1\r\n git commit -am \"Added a comment.\"\r\n git push -u origin master<\/pre>\n<\/blockquote>\n<p>A few minutes later, a job build shows up on the project page:<\/p>\n<p><a href=\"http:\/\/i.imgur.com\/5y9Vxxb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"http:\/\/i.imgur.com\/5y9Vxxb.png\" alt=\"Build history in Jenkins indicating unstable build\" width=\"353\" height=\"127\" \/><\/a><\/p>\n<p>The color of the status orb is different this time, and if we hover over the build information, we get a status showing that the build was unstable. Jumping to the console output, we can see that, indeed, the Jenkins plugin found the pattern we specified and changed the status of an otherwise healthy build to be unstable, just like we wanted:<\/p>\n<blockquote class=\"imgur-embed-pub\" lang=\"en\" data-id=\"Mc9jIBU\"><p><a href=\"https:\/\/imgur.com\/Mc9jIBU\">View post on imgur.com<\/a><\/p><\/blockquote>\n<p><script async src=\"\/\/s.imgur.com\/min\/embed.js\" charset=\"utf-8\"><\/script><\/p>\n<p>&nbsp;<\/p>\n<p>Typical projects will often call for more in-depth setups than those demonstrated here, but hopefully these examples will give you some direction to jumpstart your Jenkins journey. Thanks for reading and best of luck!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learning Jenkins? Jenkins, a free continuous integration tool, is fantastic for handling large projects, and its abilities within its domain are practically limitless. But this benefit is a hindrance, too &#8212; getting started can be befuddling! &nbsp; The fundamentals of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[107,109,108],"tags":[116,117,87,67,113,112,110,70,14,114,111,115],"class_list":["post-91","post","type-post","status-publish","format-standard","hentry","category-jenkins","category-learning","category-tools","tag-build-monitoring","tag-centos-7","tag-code","tag-coding","tag-development","tag-integration","tag-jenkins","tag-programming","tag-software","tag-source-control","tag-tool","tag-version-control"],"_links":{"self":[{"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/posts\/91","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/comments?post=91"}],"version-history":[{"count":7,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/posts\/91\/revisions"}],"predecessor-version":[{"id":98,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/posts\/91\/revisions\/98"}],"wp:attachment":[{"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/media?parent=91"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/categories?post=91"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mberlove.com\/blog\/wp-json\/wp\/v2\/tags?post=91"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}