 Good morning, everyone. Well, I guess it's morning for me still. But good evening, everybody here. This is a session on continuous integration for web and JavaScript projects. And what we'll do in this session is we'll talk about number of different things that are related to craftsmanship and continuous integration for web and JS projects. So before we get started, I just want to get an idea of a couple of basic things. How many folks are doing continuous integration for web or JS projects already? So the numbers are usually very low in terms of how many folks actually do CI for web and JavaScript projects. And unfortunately, this is a bit of an issue as we'll get into when we talk a bit about craftsmanship because we really do need to have CI, maybe even continuous delivery for web and JavaScript projects. Just to get an idea, how many folks are Java developers or work in a Java shop in here? There's very few people. What other technologies are folks using today? Let's say it starts with C-sharp. How about that? OK, so a fair number of folks C-sharp. How about Ruby or Rails? A couple of folks? Python? So not a lot of hands, but it's OK. First, let's talk about craftsmanship. When we discuss craftsmanship for the server side type of projects, whether it's Java, C-sharp, Ruby, Python, whatever it may be, we typically think of something that is well thought out and well engineered. There's a word that I'll use quite a bit in this session where we talk about software engineering, as opposed to just kind of putting something together or throwing it together. So when we think of something like a Java or C-sharp project, especially on the server side, we go to great effort to ensure that we follow common principles that we apply today for software craftsmanship and specifically for software engineering. Unfortunately, the web world hits more like this than having something that's well done. A lot of times web projects are just hacked together, or especially the kind of CI testing, all those kinds of things are just kind of hacked together, which is unfortunate. We need to be able to apply the same principles that we have that we use for server side projects as for web and JavaScript and other kinds of projects that may not necessarily be as easy to do. And so if you went and you talked to the folks on your engineering team and said, oh, we don't need to do unit testing for a Java project or for a C-sharp project. We don't need to do CI for these kinds of things. What would happen? You would get laughed out of the room. That would never fly because we have to apply certain base engineering principles to produce high quality software. And that's what this session is about. What does software craftsmanship mean? And we'll get into the continuous integration part of this after we've talked about this a little bit. So when we typically think about craftsmanship, there are three basic things. And again, how many folks in here are not software developers, just out of curiosity? So there are a few folks in here. So even for people who aren't software developers, you may be leading an agile team. You may be a scrum master or whatever it may be. You still care about the product that you shift in some way. So for developers and also for people around the project, what we care about is we care about the code quality first and foremost. And obviously we care about the maintainability. So we need to be able to write software in such a way that it is maintainable over time. Because there's one thing for certain in this life. And that is that once you've written some software, there's going to be changes. And there's going to be more changes. Changes, changes, changes down the line for months and for years afterwards. So having the ability to produce a project which has long-term maintainability is a key factor in doing continuous integration for any kind of software project. Basically, being a craftsman as opposed to being a hack. So when we talk about code quality and project quality, there are two things that immediately pop to mind for me. One of them is the low-level code quality that we have. This would be things like unit tests. And then there's mid- and high-level quality types of things which we'll also look at. So things like doing functional testing, doing acceptance testing, user testing, and other things like that. All those things lead into code quality. So along with this, we have the ability to automate these things using continuous integration. That's what we'll get into more detail in a few minutes. So one of the practices that we apply as part of a well engineered project is doing test-driven development and obviously the automation of our TDD tests and the other kinds of tests that we have for our project. So in the Java world or in the C-sharp world, I'm going to use Java as an example here just to give you an idea of the kinds of tools that exist on the other side of the fence. Then we'll look at what specific tools we use in the web world to do the same kinds of things. So in the Java world, we have some basic things that we typically use. For example, we use Clover to get code coverage. We'll use FindBugs to find low-level artifacts that may be problematic in our code base. And then we'll use things like CheckStyle and PMD to ensure that we use the correct type of coding standards so that we have long-term maintainability within our projects. So these are just three of the tools there, more, but these are the three most common or four most common tools that we have in the Java world. And again, if you're not in the Java world, that's fine. These tools exist for pretty much every environment, whether you're doing Python or Ruby or Scala or whatever, maybe all these tools exist to help you do code coverage, help you follow maintainable coding standards, and also to give you things like low-level code quality, complexity metrics, and other things like that. If you have any questions while we're going through this, be happy to answer them. We have plenty of time. We have about 90 minutes in this session. So if you have any questions as we're going through this, please ask it whenever you feel. So again, we have all these great tools on the server side for Java and other types of projects. What about tools for the web and JavaScript world? What do we do in this case? So we have tools like ESLint to JSHint, which allow us to check the low-level code quality standards that give us the ability to make sure that we're writing code in a maintainable way so that long-term we use the same style of coding, and we also resolve certain errors up front before we even get to the runtime. So what ESLint and JSHint do is they check to make sure that you have certain enforceable types of things in your code base. So for example, in the JavaScript project, one of the common things that we have in our ESLint and JSHint rulebook is that you always use a triple equals as opposed to a double equal. And if you're still using ES5 as opposed to ES6, we ensure that you sidestep the hoisting problem in JavaScript by pre-hoisting all of your variables within a scope. If you're using ES6, we would use something like ESLint to enforce the kinds of code styles that we have in there. So one of the things that we would do, for example, with that is we would make sure that instead of using the var keyword to declare a variable, we use let or const instead of var to give us scope safety. So again, these are low-level code quality kinds of things that we use in terms of making sure that we have code that is maintainable and follows certain rules, because JavaScript is different than Java and C-sharp and other languages. We have the ability to write code in any way we want, and the compiler doesn't tell us anything. Why does the compiler in JavaScript not tell us anything when we're writing code? These are trick questions come later. The easy questions are up front. Does anyone know why we don't have a compiler checking in JavaScript? No. What's that? Right, exactly. JavaScript does not have a compilation phase. It is a scripting language. So we have to take more effort to make sure that we check things up front as opposed to the Java world or C-sharp. For example, if you go into some Java source or even to some C-sharp code and you write something that is not syntactically correct, what happens? When you run the compilation, the compiler screams at you and says, oh, you can't do that. It won't even build your code. Whereas in the JavaScript world, you can just write anything you want, and it won't actually blow up until you try to run it. So that's why we have to take extra measures to ensure that we have maintainable code that follows certain rules. So Istanbul is the second bullet on this slide. This is what we typically use in the JavaScript world to do code coverage. So as we're writing unit tests, whether using Jasmine or Mocha or Tape or any of the other frameworks which are available to write tests in JavaScript, Istanbul will run your test and we'll see a demo of this in a few minutes. It will run your test and will allow you to see exactly how much code coverage you have inside of your code base. So of course, I mentioned Jasmine and Mocha and the other test tools already. And we'll talk a little bit more about the difficulty in the JavaScript world in picking these tools as we get into some of the build tools. So if we look at the ecosystem, one of the first things that you have to get familiar with if you wish to use these tools in the JavaScript world is you have to get familiar with Node.js and NPM and the modules that are contained within it. So typically for Java projects, you use something like Maven or you might be using Gradle to put together a build system. In the JavaScript world, we use Node.js and NPM and the tools that it provides, which we'll look at in just a minute to get an idea how to build your projects. So most people are probably familiar with Node.js. It is a JavaScript runtime based on the V8 engine. V8 is a very fast JavaScript engine from Google. If you use Google Chrome, V8 is the JavaScript engine that's in Chrome. So what some clever folks did about six, seven years ago was they took V8 and they made it able to run outside of the web browser so that you can go and just run stuff from the command line. You can run JavaScript from the command line and that's what Node is. And when you install Node, you also get something called NPM or the Node package manager. Node package manager is used to manage dependencies and there's a big repository online where people publish their Node libraries or their Node modules, i.e. their JavaScript libraries and their JavaScript modules. So just to give you an idea of some of the modules that are available in the Node world, there's Express, Grunt and Gulp, which we'll talk about in a little bit in detail in a few minutes. We'll also talk about Webpack, which is a module builder to give you an idea how people build modern JavaScript projects today and bundle them. And Jasmine, which we talked about already, is a JavaScript test runner. There's also Mocha and other things like that. So this is just some of the very few, some of the very commonly used JavaScript modules that you can get via NPM. And one of the common questions with Node and NPM is, well, okay, I'm already building a Angular project or maybe I'm doing a React project or maybe just a simple jQuery project. I don't use Node or NPM to go get those dependencies. I just go grab the jQuery 2.1.0.zip file. I pull that down, I go get the js file that's in the jQuery min.js and then I kind of assemble everything myself, right? Just using the standard zip, the standard distributions. So what's happening in the community today is that folks are moving away from going and grabbing the actual source or these libraries and using a module builder with NPM-based version libraries. So the modern way of building projects today is to have everything in NPM or use NPM libraries even though you can go and directly get jQuery or you can directly get the React libraries and you can kind of hack everything together yourself by importing it into an HTML file. That's not how we do things today in the web community. What we do is we use Node and we use NPM, we use version libraries that we pull from the NPM repository and we'll have a look at how this comes together in a few minutes. So very quickly, if we look at Node.js, it is just a binary that you install using brew just using the installer that is available for Node and it allows you to run stuff from the command line. So we can come into a sample project here and I'm just gonna show something really quickly. And so we have a file in here just called test3js. And if I list that file, you see all it does is it prints out the date. And again, all Node is is just a way of executing JavaScript from the command line. So I can go run this and you can see it prints out today's date. Or what I can do is I can just run any basic JavaScript here. So if I go into my code editor and I open this file, I can find it. So I can come to here. Let's just open this file really quickly. So you can say, instead of doing this, we can say console.log. Make sure I spelled that properly. So you can see I've just written some JavaScript code and now I can go to command line and I can just execute that. You'll see that it just prints out whatever I have. So this is the base starting point. All Node does is it just runs some JavaScript code. Doesn't matter what the code is, it will just go and run it. It's a command line runner for JS code and that's what NPM and the other libraries are based on. So we've already run this example. So we'll move forward. And the way that we typically define a JavaScript project is we have something called a package.json file. So if we look at this file, let me open this project so that we can get an idea of what this looks like. We'd look at a package.json file. You can see that we have some basic things in here. Like what's the name of this project? Version is a private. We also have this scripts thing that we'll look at in a little bit more detail later. And then we can say these are the Node.js dependencies we want to use or the NPM dependencies we want to use in our project. In this specific case, I said I want to use Express which is a basic server-side JavaScript web framework. I want to use Jade as the template engine and I also want to use Lodash which is a very basic utility library for JavaScript. And then we have some dev dependencies which we'll look at in just a minute to give us an idea of the different types of tools that we use to build this project. But before we get to that, again, part of this session is to introduce you to the concept of the way people do modern JavaScript development and how we assemble projects. So we have this specific project here. And you can see I removed Lodash from here. So what we would do to say we wanted to use the Lodash libraries, I would come into this project and I would do NPM install Lodash and then I use the dash-save which will go and add that dependency into this specific project. And hopefully I have internet so that this works. Okay, so it looks like it went installed it with some warnings. And now if we go to the project file, you can see it's installed Lodash. Now, the other thing with the package.json file is when we go and install something like we just did, you can see that it gave it a version number but there's a character here. What this character or what this star means is it tells you which specific revision of that library you wish to use in your project. All right, so you can see for Express what we've done is we've said we want to use version 346. When you specify version number like this, you only use that very specific version and this is how we typically operate. Because we're going to be using a large number of different libraries, we'd like to lock the library version to a very, very specific version so that we don't have any variability in our build process or when we go to deploy. We know exactly what versions of libraries we have and we can safely reproduce any problems or reproduce a build, right? If we use star, star basically means go and use the latest version of this library. Doesn't matter what version is, just go use the latest version. What the carrot and the tilde do is they allow you to specify, okay, use the latest version of the library down to two dots, right? So 4.6.x or the tilde says, go use the latest version of the library down to one dot. So in this case, we may use 0.4 or 0.5, right? So it allows us to say, well, let's use the latest minor, minor version or let's use the latest major, minor version of that specific library, okay? So again, this is our package.json. This is our basic descriptor file for a JavaScript project. The project can be either a server side project like the one we're looking at here or it can be a client side project. We still use Node to build a client side project. You can use Node to write a server side JavaScript project or you can use Node to build a front end project that never runs on the server in JavaScript, okay? So I think we've done most of this NPM stuff. Again, NPM is basic management, a package management comes with Node. Now, since I put this slide deck together, there's probably been more libraries added into the Node repository or the NPM repository, right? So there's 120,000 libraries. We go to npmjs.org, let's see how many we have today. Again, hopefully our internet works here, otherwise it will be very short demo. So, but when you look at this number, there's 127,000 libraries in the NPM repository. Now, if you think about that for just a second, how can there possibly be so many libraries? 127,000 libraries, what do all these libraries do, right? It's like, this is insane. Why do we need this many libraries or why are there so many libraries? Well, one of the things in the Node community is the ability to very easily take any project that you have and publish it up to the global NPM repository. It's extremely easy. In fact, I could do it right now in about one minute if I wanted to. I could publish this Hello Node library or this Hello Node project up to Node within a minute if I wanted to. So with the ease of being able to share your library, what happens, people write libraries and then they go share them, right? So you can see today, there is almost a quarter million libraries. This is ridiculous, obviously. I mean, how many libraries do we really need? So for say, for example, you wanted to use a library to do CSV parsing, right? Everyone knows what CSV is, copper separate comma separated values. Let's search the NPM repository for comma separated value libraries. There's 1500 results for this, right? In reality, how many libraries do you actually need to do CSV processing, right? If you're in the Java world, you might see one or two or three, right? Maybe, there's 1500 here. So if we go look at this, you'll see that again, because it's so easy to publish things in the Node world, people just publish them. They'll write a library and I'll just throw it out there, right? And that's great if you're publishing something, but it's not so great if you want to search and find a good library for doing CSV processing. So what we actually do for this, and what most folks in the community will do, is they'll find something that is popular and also meets a few other basic standards. So this is the top hit for CSV library. You can see that it looks like it's fairly, the documentation so far looks pretty good, okay? What we can do is we can say there were 10,000 downloads, so it looks like it's fairly popular, then we'll go have a look at the actual library in Node, and just, or sorry, the source repository for this in just a second. But what I wish to key on right here first is this stuff right here. So you can see that there are these little green tags here, build passing, build passing, build passing, right? So if I click on that, hopefully that'll load relatively quickly, you can see what they've done for this library, if it ever loads, is that they have applied some basic software engineering practices, specifically in this case, they have a continuous integration build around this. So that gives me a little bit more comfort. It lets me know that the people who wrote this library have, and of course I picked the wrong one here, let me find a better one. So let's look at this one here. But it gives me a little bit of comfort knowing that they have a build process around it, which means they probably also have unit tests around this to do low level testing, so as they make changes, everything continues to work properly. And as you can see here, indeed, they have builds in here, people have committed into this repository. Sorry, it looks like they had some errors a few days ago that someone went in and fixed. So that's the other thing that this also tells me, aside from the fact that they're applying basic software engineering principles, continuous integration, unit testing, things like that, there's also people actively contributing to this repository, which gives me a good feeling about this. And of course, the other thing that we care about is documentation. Has the folks who have written this library written proper documentation for this? Okay, so if we go into here, you'll see that we'll get some documentation, right? So this is probably a pretty safe bet for me to use inside of my project. So the other thing that we care about a little bit is it's being managed, how many folks are using it? The other thing is it's not just, oops, so I'm supposed to go back. The other thing is you can see that more than one person has contributed to this library. So there's an active community of people also contributing into this library. So that gives me a good feeling and lets me know that this is probably a good choice to use in my own project rather than some other library which maybe not many people are contributing to and not many people are actively supporting, right? So if we go here, you'll see that there's something for JSON and other stuff, okay? But this is both one of the strengths of the node and NPM and in general the web community is that there are a lot of people who contribute code and so we get a lot of great ideas. The different tools and frameworks that we have in the JavaScript and web world are constantly being pushed to the limits. People are coming up with new ideas and new tools for doing things better. But the problem with that on the other side is that as a developer, which tool do you pick to do something, right? Whether it's something really low level like a CSV library or something high level like a web framework, right? One of the questions I always get when I speak at a conference is, well, we're starting a new project or we're refactoring an old project, which web framework should I use? Right, should I use Angular? Should I use React? Should I use Ember? Should I use BatmanJS, CanJS, SensorTouch, et cetera? You get the idea, et cetera, et cetera. There's so many of these projects. So it's both a good thing and a bad thing, right? It's great that we're, as a community, pushing forward and doing things in a better way, but sometimes it's like I just want to mill the project. I actually have to get real work done, right? Okay, so we'll talk about it again, so I've jumped ahead a little bit. This is what I mean by it's a different universe than what you're used to. If you're from the Java world or the C sharp world or even the Ruby world, it's a different way, different mentality in the node world. Very much a concept of sharing and pushing forward as quickly as possible. All right, so what I want to do next is talk about Grunt, which is a build tool. So we'll look at some examples in just a minute to give you an idea how we start some basic building and testing of our project and other things like that. And the most popular tool in the community currently is something called Grunt. Grunt is a task-based command line tool. You probably saw in my package.json earlier that I had some Grunt dependencies in there. And Grunt has a number of different plugins that you can use to do things. It has a plugin for doing JavaScript linting, running unit tests, doing code modification, et cetera, et cetera. It has tons and tons of plugins that you use inside of it. Again, if you recall from when I had my package.json up, you will probably remember that we had this dev dependency section here where I specified Grunt and some Grunt plugins here. So you can see in this project, I have the js-hint-node-unit-uglyfi plugins as well as Grunt specified for this specific project. And what a Grunt file looks like is something like this. So first thing we do is in our package.json, we specify the dependencies for Grunt and some plugins, and then we write something called a Grunt file. In this case, what this Grunt file is doing is something very straightforward. It's initializing the Grunt js-hint plugin, which you can see we have Grunt load npm task, Grunt contribute js-hint. So we're saying Grunt, go load the js-hint plugin for us. Okay, and then initialize the configuration for js-hint. All the files that we want js-hint to run a linter and again js-hint is a style checker and a rules enforcer for your code base. We're saying go and test all these files or go and check all these files. Make sure that they meet our coding standards that we have in our project. So what we can do from the command line now is in this project, I can just say go run grunt js-hint or because I've registered the js-hint task to be the default, and you can see that this is also an array. So I could say, all right, as part of our build process, let's run js-hint, let's run node unit, and then after that, let's run the minifier, et cetera, et cetera. So we can go in and specify a series of different tasks that we wish to run for this project. But in this case, I'm just gonna run js-hint, so I can come in here and I can run js-hint and you'll see that it looks like I actually have some problems in my code base. So let's see what we have here. We're mixing tabs and spaces, so I can go in and I can fix these things, but again, you can see that these things are violating the rules that I have as part of this js-hint project. Again, the reason why we want a linter like this is to give us a maintainable code base that follows certain rules. So if I went into here, and for whatever reason, go into this app.js, right, and I'll just do something silly like take out a semicolon, right? Say I forgot to write the semicolon. The compiler doesn't check this for me, so I have to have something like js-hint that will check it. So now if I go run this, you'll see now, it will say, hey, it looks like you forgot to put a semicolon here, right? Or, hey, you forgot to use a triple equals instead of a double equal. Various other rules that we have that we wish to enforce before they make it into our actual code repository. Good. All right, so we ran grunt from the command line. We saw that there was an error there. We could go and fix that. And that's about as deep as I want to get into grunt for now. What I want to talk about for a couple of minutes, because if you go and look at different projects that you find source code for on GitHub or other places, you'll see that some projects use something called gulp instead of grunt to build. So gulp is a streaming build tool. It's very similar to grunt. It has a slightly different approach, right? What it does is you stream things from one processor to the next, and it's also plugin-based, like grunt is. And there are a lot of projects that use gulp. A lot of projects do use grunt. Some people believe that gulp is a successor to grunt. That is still very much a question mark, unfortunately. Okay, so there's not one specific build tool that people use. And in fact, when we look at the next tool, which is Webpack, which is a module bunver and not so much a build tool, you'll see that there's yet another tool that folks use when building things. So let me just show a quick example of a gulp file. Yes, please. Yeah, so I'm gonna show that in just a second. When I look at the source, hopefully, of course, I don't have project open with that, so bear with me just a second, and I will go open a specific project that has a gulp file inside of it, and we'll have a look at what a gulp file actually looks like. So this is a gulp file from a starter kit for a React project. And if we go look at how a gulp file does things, let's look at the assets tag in here to demonstrate the streaming part of this. So this is a specific definition for a gulp task called assets, which does processing of static assets. And the streaming part comes in right here. So you can see that we're saying, this is the source of our assets, go and pipe that into this specific process, take the results of that, pipe it into this next process, and then pipe it into this next process. So it's a streaming build tool. You basically stream transformation of your source or your assets from one thing to the next thing to get to your eventual result. So again, if you're familiar with the concepts of streams, you can see we're piping results from one processor to the next. If we look at something a little bit more elaborate, this is a gulp definition for processing styles. What we do here is we say, go and grab all of my CSS and less files, pipe them into the source mapper if we're doing a development build, run a CSS auto prefixer against it, run CSS comb, which is a way of inlining and speeding up the loading of your CSS. Take the result of that, pipe it into the task runner that will minify the CSS, and then we're gonna output it into here, and we're going to go apply this into a template. So you can see we take our CSS files, we gather them up, we go run an inliner, first we run a source map up here, then we do an auto prefixer, which is a standard practice for CSS files. We run an inliner, take the result of that, pass it to the minifier, and then finally output it to a file. So you can see this is how it's different than grunt, and one way is that it is a stream-based thing where you pass resources down into the next processor. So if we look at this gulp file, see if there's anything else that's interesting in here, you can see our main build task in here goes and runs a clean first, and then runs a sequence similar to what we saw in our grunt file, where just go run this, run the assets, run the style, and finally run a bundler to get everything ready, okay? But we can also do other things within our gulp or our grunt file. So for example, in this gulp file, what we're doing is we're saying when we're running a build, watch task, what we wish to do is we need to run a build, and we need to watch the assets and the styles so that we can do auto-updating in development as we're building our project. So this is a task that we'll use to make sure that as we're building stuff, or as we're actually coding our project, go and update things and automatically push them into the browser so that we don't have to keep restarting or reloading our web browser, okay? So don't want to get too much into gulp now, but what I do want to spend a little bit of time talking about is Webpack. Now, Webpack is similar to Browserify. You may have heard of a tool called Browserify. That is a similar tool to this. It also builds a set of files for you and produces what is called a bundle, right? And Webpack and Browserify are both commonly referred to as module builders. What a module builder does is something that is suited for large projects, specifically Webpack is suited for large projects. Webpack allows us to do code splitting, allows us to process static assets, et cetera, et cetera. We'll see an example of a Webpack build file in just a minute or Webpack configuration file in just a minute, right? So with Webpack, what we want to do is we have a bunch of different assets in our project. We have JavaScript files, we'll have j-templates. We may be using CoffeeScript, or if we're on the leading edge of things, we may be using ES6, right? So we need to have a Babble Transformers part of our Webpack module bundle. We also may have PNG files, et cetera, et cetera. And the idea is we take this, we configure Webpack to say, here's all my source files, and this is how I want you to take all this stuff and produce bundles that we will ship up into the browser for either development or production build. So it takes all those assets and it produces one or more JavaScript files for you that you can then import into an index.html or whatever to start running inside of a browser, right? We can also do processing of PNGs, processing of CSS, just like we did in the gulp file and other things like that. But the way that a Webpack generally works is if we go look at a Webpack configuration is, so you can see that we're saying, this is where we want to output stuff, here are some different configuration options we wish to use, okay? And let's go find the specific thing that we're interested in, right? So here's the configuration for my Webpack, my second layer of configuration for this Webpack. It's saying that the entry point is source slash app.js and the output is going to be app.js in the distribution folder. Now, if you remember what I said before, the way that we do modern JavaScript projects is we don't just go get the actual raw source for, let's say, Angular or React and all the other libraries and our own source code we're using. What we do is we create a package.json file and with this package.json, we say here's all the dependencies for my project, right? Let me pull up the package.json for this specific file or this project because it's much more elaborate than what we've looked at, right? So this is specifically for a React project but it doesn't matter if it's React or Angular or Ember or whatever, okay? Webpack can be used for any type of framework. See, we're using React here but we have all these other things that we're using. We're using Lodash. SuperAgent is a way to make Ajax calls. We're using Bootstrap and Bootstrap is a CSS library. It's not even a JavaScript library but a modern module builder like Webpack will understand that, hey, I also have CSS checked in to my node repository for this specific project, okay? So here's all our dependencies here and what Webpack does, again, if you remember, our entry point is source slash app.js. So let's go into that file. Here's app.js and you can see that this is an ES6 style so that's why it says import instead of require but we're using ES6 modules to specifically say that, okay, I wanna use React and my main component for this application is in component slash app and then I have a bunch of other dependencies in here, okay? So what a module bundle like Webpack does is it looks at the dependencies you have in your entry point and it basically starts walking all the files. So it comes here and says, okay, this is my entry point for building a bundle.js, a bundle that contains all the JavaScript that I need for this project. So from here we'll say, okay, looks like we're pulling in component slash app so I'm going to go now walk to this file, right? This file right here and it says, okay, what are its dependencies? So its dependencies are all these things right here and let's just pick this one right here, content page. So we'll say, okay, it looks like the app, the main component app also uses this thing called content page so then it goes into here and it says, okay, this is the import for that, right? So basically it walks all the import statements starting from the top and it gathers all the files together, right? Some of the files we have here locally, right? So you saw what we did is we went from this app.js here, we went from this app.js that included this content page so it walked over to that, right? So these are our source files for our specific project but we also have things which are checked into our node modules. So here's import react, right? Import invariant from this specific place in the react library. We go to other places in here, for example, for, we'll see that this specific project also uses a library called flux, right? So what it does in that case is because that's not a JavaScript source file which is in our project, it actually goes and it uses the source from our known modules folder. And you'll find it. So if we go into this project right here, you'll see that this is where we're at, we're inside a node modules folder. So when we do an npm install, it goes and looks at our package.json and it actually installs a copy of that library inside of this node modules folder. Now if we look into here, you'll see that here's the react library. So when the module builder, in this case webpack, goes and needs to load react, it will go into the node modules slash react folder and go grab the source of the library from there, right? So once it's done walking the tree from the entry point, the module builder webpack will go and output all of those different JavaScript files, whether they're locally in our project or whether they're from a node module and we'll go put them into app.js, but it will also run some transformations. In this case we're saying first go grab all the JavaScript source files, run the dedu plugin, run the aglification JavaScript plugin and then run an aggressive merging plugin to reduce the load time of this specific JavaScript file. And once it's done that, it will output a bundle.js that we can then import into our project. So just to kind of cover, let's go into slightly simpler project real quick. So let's go find simple file here, right? Again, you'll look at app.js, it walks this app, grabs all these different libraries and will output everything into a bundle for us. So this is a different webpack configuration, but we'll see it has the same basic stuff. This is the entry point, this is the output file name bundle.js. Then what we'll do is we will import that single bundle.js file into our index.html and that's how it actually gets loaded into the browser. All right, so let me pause here for just a second because I've gone through quite a bit of stuff. We talked about webpack, how it uses the entry, how it does processing of these assets and then how we load it into our actual, and that's a little cut off there, but you can see that there's a script tag where we load our bundle.js. So this is how we do modern building and kind of packaging of our application. Yes, sir. You want to use what, I'm sorry? Yes, yes. Okay, so let me understand your question specifically. So what you're saying is that I have all these libraries that I'm using both internal and external and your question is specifically, yes, yeah, yeah, yeah. So okay, so the question is what if I have a React in my pad somewhere, the React library in my pad somewhere. Well, that's how we do things today. What we do again is we pull the React library down from the master source, if you will, from the node repository. Yes, you can go grab the react.min.js from the React website, but that's not how we do things nowadays. What we prefer to do is, well, so I'm gonna be here. What we prefer to do is we prefer to put things into our package.json file and specify in a versioned way these specific libraries that we want to use. And then what we'll do is we'll, so say you're new to this project. What you'll do is you'll do a git clone, pull down the repository from source, and then you'll do an npm install. And what this will do is this will reach out to the npm repository and download everything and put it into my node modules folder like so. So there's a little bit of a process there where you sit. Okay, so if you don't want to include something, then what you do is, and I apologize, I may have glossed over this a little bit, what you do is you include it as part of dev dependencies. So when you include something in dev dependencies, that will not get packaged up as part of your project. But again, it's actually a little bit more subtle than this. If in my project, let me go back to my source editor, in my project, if find the right project, sorry. In my project, if I import with, somewhere for my web JavaScript project, if I import a library that, and then that library gets used in this file, you have to have it. So basically if you have it as an import, if you have it included as part of your project, it will automatically go and get included. Or otherwise your project won't work, so. All right, so let's move on. Talk about Webpack, and let's get to the heart of what we want to talk about here, which is specifically CI automation. So we talked about how modern projects are built in the JavaScript web world. We talked about craftsmanship already. We talked about some of the tools that we use. Now let's actually see them in practice, okay? So why do we want to do web and JavaScript project continuous integration? We talked about bundling of all assets, automated testing, unit functional and integration tests. What are some other reasons that we need to do web and CI, CI for web and JavaScript projects? We can have that automated reports that are part of our build process. And we can also do continuous deployment once we have some continuous integration in place. So we can do automatic deployment of assets and our build artifacts to staging or test servers or even to production if you're that sophisticated. You can also do deployment versioning, okay? All the great things that we normally do for CI and CD, continuous deployment and continuous integration for our other projects, okay? We want to apply the same rigorous engineering principles around that, right? We also get some other things that we can do which are very useful, static analysis of code. How good is our overall code quality? Where problems that we can fix even before we get to runtime? And then some of the advanced things that we can do is we can run performance tests against our web and JavaScript projects. We can tag releases, right? All these useful things that we need in especially once our project has a large number of people working on it or the project becomes complex. Great. So unfortunately this is something that does require effort. You have to have a build script, right? You have to write a build script to be able to do this. This is not completely true. What you can do is if you're using Angular, using React or basically any framework, there are already recipes available to you where you can just say, I'm just gonna use this template project and it has everything set up for me. It'll have Grunt set up, it'll have Webpack set up for me, right? It'll use some specific version of Angular or React or whatever. So you go grab this template project and then you can mix in the specific things that you want to do for your project instead of having to write everything from scratch. This is what we do in fact, because it takes a lot of effort to write a Webpack file and make sure you get the Grunt configuration exactly right. So we have a starting point, then we'll add in stuff to do our very specific things. So there are common recipes available that just go grab a starter kit or a template project and that's your starting point so you don't have to spend weeks trying to put all this stuff together and get it exactly right. And then what we do is we use something like Grunt to drive our continuous integration automation. We're gonna look at that in just a second. Let's look at a simple build script which we've already done. So you can see that we ran Grunt here, let's go into our project real quick. Let's have a look at this other project that we have. This is a simple CI project. So in this project, you can see we have dev dependencies. Again, these dependencies don't get packaged with the actual thing that the user uses. This is just stuff we use at development time. Grunt, the Grunt CLI. We looked at JS hint earlier, Jasmine test runner. What do we do to run this project? This is how we run it. So let's actually drop into this project real quick. So we should just be able to fire Grunt from here. Let's go look at the Grunt file. You can see again, this is just doing a JS hint. We register a couple of tasks against it. Let's go run this and you can see we don't have any errors. Now what I'm gonna actually do is I'm gonna come in here and I'm gonna break this in some way. Let's just go and do something simple like remove a semicolon. We're gonna run this. Now this is broken. So now I'll do git commit dash A dash M broke the code base in some way by removing a semicolon, right? So I did something stupid. I'm gonna check this in. I'm gonna push this up to git. But before I do that, what I wanna do is I wanna fire up Travis, right? This is the first build tool that we're gonna look at. So you can see that this is something that runs in the cloud and let's go into our project. We see our build history. Currently the project is good. So what I'm gonna do is I'm gonna go and try to break this now. So hopefully our internet holds up here. If not, I have some screen shots I can show you. All right, so there you go. We have gone and almost pushed this up to git. So we pushed this up to git. Now what should happen is that for this specific project I have this configured in Travis CI, which is a continuous integration service in the cloud. And any second now, this should start spinning and, right? So you can see that it detected that I, or somebody made a change to the source repository and it's gonna start building it, okay? So it started building it and it's currently still running. So let's see what's gonna happen. I'm sorry, it's called Travis CI. You can see right here, Travis CI. All right, so it's still running. We'll give it just another few seconds to continue. Hopefully this won't take too long. It looks like it's installing the whole world though for some reason, okay? And you can see that the build is now failed because it failed a JS int task, right? And again, if you remember my commit message, I broke the code base by removing a semicolon, right? That's my commit message that I specifically wrote right here. And so now broken this. And the other additional thing that should happen is that I should get an error in my email in just a second saying that the build was broken. Okay, so it also emails the person who checked in that specific revision or checked in the revision until the build process fired up, right? But you can see I get my output and I can read the issue here. You can see it says it's missing a semicolon, i.e. it failed a JS int specific task. And of course to fix this, I would come into here, I would run this, I'd run this from the command line to make sure that I have everything good. And then I would say get commit dash A dash M, fix the build by adding semicolon. And then I would do a git push and then you can imagine what's gonna happen since we've already seen this, assuming to git push works here, is that it will detect another revision and it will start to build the project and I should get back to green once we get, once it detects that this has happened, right? So I've jumped ahead a little bit, we'll come back to this, we'll add build okay. So there it goes, it's gonna start building now. I'm not gonna wait for this to build because I don't wanna stare at the screen while this is happening, right? So we ran the thing, showed the demo, so now let's actually have a look at those build tools in detail. There are two specific build tools and there are lots and lots of different build tools that people use or CI tools to be specific, right? The two more popular ones are Travis and Jenkins. Now at your company, you may be using something like Bamboo from Atlassian or you may be using TeamCity, right? There are lots of these different build tools that are provided by different vendors. All of them support the ability to do what we're going to do here using Jenkins, right? So most people are probably familiar with either Hudson or Jenkins, so we're gonna do a demo of that. Those are both open source tools. There are other commercial tools, for example, such as Bamboo from Atlassian, TeamCity from JetBrains, et cetera. So it doesn't matter which build tool you use or specifically continuous integration tool you use, any of those will be able to do what I'm going to demo here in Jenkins, okay? So we already looked at Travis CI. This is a cloud hosted CI tool, so if your company's using GitHub or something else in the cloud, you can use their cloud offering. You can also install Travis inside of your own company, but obviously you have to pay money for something like this. The next tool that we look at Jenkins is a free tool, okay? What we do for Travis is we configure a Travis.yml configuration file and then we go and tell Travis, hey, this is where our source repository is and if you're using Git or GitHub, it automatically installs a build hook so that whenever you do a commit, it sends a message to Travis, which will go and start building it as we just saw. So our project should now be green as we just saw here. You can see currently this is the only open source project I have and hopefully this loads. This is the only open source project I have on my GitHub repository. But let's look at the Travis configuration file really quickly. It's very simple. It's saying this is a node-based project, specifically I'm using node version 422. Then what I do is I come into Travis and I say go and build this specific project. Let's go into accounts. All right, so what this will do is this will go and fetch all of my GitHub repositories and I can go and add one of these things in so that Travis will start building it. For example, if I wanted to build this React project or this other project, whatever, I would go and hit this button and it would start going to build it. So it's very easy to set up, very easy to get started. For open source projects, it's free. For commercial projects, there is a fee for it. Not a lot of money, but it is a paid for product, but it is the most popular CI tool in the cloud currently available. So we've done a demo of this. I'm just... I'm sorry. Okay, so the question is this. Can we also build a branch? The short answer is yes. So you can configure Travis to say I want to also build this branch as opposed to just master. So it's very simple to set that up and do. But what I want to spend the remainder of the time doing is talking about Travis and looking at its configuration. So again, Travis is a open source, general CI slash build server. It runs on your own hardware. If you don't want to run on your own hardware, there are companies that offer Travis build solutions in the cloud, obviously have to pay for them. But you can just go grab Jenkins and run this in your own server if you want. So before we get into this, I just want to remind what our three goals for doing this continuous integration project is. Our three goals are quite simple. We want to do code style checking with JS hint. We want to run code coverage using Istanbul. And obviously to run code coverage, we need to have some unit tests that tests make sure our stuff works properly. Okay, so our three goals, code style, code coverage, unit testing. All right, let's see how we set this up with Jenkins and let's actually run this. Again, the tools that we'll use to do these three things is we'll use ESLint or JSHint. ESLint is for ES6 code bases. JSHint is for ES5 code bases. Istanbul for code coverage. And your test runner doesn't really matter if you're using Mocha or Jasmine or tape or any of the other ones that are out there, okay? You can write your unit test in whatever you want. What we do to set up Jenkins, it's actually quite straightforward, is we'll go grab the Jenkins compiled file. Make sure I'm in the right project. So you can see I have a war file here. So you just go download the Jenkins war file, do Java dash jar Jenkins dot war. And this will go start running Jenkins server on this specific machine. And so we'll wait for this to start up. Jenkins is fully up and running. Let's go to localhost 8080, I think that's the ports it's running on, yep. So here's our Jenkins server. You can see I already have the demo set up here for us. And what we do once we have the server installed is we'll want to go and add a new project, okay? So what we'll do is we'll say let's do a new item and I'm not going to run through every little configuration step through this. It doesn't take long to set this up, probably maybe 30 minutes or so, okay? So we would create a new project, in this case I already have a project set up. Let's go look at its configuration. Okay, so here's my project. Where is my source code management for this? So in this case what I'm doing is I'm saying use a Git repository and I've just pointed it to my location for my local Git repo. Typically you would say Git's colon, SCM server, whatever, okay? So this is where I have it. Someone was asking which branch do you want to build? You can see I've said build master. I can also add a branch to have it build a separate branch if I want, okay? So let's go and look at some build triggers. In this case there's a little thing that we have to do when we use Git specifically or subversion to have a build trigger. We have to say pull SCM but we don't actually put a schedule in here. We can put a schedule if we want. We can say go run this build at the end of every day, let's just go run it at the end of every day, every work day and let's just produce a bundle, run all the tests, see what everything looks like. Or we can also, along with that, configure it to say whatever a check-in has been made, let's go run the Jenkins CI tool to go do a build. And how do we run that build? Well, you can see what we're doing is we're gonna run npm install and then npm run CI test, npm run CI lint. So this is gonna run the three tools that we talked about. So let's go do that really quickly actually. So now if we go to, if we zoom back out, go to our command line. All right, and of course that had to happen exactly when I was getting ready to do the demo, right? So all right, so while we're waiting for the projection to come back up, let me talk a little bit about Jenkins and how we approach the build tool and kind of how all this comes together. So what Jenkins does is it's just something that just goes and runs stuff for us and it looks for output from these tools in specific places. So when we're running Jenkins, we're running a build, we'll say Jenkins, go and run the test coverage. Go and run the JS hint to check the style. Go and run this other thing. So we basically just tell Jenkins to run stuff from the command line. It will go and run all these things and then once all those things have run, right? We run JS hint, we run isTanBolt to get our test coverage and we'll output a file over here that has all the details of our test coverage. We'll run the unit test runner, which will have the output over here and then we'll have the thing that goes and checks the style and make sure that that's all good. That will output something over here. So we basically just go run stuff from the command line, right? Jenkins will go and run these things from the command line as we tell it. We'll get these outputted files for the results of those tools running and then Jenkins grabs those outputted files and puts them into its dashboard so that then we can go look at it, right? It will also notify us just like Travis did. Jenkins will go notify us and say, hey, we ran this stuff and it looks like somebody broke the build since the last time it was run and it will give you a list of the people who did a commit since the last time a build was run, right? So Jenkins in and of itself is actually a very simple tool in some ways. All it does is it says, okay, you told me to go run these things from the command line. I will go run them and then once I'm finished, I'll go gather the output of those tools running. I will go put them into the console so that you can come back and see exactly what happened the last time I ran this build script. That's pretty much all Jenkins really does. The real kind of work around this, Jenkins is fairly easy to set up, right? There are a few little things but this is a known thing at this point in time in terms of how we approach this but the real work for us as developers or as build maintainers is setting up those low level tools, right? Setting up ESLint or JSN, setting up Clover, sorry, not Clover, setting up Istanbul, thank you, setting up all those different tools, right? So that's the kind of hard part about this and if the projector ever comes back on, I can show you exactly how those things are set up. So yeah, so the question was do you have a project template for all this stuff? If you go to my GitHub repository, I have all the source code that I've shown in this session in my GitHub repo and you can just pull that down, okay? So all the template projects are up there and in fact, remember earlier I mentioned that if you're building something with Angular, you're using React or even if you're doing a jQuery based project, if you go to GitHub or if you just do a Google search, you will find a large number of template projects that people have already published the source for into these repositories. So you're welcome to look at my project, my project is very simple, but what we typically do is we will use a more sophisticated template project for the specific thing we're building. So for example, for our React project, we have a very specific template project that we use that is the starting point for our React project and that has all the stuff built into it, right? So yes, go look at my project, you may want to integrate that into yours, right? Or again, if you're using Angular, React, or Ember, or BatmanJS, or whatever it may be, you'll find a much more sophisticated project that most likely will have all this other stuff set up as well, okay? And is the projector gonna come on? Someone looked at the projector yet? It usually doesn't take this long to come on. It did during the last power cut. So yeah, go ahead, please, let's take some questions while we're waiting for projection to come back on. Yes, okay, so the question was is, in my package.json, I had a static version number, okay? So, and the question is, is how can I do dynamic versioning of my build? Is that what you're asking? All right, so there are two different things that we're talking about here. For my project version that I have in my package.json, that's version 1.2.3, or whatever. That's the specific version of the project itself. When we wanna build, we also can affix a incrementer or we can use a timestamp to stamp that specific build width. So you know exactly what that build was, okay? So there's kind of two different things. Right now, my project is on version one, two, three. Oh, I have this new feature that I need to build. Now I'm gonna increment my project number from 1.2.3 to 1.2.4, or maybe 1.3. But that's separate from the actual build number. The build number is, relates to yes, the version number of your project you're building, but that's specific build for that specific revision. So the build number changes quite frequently, but the actual project version number doesn't change very frequently, right? So I get a new project, now I'll increment it from 1.2.3 to 1.3. I have these four bug fixes I need to do next week. I'll increment the project number, oh, that's me. Increment the project number from 1.3 to 1.3.1, but the build number is still something that's totally different from the project number, okay? Does that make sense? I'm sorry? You mean in the build? Yeah, we'll have a look at that in just a second. All right, so let me come back to your question. Let me get moving on with the slides, okay? All right, so again, what we want to do was go into here and how does Jenkins run our build? Again, all you do is you just say, run this thing from the command line and then tell me where the results are. That's all Jenkins needs. So what I'll do is I literally will come to the command line now, I'll go into my project and I'll do NPM run CI test, right? If we want to know where that came from, let's go into our Jenkins example. I'll look at the package.json for this project. You can see the dev dependencies are ESLint, espan, Istanbul, and tape. Tape is like Mocha, it's just a test runner. And specifically in your package.json for an NPM project, what you can do is you can say, these are the quote unquote scripts or command line utilities that are part of this project. So I can specify them like so. I can say test does this, lint does this, CI test does this, and CI lint does this. And again, if we flip back here, you can see what we're doing is we're telling it to run from the package.json, CI test, and CI lint. We can actually go and test all this stuff and run it directly from the command line. All right, so I'll do NPM run CI test that will go fire up Istanbul. And you can see it's saying Istanbul, do a coverage using the tape tool, test everything in the test.js folder and output it to test.tap and then run a report against it to produce a Clover like output. The other thing that we ran was run CI lint. So we can do NPM run CI lint and that will go and run, let me go run this again, it happened very fast, that will go and run that. And you can see what it's doing is it's saying run ES lint. Again, if I flip back to the package.json, CI lint runs ES lint, output it in check style format, start with index.js, and here's where the result goes. So it actually outputs that XML file once we've run it. And you can see when we ran this, you can see I got an error. Okay, why would I get an error here? It looks like it ran the tool. So what actually happens is when these command line utilities are run by Jenkins, it will output to the exit code whether or not that thing was successful. So if you run something from the command line, let's say we just run something really quickly. Like let's say I ran clear, but let's say I run echo, hello, BLR, right? Whenever we run any process on Unix, on a Unix based system, it will output a zero if that process finished successfully. If that process failed for some reason, what will it output? Something besides zero basically, right? So that's what Jenkins uses to detect if there was some kind of error along with the output files. So when we ran this specific task, we didn't actually have a real error in here. What happened is the link to ran, it detected some issue with our code and instead of outputting a zero as the exit value of the process, it outputted a one or maybe a three. I don't remember exactly. It's something besides a zero so that it lets whoever ran the thing know that there's some kind of quote unquote error. So we go look at the actual output for this project. Let's go to the status. You can see that the last time I ran this, there was an actual issue with one of the tests. So you can see that there is some kind of issue within this specific test that says that I had a build error of some kind. So let's go back to our configuration. Let's actually run this from the command line and see what happens. Okay, so let's go back to our project. Go to the configuration, zoom in a little bit. So you can see this a little bit better. All right, so there's where we ran it. And again, the kind of last step, so if I go full circle on this and complete the loop, I showed how we run this, showed how Jenkins runs this. We said that some files get output over here. Now how does Jenkins pull those files in? Well, what we do is we have something called post build actions in Jenkins. We say we add these three different things that I'm talking about, right? So what we do is we go to the bottom and we say go and add a post build action. And you can see that we have a number of different post build actions. We already have added published tap results, published check style, published Clover coverage report. So those things are grayed out, but there are other things we can add here as well. We could add in an email notification or set the build status on the git commit, do a git publish of some kind, right? But if I scroll back up here, you can see for this we say, this is where the output for the test result is. This is where the check style result is. And by default, it uses checkstyleresult.xml as the output, right? So checkstyle-result.xml. If you remember, well, I'm gonna need to zoom back out. If you remember what we did is when we configured the slink task, what do we tell it to do? Output the results as checkstyle-result.xml. So you can see we're just kind of gluing everything together here or connecting the dots, right? Same thing for the Clover code coverage report. Where's the directory for it? What is the report file name? And also one interesting thing I can do here is I can say what are my coverage metrics for a good build, a bad build and a somewhat good build, right? So you can see I've said that if a build is good, if I get 70% method coverage, 80% conditionals coverage and 80% statement coverage. So we can apply these little metrics here, specifically for the code coverage to let the build know or Jenkins know that this build should be passed or failed based on these results, okay? Because getting 100% code coverage is often not realistic for any kind of project, not even just a web JavaScript project, but even a Java or C-sharp or Ruby project. 100% code coverage is not something that we can typically do, right? So let's go and actually see. Let's go back to our status page. I'll leave this page, I don't want to make any changes. And now you can see we can, we looked at the TAP results very quickly to see what the actual issue was. You can see that this specific test case should be equal was the thing that failed so we can go into our source code. Excellent, let's go run this before we do anything else. So normally what we would do to run it is we would just have a, as we saw in the configuration, we would just have some kind of schedule or we would use a build trigger or a SCM trigger, right? I'd check something in to Git. Git will go and form Jenkins with the hook to say someone checked something in, go do a build, or we can have it run every hour or every day or whatever. It's fully configurable by you. So what I'm gonna do instead here is I'm just going to click this button to build now and I'm gonna have it start building our project, right? And it should start building anytime now. Let's go back to the command line, let's see if it's actually building, yep. So you can see that it started running a build and if we go into here, we can see the results like so, okay? And it didn't look like we actually broke something but you get the idea, right? I can also click into here for the code coverage and you can see that this build passes even though I have statement coverage, functions, list, et cetera, right? So you can see this is the actual result that was pulled in by Istanbul, which is our coverage tool, right? So we looked at the code coverage, we looked at the test runner, now let's go look at the check style, right? So what this does is this allows us to look for this specific build, what the different issues were and you can see that one of the issues that I have here is that this specific line, you can see from the tool tip is missing a semicolon. So you can see that it's gone and run our stuff and it has this nice console force, right? We go back, we look at the build history, you can see as I was playing around with this project, I went through and I broke the project in multiple different ways. I could come into here and let's go actually break this in a way that is not recoverable. Go into here and we'll just type some garbage in here and let's see what happens. Let's come into here now, I'll say build now, this will start a build that should show up here any second now, there it is. So you can see that this build is running, who made the change and of course something is not set up right because that should be totally broken, okay? All right, so we don't have much time left so what I wanna do is I wanna make sure I've covered everything and then we'll move forward. All right, so we talked about how to start, set up Jamkins, the things that we used, created a freestyle project, we can use a local repo or git, showed how to configure that, we can pull the SCM or have a build trigger, we can set up our configuration to provide a node.js binary if we need to. We talked about how Jamkins just runs something from the command line, showed how to add a build step, how to publish the results for the different things we were doing, looked at how we integrated these things into the build process, okay? Showed how we ran these things, package.json, we ran these things and we got the outputs. So the results for the outputs. So last few minutes what I wanna do is I wanna talk about kind of next steps. I've covered the basics for this and how this works. All right, so some of the other things we can do as part of this. If you remember I briefly showed one of the post-build hooks that we could put in which is send an email to the people who committed, or the last number of people who committed to this project. We could use this to do isolated build environments. One of the other things we can do is we can also have Jamkins take the resulting output of our web and CS project and have it directly publish the assets, index.html, bundle.js, et cetera, et cetera, have all that stuff published directly to a staging or a test server of some kind. So we can do push button deployment to a test staging server or we can have it even push directly up to a production server if we want. So the things we did not talk about is having multiple Jenkins servers in a master build configuration so that if you have a lot of builds going on, you can configure an array of Jenkins servers so that they don't have to wait for things to get built. We didn't talk about how you enforce security for the Jenkins servers and there's a ton of different other options that we didn't have time to talk about, okay? And again, I've talked about this a little bit before if you're using an Angular, React, even if you're on a jQuery project, one of the things that we try to do is we try not to make our build process so customized that it's difficult to keep up with the changes that are happening in the JavaScript world. As you know, there's a new framework out every year or there's changes to frameworks that are very, very different. So what we like to do is we like to use a template or starter project and we like to stay as close to that as possible as we go through time. We don't want to make too many customizations because what happens is a year from now, everything will be different and now we have to figure out how we fold everything back into what's different in these frameworks and if we're using a starter project, how do we merge that into our old project, right? So we try to use a good starter kit and we try to not have too much customization, right? So some references here and again, my GitHub URL is the same but you can't see it unfortunately. My GitHub ID is github.com slash prptel right here. So you can go and I think Narash is going to make the slides available online. So if you want to have a look at the slides, grab the slides, the source code for all this stuff is on my GitHub URL, github.com slash prptel. All right, so we have about five minutes for questions or four minutes for questions. So I'll happily take some questions. Yes, that's all right, go ahead. We don't have much time, so. Okay, so the question was is if I have a schedule build, how does a script know when to run things? How does a build trigger work? And what's the configuration or the setup of that, right? So the question is say I'm writing test scripts in Selenium or whatever and then I need to have a build to test that against. How do we kind of manage those two different things, right? So typically what folks do is for things which are not part of the base kind of build process, the low-level unit test, but if we have automated acceptance or functional tests here, what people typically do is they'll do a build at the end of the day and then they'll take that build and then publish it up to a staging or dev server and then schedule the automation to happen right after that, the test automation to happen right after that. So people generally use a test automation schedule to do things like that. That's one approach. The other approach which is more sophisticated is if you're using something like Selenium, when the build happens in Jenkins, you say, okay, you remember we ran NPM this and that. One of the other things we could do is within Jenkins is we can say, hey, go add some more post build actions, right? So if you remember, there were some post build actions right here. Let me zoom in here, right? So you can see that we have the ability to say, after you finish doing this build, go and run this thing over here or run this thing over here. So you can just go in by doing, by picking one of these options and specifically we would use build other projects here which would tell this other project to fire off and it would go find the, you tell it, hey, this is where we output all the results from running our code build. Now go run our automation build over here and that will go find the latest post. So we can have something trigger the code build and then that can go trigger within Jenkins the other stuff that we want to run. Okay, it's relatively straightforward to do this. More questions? Oh, are we at time now? No. Okay.