 Mae'r ddweud yn 50-miniad cyfnod. Mae'n mwyntiwch. Fyddwn i'n meddwl yma, rwy'n meddwl i'r rhaid i'w ddweud y rhaid i'w ddweud yma, mae'n edrych i'w ddweud o Jenkins, ac mae'n meddwl i'w ddweud. Mae'n meddwl i'w ddweud o'r PhD o'r 12 yma. Mae'n meddwl i'w ddweud i'w rhaid i'w ddweud. Mae'n meddwl i'w ddweud i'w ddweud i'w ddweud i'w ddweud i'w ddweud. Mae'r ddweud sydd yn geniwch, yw'r ddweud i'w ddweud i ddweud. Be gwybodaeth a rhaid. Dwi'n meddwl i hynna yn dru, dwi'n meddwl i ddweud o flyn i gyntafol. Dyma'r cwrdd o Jenkins! Jenkins wedi i ddim i gweld, rydw i'n meddwl i'n meddwl i'w ddweud o Jenkins 1.0 i cael y gweld o fynd i dewis gyda'r crampenau x a l. Mynd i fynd i'w ddweud gyda'r crampenau yw'r ddweud. Mae'r gweithredu yng Nghymru, genkins 2 yn ddim yn gwybod, a'r wneud yn fygwyd yn ddigon. Rwy'n ddweud i chi'n gwybod o'n gwneud, ond rwy'n gwybod yn wneud. Ac mae'r ddiwrnod o'r rhan o'r 50-miniwn gyda'i cyfnod o'r gweithredu o'r hynod o'r hyn o'r phoedd a phoblio cyfnod o'r paru Cyfnodau ar gyfer yn ei paru a bryd o'r gweithredu. 50 mini oherwydd, mae'n ymweld. Mae'n rhaid i'w meddwl. Ond, mae hyn erdoedd yn gweithio. Yn cyfnod, ond mwyaf, ond i fath. Ond yw'n gwaith. Rwy'n gweithio genkin. Mae yna'r griffau, rwy'n gweithio'n eu llwyddiad a'u llwyntau. Rwy'n gweithio genkin. Yn ysgolio'r newydd Lavavel, leolwyr, gref, ddwy'n cael ei gael. Mae'r llwydd rydyn ni'n gweithio'r llwyddiad ac mae'n gweithio'r llwyddiad ar y cyd-dweud ychydig, gweld yn y buntwch, ac yn ddwy'n oed yn gweithio'r rap yn ymgylchedd. 50 min, gallwch chi'n gwybod? Felly, ddim yn ymgylchedd. Felly, rydyn ni'n gweithio'n gweithio'n gweithio. Rydyn ni'n gweithio'n gyda'r gyda'r arloesio, felly rydyn ni'n gweithio'n gweithio. Rydyn ni'n ddweud genkinn ac rydyn ni'n ddweud'n gweithio'n gweithio. Rydyn ni'n gweithio'r API fel y maes health tool, ac yn lydw i'n ysgol iawn i eich rhalad, neu yn ddweud, dwi'n ersgylchedd aprian. Genkinn yn ddynnu 8080, a hynny'n gweithio'n chendol allan nid i ddweud. Felly, rydyn ni'n gweithio. Llygu chi'n ddweud genkinn i'r dynnu. Felly, mae dyma sydd wedi'i ddweud, pen styleu. Pwyll meditationg darmer 10-30 sg. depending on how lucky you are. I was unlucky this time. Man, this is not off to a good start, is it? Come on, Distilloshion, don't let me down. There we are. So now we've got this empty box for running Jenkins. Jenkins give you really, really straightforward installation instructions. Literally, copy. And paste. I mean you should always understand what you're doing here. We're trusting the GPG key to say that the package has sank greatly. We're adding the package repo to our list of sources, and then we're going to install Jenkins. App get install Jenkins. Now, this is going to take a little while because Jenkins, and I know this is a dirty word at PHP conferences, but Jenkins is listening Java. I know. It runs on the JVM, it requires Java 8, but it always has done, and it probably always will do. There's nothing we can do to change that. I did have an issue with Jenkins. I came into work one day and Jenkins wouldn't start. They're not the best at semantic versioning. In a patch release, they bumped the requirement from Java 7 to Java 8. So you do have to be a little bit careful sometimes, but for all its faults, it is one of the best things we've got. Jenkins is installed. If I go back to the install, there's Jenkins. Five minutes past four, five minutes, and we have our instance. We created virtual machines, we installed Jenkins. Now, when you install Jenkins, it sets a password so that no one else can get to it before you can. So let's unlock it by logging into the server and taking out that password, and this is where it allows me to create a user and to install plugins. In the interest of time, I'm not going to install all of the suggested ones. I'm just going to install the ones that we need, which are the credentials binding plugin for secret management, the GitHub plugin for automatically scanning an organisation on GitHub, and the pipeline plugin, which is used for defining your Jenkins builds in code. Those are the only three that I need. If I take you out one step, this is downloading them. They're all packaged as joys. They just get downloaded into the directory, and then Jenkins will restore it itself. Credentials binding, fairly quick. GitHub branch source, fairly quick. Pipeline takes forever. That's because pipeline isn't actually a plugin. It's a collection of plugins. That's the wonderful thing about Jenkins, everything is a plugin. They recently launched a new UI for it, but instead of just changing the default, they wrote a plugin. It means that you don't get stuck maintaining and patching things that you don't really need. You just install what you need to get your job done. This should be done in about five to 10 seconds, and then we should be able to log in to Jenkins. That's another two minutes, and we've installed all of the plugins that we need. I'm going to create a user, if I can spell my own name right, seven finish. Start using Jenkins, seven minutes. Jenkins installed, configured, plugins installed. Doing well, but it doesn't actually do anything. So well and good that we can go to Jenkins, but it's not actually doing any work for us. So let's create a new job. I have Michael Testorg registered as an organisation name on GitHub. This is a GitHub organisation, and what this will do is it will configure everything in the background to start scanning that org. Now you can do this without credentials, but you will hit the GitHub rate limit very quickly. So I'm just going to add a set here, and that's just a username and password to authenticate with the GitHub API. Skip over the behaviours for now. You can do cool things like don't build branches that are already raised as a pull request so you don't get duplicate builds. And then we've got this project recognisers section. And what it says to Jenkins file, that's the file in your project that Jenkins will look for to recognise that it can build it. If I save it, Jenkins will go off, it will scan the organisation. It's found this repo called demoelectron, which we can completely ignore because that was something different, but it has a Jenkins file. That's for a separate article that I wrote. And what Jenkins will do is it will actually, it will try and build that project. Ah, GitHub API usage. Let's go back to that job definition. I must have forgotten to choose the... I forgot to choose the credentials. And you see how we've got rate limit is straight away. So I'm just going to kick off a new scan, cancel that one. So it's proposing demoelectron. It found the Jenkins file and it's here. And it tried to build it and it failed. And that's because I don't have node or anything like that on this machine. Let's ignore it for now. We don't need anything in this repo. Instead, we're going to create a new lavavel app. So if we jump back to the terminal, there's nothing in here, honest. We're going to create a new lavavel app and we're just going to call it basic. And I'll just download all of the dependencies. It has one, two unit tests, things like that. That application is now ready. Let's push it up to GitHub because we don't have a repo for it either. So a new repo. When I said we're going to do everything, I meant we're going to do everything. So it's just called basic. And we're just going to commit everything. Okay, commit. And then we're going to push that up. And what's going to happen now is that Jenkins isn't going to do a thing because it's going to detect it. But it doesn't have that special Jenkins file. And if we go back to Jenkins and we scan the organization, we can see that it proposed basic, but the Jenkins file was not found. So that's why it didn't do anything. So let's add a Jenkins file. A Jenkins file is the file that contains all the instructions for how Jenkins should build your project. Everything starts by specifying a node to run on. In previous roles, we had to build on Windows, Mac OS and Linux. So the machines were tagged with what operating system they are. Here master is a special tag that is your master Jenkins server. So we're just going to run on the single node that we created. You don't have to use stages, but it really helps. So a stage is just a collection of actions to run. So I'm just going to do a little demo here. And all we're going to do is make Jenkins say hello world. Doesn't do anything with our project. It just builds the basics. We're going to push that up. And this time, if we scan our organization, it found the Jenkins file. And it disappeared. And if we go into the build, it was successful. And it just says hello world. Now if we make any changes to that Jenkins file and push it up, Jenkins should automatically detect those changes and we run the build. 13 minutes. We have a project. It's building. It's not doing anything useful, but it's being automatically detected. And it's running the instructions that we gave it. So back to the Jenkins file. What's the first thing that we need to do when we're trying to build a project? We need to call on the source code. Now check out SCM is a clever thing that Jenkins has. So you can set specific repositories and branches and things like that. But SCM is a magic variable that automatically contains all of the correct information for multiple branch pipelines. So GitHub has told it what repo, what branch, and SCM contains that. Once we've got that, we probably want to run Composer and then run our unit tests. Now if you've ever configured Jenkins before, you'll notice that this is way, way easier than clicking through all of those screens and finding the right checkboxes. We're PHP developers. We know how to run Composer install. We can tell Jenkins, run a shell command, Composer install. We know how to run PHP unit. We tell Jenkins, run the shell command, vendor bin PHP unit. This is all familiar to us. It's what we do in our day-to-day jobs. So if I save that, push it up, my commit messages for this repo are going to be horrific. But if we go back to basic and give it 10 to 20 seconds, there it is. The job's been picked up. That's a webhook from GitHub to our Jenkins instance. And it failed. That's because PHP isn't installed on the server. Composer, not found. But it did. It cloned our repo and it tried to run Composer. So what we're going to do, is just jump onto the Jenkins server, install all of our dependencies. And earlier I mentioned a new UI that they built as a plugin. That takes a little while to install. So I'm just going to kick that off now in the background so that I can show it to you later on. It's called Blue Ocean. And it's quite nice. This is another one of those meta packages where there's about 20, 30 other packages underneath it. In fact, there you are. All of those pending ones are part of Blue Ocean. We just want Jenkins to restart when the installation is complete and there are no running jobs. It's quite nice. It will detect if there are running jobs and not kill them halfway through. And just like that, PHP is finished installing. So if we go back to our build and try and build it now, hopefully it should get a little bit further. Composer install, package operations, and Jenkins is restarting. Thank you Jenkins. I just told people how great you are. Watch Jenkins is restarting. I also created an app server earlier that we're going to deploy our application to. That will also need PHP on it. So I'm just going to drop in and install all of the dependencies on there as well so that they're ready when we need to run our application. Jenkins is back. Almost couldn't remember my password then. I would have been embarrassing. And the job is running. So this is all the composer install. It's downloading symphony tanks, dragman tank, corona expression, all of the dependencies for our application. This takes a little while the first time. It's having to fetch everything from the archives on GitHub. But in future runs, that will all be cached. So that will be basically instant. And things failed. It actually ran the tests, but there was an error. No application encryption key has been specified. That's a lower value error. That just means that I forgot to copy the .m file across. So if we go back to our Jenkins file, there are a few ways you can handle this. You could fetch the .m file for your Jenkins instance from S3. You could commit it to the repo. You could do all kinds of things. In the interest of speed, I'm just going to add a stage that copies it and generates a new key as part of the build because we don't rely on the encryption key in any of our tests. And that needs to go before the tests. When I commit this and push it up, once again, Jenkins will receive that webhook from GitHub and start the build. And hopefully this time you should see how much faster it actually is. So build number four. Composer done test pass. I think we just had a green build. We just had a green build. Yeah, loving the enthusiasm. 18 minutes. 18 minutes from absolutely nothing to having a brand new project building on Jenkins. Not bad, eh? I mean, we can keep going because this is all things that we could do on a local machine. What if we want to start doing things like code coverage? So we've got our exunit reports. We could put those in. We could use clover. Now, this one looks a little bit scary. For PHP unit to run coverage, I just need to change the line to actually output the coverage reports. And I'm going to commit this up and then talk you through it. So I added a couple of things there very quickly. One is that we output our junit log files and our clover coverage report into a folder called reports. junit is a Jenkins plug-in that was pulled in earlier as a dependency. And we're saying, I want a junit report, lookin reports slash exunit, and then we've got this mashed roster. And this is what happens when plug-in authors don't update their plug-ins to take advantage of the Jenkins file. It doesn't mean that you can't use their plug-ins. It just means that you've got to call the jover classes directly and pass in all of the CREP parameters. It's not nice, but it's better than not being able to use a plug-in just because they haven't updated to the latest standards. Here we're saying call the clover publisher class, look in reports. It's called coverage. We're aiming for 10% coverage for healthy, 5% from healthy zero for failing. I have low standards. And this time, it's failed again. Let's take a look. The nice thing about Jenkins is it shows you all of the commands that it's running. No implementation of interface clover publisher. That's because I haven't installed the clover plug-in. So back to the drawing board we go. Manage Jenkins, plug-ins. Remember when I said everything was a plug-in? So clover, not clover PHP. Clover PHP was written a long time ago and then abandoned. Clover is a standard. It doesn't matter whether you're working in Java, PHP, Python. If your application will output clover files, this plug-in will work. I'm just going to restart Jenkins so that that gets picked up. I'm just going to take a few seconds and then we'll run the build again. You start to see all of these additional things that Jenkins can do. Like how many of you run code coverage and then look at clover reports on your local machine? Yeah, a couple. I'll take my hat off to you. That's pretty good. But people don't in general. People just run the test and say, yep, it looks green. Ship it. Jenkins can do things like code coverage percentages, health of the code. So basic build. Master. Build now. And this time it should fly through because we've got all of our composite dependencies cached, things like that. You see these things at the top? You know I said you don't have to use stages, but they're really useful. This is why. It tells you how long you spend in each stage so you can find out why your pipelines are taking longer than intended. 50.7% method coverage as according to clover. You can see the test results. We'll look at the unit test, example test, test basic. This is all the X unit input. So now Jenkins is actually starting to add more than just running unit tests on your local machine. This is good, but this is all contained in one Jenkins file and this is one Lavavel project. What happens when I've got a second Lavavel project or a third, or a fourth, or a hundredth? If you want to change a single thing, you'd have to go through all of those projects and update your Jenkins file, right? Thankfully Jenkins has you covered there as well. So it has a concept of a global library and that's just a set of reusable steps that you can call from your Jenkins file. And if you update the step in your global library, it gets updated in every pipeline that depends on it. So we're going to take this and we're going to turn it in to a global library. Now, Jenkins runs on the JVM. All the Jenkins file that you saw and the global library are actually written in a language called Groovy, which is interesting, but it's functional. Because it runs on the JVM, sorry, I'm going to create a folder called Jenkins Pipeline to hold this. Because it runs on the JVM, you've got to respect the JVM naming standards and that is not right. So it's source.com.michaelheap because my domain is michaelheap.com. What we need to do next is define the Laravel project because I don't want to build up the individual steps for every Laravel project. I just want to say this is written in Laravel to read them all the same way. And there's a lot of stuff in here. We've got this run method which tries to execute a step passing in any options. And if there are any exceptions, it fails the build. We've got a couple of things defined. So for every Laravel project, if we want to check out the source code, then we want to run composer install. We did more than that, but I'll just show you implementing those two first. So if I try and write checkout.groovy, every step looks something like this. It's just a single execute method and it's just what we had before. So that stays check out, check out SCM. It's exactly the same as what we would have put in the Jenkins file. Except now, it's in a global library that we can reference. Let's do the same for composer install. The documentation on this isn't particularly great. I banged my head against the desk for about a week trying to get this working, but this will all be on GitHub for you to take a look at later on. So check out and composer install. Let's push that up to GitHub and everything. There's no repo for it. So off we go to GitHub again. Create a new repo. I'm going to call this one Jenkins Pipeline. Jenkins Pipeline. I'm going to push this up. And now this is available on GitHub to be pulled in, but we haven't actually told Jenkins what to do. We haven't told it where this global pipeline lives. So if we go back to Jenkins, we're going to manage Jenkins, configure system, thinking, and then scroll down to global pipeline libraries. We can add a new one. Its name in a really small box is Jenkins Pipeline. The default version we're just going to grab from master. We want to load it from modern source control using GitHub. We're going to use the credentials that I provided earlier. The owner is Michael Testorg. So you don't actually have to depend on the pipeline library that your organization owns. You can get it from anywhere. And the repository is Jenkins Pipeline. Now any job that builds will have that pipeline available. If we go back to Jenkins file, we've got all of the steps in there. I'm just going to delete those. We don't need them anywhere. We've got a global library. And I've forgotten what it is. So now we still have to run it on the master node. But we just say that this pipeline is a new Michael Heap lower valve project. And we execute it and we tell it what the application's name is. And it's just called Michael Test in this case. Push that up. And I really hope this works. Basic. So seven minutes since our last success were 29 minutes into the talk. We've installed Jenkins. We've created a project. We've built it. We've extracted those steps into a global library. And now we're trying to build it again. And this time it failed. What did I do wrong? I think I missed an option when I was configuring it. So by default, I don't think Jenkins will pull in global libraries. You've got to say this is loaded implicitly. Yep, there it is. I missed a check box. So in your Jenkins file, you can say, grab this global library or grab that local library. I just want it to be pulled in all of the time. So let's check that box. Try again. And this time, we can see that it was pulled in just here, fetching upstream changes from Jenkins pipeline. And it ran. It cloned our codes and it ran Composer install. That's exactly what we told it to do. Now, this lot of helpful projects, it's only got two things. When really, we want lots of things. So we've put in everything that we did before. We check out, we Composer install. I didn't actually create a reusable stage for create the environment keys. And that's because it's very specific to a lot of health projects. So why not just keep it in that pipeline definition? Then we run PHP unit. We run ex unit. We run coverage and this time I'm passing in parameters for what I consider healthy, unhealthy and failing. My standards have gone up. I expect 80% for it to be healthy now. And then we do something different. We say, if we're on master, and only if we're on master, first of all, check that I can actually proceed. And if I can, build a dev file and deploy it. Now, we've got most of these steps up until this point. But they're not in our global library yet. So if we go into source like a heap, we've just got those three. Fortunatly, here's one that I made earlier. And now we've got all of those steps, all implemented under all what we expect. If I show you ex unit, it's just what we saw in our Jenkins file. The ones that you might be interested in are confirm, build and deploy. So we've not seen these steps before. Jenkins will let you prompt the user to say, do you want to deploy this build? In fact, it will let you prompt to say anything. And you just say, yes, I know. Depending on the interface, it will say, yes, I know. Proceed or abort. If we get past this, we try and build a dev file with a tool called FPM. We don't actually have FPM installed on our Jenkins server yet. So I'm just going to go ahead and install that in the background. That will create a Debian package that we can deploy. And then finally, we're going to run an Ansible Playbook. It reads the secure credentials to get the SSH key to use. That means that even if you wipe the machine, so long as you've got a Jenkins backup, it can still work. It's not looking for files on disk. It's not looking for special privileged SSH keys. All of the config for your job now lives in your code repos and in Jenkins. All of the credentials, everything. To do this deployment, we're also going to need Ansible, which some of you might have seen in Taylor's talk just before. It's a relatively simple playbook, but let's just install that in the background whilst we're waiting. So these three new steps, push that up. And because I added that to the Laravel project definition, our actual application doesn't change because our application is still a Laravel project. It's just so happened that the definition of that project has changed under the hood. So, if we build, it should get all the way to proceed or abort, or not, if I don't run this time, unable to resolve class PHPUnit. So, it is case sensitive, and the way it works is it uses the file name as the class name. So, PHPUnit.groovy, new PHPUnit. Ah, of course, because I did git commit minus AM. It didn't actually add the new files. On the plus side, you can see that this isn't a video or anything like that. This is actually happening. I always feel like the mistakes make it feel a little bit more authentic. So, that's pushed up to GitHub, unless try rebuilding our project again. And this time, it should go through. Check out build, test, exunit, coverage, and then we should get a new prompt. Do you want to deploy this build, proceed or abort? Yeah, apologies at the back. It is right at the bottom of the screen. I'm going to abort this build for one reason and one reason only, and that's that we don't actually have an Ansible Playbook to deploy it yet. Now, I'm going to show you the app server before we get started. It's just your standard Apache 2 install page. I'm not going to build the Ansible Playbook live on stage. Again, I'm going to take one that I did earlier and just copy it in and just change the IP address that we're deploying to. I just need to grab that here. Then, once again, add that folder, commit and push. We go back to Jenkins. When you're building up your Jenkins file and testing, you will see a lot of red. That's just the way things are with Jenkins. The tooling for testing locally isn't quite there yet, but, really, if you can get it going green every couple of commits, that works really well. Do you want to proceed? This time, I do want to proceed. It failed. I forgot to install FPM. I installed all of its dependencies, but not the actual gem itself. Now, FPM is a Ruby package. If you've never seen it before, it's fantastic. You can build RPMs, DEB files, the rest of the game is zip files. Basically, any package that you want to deploy, FPM can build it. If FPM isn't making packaging easier for you, that's a bug in FPM, that is its mission statement. If any of you have ever had the pleasure of writing RPMs spec files by hand, FPM is a godsend. It's wonderful. For those of you that haven't had the good fortune to write RPMs spec files, don't. You can get the PHP ones by Remicolor. I think that RPMs spec files about 1,700 lines long. It's just a mission to get through it. But FPM takes all that pain away. If you go to michaelheap.com, there's an intro to FPM there. That's how much I love it. Whilst that's installing, I'm just going to show you a blue ocean. A blue ocean was actually designed unlike the rest of Jenkins. By that, I mean it had UI people, people that know what it looks like. It actually looks quite nice. You can click in to a project. You can see everything. You can see the latest commit message. You can click in and you can see each stage. This is where stages come in, so instead of just that wall of text that you see in the normal log, you can see what happened for checkout, what happened for build, create N for keys. We confirm diploys. But it failed when building the dev file because FPM wasn't installed. FPM is now installed, so I'm actually just going to click this button here to kick off the build again. Waiting for the run to start. It gets picked up. And it actually looks quite nice blue ocean. We get this nice big deploy this build button instead of just that little bit on the text. This time it's packaging. Build failed. What failed that time? This time the deploy failed. See, this is where blue ocean falls down. It's very pretty, but it's not entirely functional. I don't know what it is about the original UI. I always find myself using this. Yes, so it's tried to deploy using the SSH key that I haven't put in there yet. But that is the last thing. So we installed the credentials management plugin earlier. So we can go in, we can add a credential. This is a secret file. I'm just going to upload my SSH key. This is my actual SSH key. Demo one. And the idea is important here. So I've called it SSH-key. And the reason I've called it that is because that's what I've used in my pipeline definition. If I kick off the build, I can show you that. So just here, credentials ID, SSH-key. That has to match exactly, otherwise Jenkins won't be able to find it. Yep, I want to deploy this. Come on Jenkins. It builds, it runs Ansible. And this time it's actually running. It's found the dev file that I built. It's deploying it. So it's now on the remote server. It's installing it. It's taking a little while to install. And it's done. And if we go back to this and we refresh, we get a level up.