The journey from Powershell to Grunt for Build and Deploy
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Stack, Paul
I am a huge fan of PowerShell. I use it for Windows infrastructure automation. I used to use it for build and deploy systems for ASP.NET applications. I feel that there are simpler alternatives for build and deploy systems out there. This is when I was introduced to Grunt. Grunt is a JavaScript based task runner. As it is JavaScript, it is multiplatorm. It can be used to build and deploy ASP.NET applications as well as Node.JS applications. During this talk, I will create a build and deploy system with Grunt. This will replace the PowerShell build and deploy system that I already have. I will then integrate the new Grunt scripts with TeamCity to show how simple it is.
 Okay, thank you all for coming to my talk. Are you sure you want to be here? Douglas Crockford speaking, Mark Seaman are speaking. You know, some great speakers out there. Do you want to really be here? So this is a talk about the journey from Pireshell to Grunt for our build and deploy. Okay, my name is Paul Stack. I have some contact details on the screen. If anybody takes offense with what I say or wants to discuss it further, then please do get in contact with me. I'm an infrastructure engineer for OpenTable. After the last session, someone said, what does an infrastructure engineer do? I don't know. I seem to be away from the office an awful lot and I have an amazing team who are building very cool tools for our infrastructure based around using Puppet for orchestration of changes to our production systems. I'm a DevOps extremist. Over the past six, seven years, I loved CI. After CI, I thought there's got to be something else and then I really get into continuous delivery and in order to understand continuous delivery better, I started looking more in towards DevOps and getting into the DevOps world and now I just believe that it's the only way that companies can truly succeed in delivering amazing software in the best manner. I'm a conference junkie. This is my eighth conference. I feel as though of this year, it's only June. I feel as though I should go to a support group so that I can go, my name's Paul. It's been two weeks since my last conference. I enjoy going and meeting lots of new people. This is a description of where we were, where we got to, and where we went and where we're at now. We're going to be showing lots of code examples so people can see them. There's a ton of our code that's already open sourced. You'll actually be able to see a lot of what we've already written. In the beginning, when I started at OpenTable, just short of three years ago, we had a custom written build tool. It was a proprietary piece of software that was a little console application that required to be installed onto a build server. It was written in C sharp and SP.net. Two, it's probably not the best thing if we look at it now for a build tool. Back then, it was really good because it was interacting with our Git or SVN repository back then. Who still uses SVN? It was interacting with our SVN repository and being able to pull tags and it was being able to create tags for us and so on. It was extremely versatile because it took care of things like our own internal web config transformation. Our main website has got nine different variants of it, different languages across the world. This little tool managed to swap all the different web config pieces into the right place when it required. It was actually very good. It became extremely difficult to maintain. What we did is we had a build server, one build server. On that build server was this console application. Also, on that build server was Visual Studio. It became very difficult to maintain. We thought, let's start moving away from that. This was a central agent for all the builds across our web platform. This was quite a big deal. We had a lot of builds going on. When that server went down, that agent, we were in real trouble. We had the rise of PowerShell. I'm a huge fan of PowerShell. I always have been a huge fan of PowerShell. If people can understand what I'm actually saying, that's Microsoft PowerShell. It's just my silly accent. Over the next couple of months after I joined the company, my team really, we became responsible for building a new web application. The application was ASP.NET MVC app. The old tool didn't build that app. That's when we realized that things had to change. We needed to create new scripts. I had just come from a previous company that I had just gone and implemented an entire new build system. Actually, an MS build. Looking back, I don't know why I'd ever choose MS build. I guess any MS build developers, anybody like MS build? By need. Who likes the brackets? Everyone loves a bracket. I started to realize how amazing PowerShell was and how versatile it was for Windows infrastructure. On top of PowerShell, there is a DSL, the main specific language called Saki. It is not pronounced P-sake as everybody that I meet does. It's a silent P. It's got a very similar style to rake. You describe things in tasks. The best thing about it is it avoids the angle bracket tax of MS build. Does anybody know Saki? I know a couple over there do. It's a pretty awesome tool. It was originally written by a guy called James Kovacs as a version 1.0. Then it was re-released by George Matos as a version 2. As I said, I was creating things in MS build for a long time. I spent many sleepless nights trying to work out why my build scripts didn't work. It was because of brackets. Brackets and escaping of characters. DSLs are a lot easier to use and they are a little bit more fluid. They just make things a little bit better. Why Saki and not rake? I'm a reformed Microsoft fanboy. I used to be a huge fanboy and it was all about Microsoft tools for me. Because of that, I hated. I detested Ruby. I write Ruby on a regular basis now. I'm like changed completely. PowerShell had to be the way forward. If it was an MS build, and it had to be Microsoft, it had to be PowerShell. I know somebody in the crowd has written their own build script tool. This was going back like three years ago. I didn't know many other tools existed then. With all the power that PowerShell actually brings it, this is extremely versatile at what it can do for builds and deploys. PowerShell is a remote for your deployments. You can start jobs, you can set process weights, et cetera, on your build. It becomes really good. The script, look, that follows. We have a repository. The last time somebody is actually maintaining this. Originally, it was created two years ago. We did all sorts of cool stuff, but our build script effectively looked like this. We passed in some properties. We had some configuration, which was like the type of configuration, so if it's debug or release or so on and so forth. Solution directories, solution names, project names, whether it's actually, whether it's going to be packaged or published or whether this is a part build, the build number. It just started to grow exponentially. If you look at the git blame of this file, you'll see that probably five or six different people have been touching pieces of it and breaking everything. We'll discuss why that's the problem later. It was really easy. We had a task default, which depends on build, unit test, and acceptance tests. The build basically said run MS build. We had a wrapper's file, which I'll actually show you the wrappers. The wrappers is where all the nastiness is. There we go. Run MS build. Again, this has got horrendous over time. We would switch based on configuration. Because you're inside PowerShell and you can connect to all the pieces of the system, we could just use exec MS build. We could actually trigger from PowerShell and MS build script. Then you pass in all the parameters and then we actually use the output parameters to Team City to tell us when the build was ready and so on. But we'll come back to that later. After it finished the build, it would then go through a series of steps based on the crap that people added to the script. I say that in the lightest, hardest, the light hardest sense of the word crap. It just so happened that these scripts other people wanted to use. I made the biggest cardinal mistake. I made these a separate repository of their own. They were not part of my application. So therefore anybody in the company who wanted to could go and change those scripts. That was my worst mistake. We'll discuss why that was a bad mistake. Then at the end, if it was a, if you want to package it, it would go off and package the build. It would do some other DLLs and it would check some of the package. We want to make sure that the package that, when we package that up for the first time, we want to record a checksum and then when we deploy, we used to actually check that that checksum was the same because we're a SOX controlled company and you have to prove that what you built and test is exactly what is released. I don't know. Then we ran some unit tests. We had another wrapper called run unit tests. Maybe not. They're in there somewhere. We just basically passed in some configuration values of where the end unit exe is because we used to use end unit and we would pass in the directory that you would run tests against. Then we actually just passed in a couple of extra parameters where we said unit test result.xml. We want to get the result back so that we can feed that into Team City. Then we passed in the type of test, unit test. Looking back, that can 100% be refactored to the same method, just pass in having a wrapper and pass the types in rather than copying and pasting. We wanted to separate the fact that there were unit tests and there were acceptance tests and we wanted people to see that. We wanted to see that there was a distinct difference. The build script in itself was extremely simple. That's what Pyrochill gave us. The Saki notation gave us that simplicity. When it came to deployments, it became even more simple. We originally just started deploying this in a very small scale. We would just basically say get the site directory, get the package directory, the deploy folder. You would just change some, this is just like configuration, swap in the correct configuration into place. Then we would just copy the folder across the network share onto the server and then we would remove all the temporary deploy and then we would actually just do an IS reset. We would swap the system into place. As soon as we had swapped into place, we'd done an IS reset and then cleaned up. That is not a good deployment plan. It's really not a good deployment plan. That was like a V1 and that one was added two years ago. Then we started to get a little bit more involved with deployment. We had pre-deployment. We had set in load balancer statuses. We had warm-ups. We had going off and getting our artifacts. A pre-deployment was, see, we started to become much more professional with our Pyrochill scripts right here. Passing in and help messages so that people could see what they needed to pass in. It was go off to get your system from Artifactory. We use Artifactory for our packages. When you get, let me just go to the bottom, deploy site. Deploy site would basically say for each server in the list, because we could pass in a common delimited string of servers, for each one in the list, go off, get the files, extract the files to the server. Does that make sense? Really simple. We're not doing anything bad. After deploy site, we would then call the deploy configuration, which would go off and it would swap in the correct configuration based on if it was production and America or production in Japan. It would go and get the correct configuration values and put those in place as well. That was our pre-deployment. Then we would take the server off the load balancer. We would go off and we would interact with SQL server to take our server completely out of the load balancer. When it went off the load balancer and we got a good X-acode, a zero X-acode that it's worked, we would then do the final step, which would be the actual deployment in itself. All we did was call final deploy.ps1, which effectively swapped the server, swapped the folder systems around. We would take the old one, we would rename it to be old or backup or temp, and we would take the new one and rename it to be the actual folder itself. We would do an IS reset on that. Again, that is not a good deployment plan. This is going back like two years ago. We were very much as a company at the beginning of our continuous integration and continuous delivery start. It's something that takes an awful long time to implement because each environment has got its own different way of doing things, and each environment has its own stakeholders that you have to consult in order to build that pipeline. This was the first phase of it. We actually moved from a company that did manual deploys of these packages that this old C-sharp application created across and started now having a real sort of a pipeline. I call it a sort of a pipeline. Anybody any questions on those scripts? Does anybody want those scripts? You want them? We were 100% Microsoft, so that is exactly why there was no need for anything else. It was MS build and PowerShell or nothing. That was okay. We hired ASP.NET developers. Our developers all had core C-sharp knowledge. We didn't have anybody inside the company who was really pushing the bounds of other languages anyway. But yes, it was on cross-platform in any way, shape, or form. If you do want these scripts, let me know. You can have them. I won't even charge you for them. We could do all other sorts of things in here. If I show you some of our warm-up scripts, sending requests across, making sure that a get request returns a 200, and that the application warms itself up as part of the deployment. Our pipeline actually became quite good, and it looked something similar to... Sorry, that's the wrong one. We would pre-deploy the site, and then we would deploy the site. Based on parameters that we passed in, we could then say, and also warm the site up. Run that part of the script as well. Very quickly, because of so many people... There we go. Because of so many people touching this, let's go back to the actual slides. The scripts look okay. Fundamentally, there's nothing wrong with them. It's probably not the best way of doing it. As I said, people started to adapt them. One person would go, but my app needs to do this. Let's add a little if statement in there. If it's my app, then I'll do it this way. My app has this build configuration parameter. Let's add that into the case statement. All solid principles are going out the window right there. Very quickly, we get into a massive spaghetti mess, huge spaghetti mess. We ended up with a build in our system that takes 17 build parameters. Out of all sorts of rubbish going in there. We'd have deploy directories. We'd have branches because people were using branches for their things. You'd have project names. You'd have some package locations, some artifact. You'd have some hard-coded IPs. You'd have whether it's a service or a web app, it just became an absolute maintenance nightmare. But rewrites completely suck. Anybody been involved in a software rewrite? Has it been fun? Have you wanted to pull your teeth out? Yeah, they're not fun. They're really, really not fun. I'd already written one set of build scripts. Why was I going to put us through writing another set of build scripts? Do we really want another? Then we had a bit of a revolution in the company. We were no longer a Microsoft house. We were actually able to start writing applications in other languages. In the summer of 2013, we had an engineer joined us called Andy Royal. Luckily, I managed to get him on loan to my team for the first couple of months. We had just started to write a Node.js app. Somebody told me I could write a new application. I was going to choose a new language. I was unleashed. Andy wanted to learn grunt. Andy then decided why don't we start writing the build system in grunt? It's a new shiny thing. This was a year ago. None of the other ones had really come out yet. We'll look at some of the other ones a bit later. For anybody who doesn't know, grunt is a JavaScript-based task runner. You register tasks and then you can call those tasks in place. It's got a massive community ecosystem. When I rewrote the talk this morning, there were 2,954 grunt plugins available. There's new ones appearing every day. Now, you go and search for a screenshot or share or something like that. You'll probably get 20 variations of different packages, but there's a huge community present. Of course, grunt works really well with Node. You do NPM install grunt and you'll actually be able to start interacting with your Node application from it. What do the scripts look like? Right. Everything has a grunt file. We'll skip that top part. That's not really relevant. We go off and we go to a directory and we can say, for every JavaScript file in that directory, register that file itself that you find as a function, as a task that's available. At that point, you can start to, you don't have to register everything explicitly. You can let recursion happen and let it register all its own tasks. Then we can say, but register a task of default. If somebody is in my directory and types grunt, it'll do the build. If somebody runs grunt build, it'll do a clean build, a JS hint, it'll run my mock a unit test and it'll copy the build across for packaging. If somebody just wants to run mock a, what our mock a test are actually doing here is it's using an in-memory database. It's actually filling the database with known data and running acceptance test against that data. It will clear the database down and refill it. If you want to retest your code, you wouldn't want the process to start again. The last one is, if you're just in development mode, you can just run JS hint and mock a. Let's have a look. Everybody read the screen? Awesome. Grunt, simple grunt, it's gone off and it's done everything. What it's done is it's JS hinted everything and it's filled my database and it's run all my acceptance tests against the database. We have a read me that basically says you need to do a brew install of Mongo, have that running and then this interacts with Mongo in the background. At the end, it comes back and says 100 tests have passed and 121 milliseconds. We've copied the build. If I do grunt dev, we just do a JS hint and we clear the database. I can't connect to it at the minute. At that point, we can run different pieces of the system. Andy wrote a blog post. His blog post was grunt your deployments too. We were like, why do we get things built by grunt and then deployed by another system? Why can't we just get grunt to deploy our system for us? He registered a task called deploy. Deploy called a list of other tasks. It's gone off and got the artifacts. It took the app offline. It stops the application. It makes the release directory. It updates all the new sim links for the new deployment. We do an SFTP deploy. We do an NPM update. We set some configuration. We start. We wait for the application to start. We run our warm-up scripts. We verify. We put it back online and we have clean up afterwards. This is a much better pipeline straight away. It's much more explicit about exactly the tasks that it does. We're not hiding this away in Team City. This is not a slating of build tools by any way. They can just be misused in a very big way. But we have the same task locally that we can run against a test database or a test acceptance site that Team City would run in our CI environment or our pre-prod environment or our production environment. Why it looks in Team City is this. For build, we have a Team City step that says grunt. The grunt task is build. We're not hiding anything away. It's as simple as it possibly gets. There's no extra configuration parameters. What we like to use our CI tool as is just somewhere to orchestrate a job. Everything else must be encapsulated. We can go and we can have a look at the deploy step. There we go. The task is just deploy API. Again, all the logic is held inside the grunt file. There was no hidden surprises when a developer decided to run a command locally that didn't happen in production. If we have a look at some of the contents of those. We have an artifact task. We have a clean. We have a clear DB. We have get artifacts. We have HTTP. If we look at HTTP, it's just going off and just running service status pages. We have a page on our internal systems that's like service status just to make sure that the application is running. Our internal applications only. Don't go and beat us on our website. I'll note to you. We just make sure we can actually warm it up and we collect any errors if it returns an incorrect response code. It doesn't do anything too bad at all. If we have a look at something like JS, JS hint, we're basically just running a simple JS hint across all JavaScript files in the solution. Others who are good at code were actually starting to use code in their build system and in their scripting system. These are not complex scripts. Those seven lines right there, that's all available open source. You Google how to JS hint with grunt. That's almost the first result you'll get. Don't try it. Maybe it's not the first result. The point here is is that why reinvent the wheel? We had a second chance at creating a good build system, a good deploy system, and we could use that. We could use that second chance in order to make it better. We could be a lot more interested in things. Then Andy was like, okay, so we do our builds and we do our deploys. How can we run our acceptance tests? We don't want every developer to have a copy of these five systems on their machine. We don't want to be running our tests against Mac OS X when we deploy into a boot and production. What do we do? He hooked into a tool called vagrant. We have another task called grunt acceptance. What grunt acceptance does is at this point, it does a vagrant up, actually spins up a physical machine using vagrant, sorry, a VM on my physical machine using vagrant. It will run some tests against that VM and it will destroy it. If I'm in the directory, I can say grunt acceptance and it's running the vagrant up task. It goes off and it clones a VM and a boot to VM box from another repository inside my machine. It will install Mongo, it will install engine X, it will install MPM and node and all these bits and pieces and it will run all my tests against them. It takes like 10 minutes to run. Before a developer checks in some code, they take 10 minutes to go grunt acceptance, this works against a known operating system. That was huge, absolutely massive. He wrote a blog post about this called grunt your acceptance too. What we're trying to show is that we're not doing anything. We took this opportunity when we had a new app and we were like, right, what does our app need to do? We continually added new pieces to the pipeline when we needed them. The main thing, I'm just going to kill that because I don't want that spinning up, the main thing is that the build files themselves were packaged with the app. When a developer checked out the code from GitHub, they had not only the actual application code itself but they also had the build code. It meant that everything could be done on the same checkout. Developer could test everything locally. They had the vagrant file that they could test everything with. They used Redis now in there as well. We're really starting to move forward. Any questions? Awesome. Anybody just want me to shut up so we can go for lunch? We're almost there, I promise. This was for a Node.js app. Can the scripts be reused? Yes. Yes. We're reused. Yes and no. I said before that we didn't want these to be reused. We fell into the trap before having central scripts. We did not want to fall into that same trap. If another team who wanted to build and package things with Node.js app in the same way wanted to use the scripts, they would have to go and clone our repository and they would have to see what we're doing with it. That's a good thing and a bad thing because sometimes it creates silos and sometimes it creates a non-similar way of doing things at all times. But in an organization of 150 engineers, you're never all going to be doing things in the same way, especially if you have lots of languages and you're doing cross-platform development work. But there were pieces of the puzzle that could be reused. Things like pushing the artifact, clearing down a database, getting things from artifact, HTTP warm-up scripts. All of these are actually reusable scripts. If we really wanted to, we could create an NPM repository inside our company and then the engineers could go NPM install OpenTable HTTP and that would bring those down. But we're not at that point. In fact, what I can show you now is, speaking about cross-platform, this promoted offer application is actually a C-sharp application. In here, we have a grunt file right there. We have a build folder right there. If we go into the build folder, we can see that we've got some other things in here. We've got N unit. Dammit. Thank you. We have N unit. We have SQL. We have other pieces of the puzzle in there. As I said, this is a C-sharp app. If we go inside our grunt tasks, we can say here that we have build SQL. This goes off and this will build a change set from SQL server and it will store that with the build artifact. Then we have SQL command.js. We have package GitHub data, hip chat notifier, get last pin build number from Team City. This is another app that's gone through a transformation. New pieces of the pipeline were put in place because it was a more complex app to build. It wasn't just a C-sharp app. There's another one, feature dashboard, which is an MVC app that builds a mono. If it builds a mono, I can build it on my local machine using Mac. Let's do that. Then we have grunt tasks for that. We've won at the bottom called xBuild because we want to execute xBuild itself rather than MSBuild. All I have to do as a developer, if I just do grunt build, it cleans the build first. It realizes it's actually doing a C-sharp build. We're in a situation now where our packaging and our builds are in the same state locally as they are in our environment. I'm the same for deploy. If I really wanted to, right here, I could run a grunt deploy and pass in some environment data and it would go off and it would connect to those environments and do the deploy for me. It would just take a little longer because I'm going across the VPN to San Francisco. We can run any of these scripts at all times. This was a very key thing for us. Are there alternatives? It's really good to see some people here from ScriptCS because I actually put ScriptCS in there. Let's see. Thank you. I told Justin that I would put it in there. It is actually an alternative. He's going to take a picture of it because I troll these guys all the time. They're awesome about being trolled, which is really funny. ScriptCS is actually there. You can script stuff on there. I'm sorry, Adam. I should have put your tool on here as well. You've got one called Bow. Is it Bow, you pronounce it? The new hotness right now is Gulp. Anybody using Gulp? Anybody know what Gulp is? It's another JavaScript. They claim to be a streaming JavaScript framework, build framework. There's always alternatives out there. This is not saying you must go and use grunt. Grunt may not fit what you're doing. It may not. There's Gradle. If you're in the Java word, you can go and rewrite stuff in Gradle. You can continue to use PowerShell. Just be very good at what you do with it. Or you can use Make. Does anybody use Make still? Hadi Hariri wrote a blog post on basically cluttering the ecosystem with systems that are written as alternatives to Make. Why don't we just stick with Make itself? A lot of people are starting to begin to feel like that again. Scripting frameworks are the new JavaScript frameworks. If you really want to, you can go and create one in a very simple amount of time. It would be very immature and it probably wouldn't do an awful lot, but you can do it. You can write one from scratch. Why reinvent the wheel though, right? If somebody's already written quite a successful one, there's no point in rewriting the wheel. There's really no point. Do I think that PowerShell is bad for scripting? 100% not. We've come from a company where one or two people were responsible for the build script. It was like me and one other person cared. When that was the case and everyone was doing things in exactly the same way, building the same style applications in the same language, it worked fantastically. As soon as you moved away from central manage, as soon as teams were given autonomy and teams were able to go off and do bits and pieces in their own fashion, then there were variations very quickly appeared into the system. What we had is a per design choice. Centrally managed build scripts are not a good thing. Does anybody have centrally managed build scripts? They're tough. They're really tough and they can break an awful lot. We also don't write applications solely in ASP.NET or ASP.NET anymore. PowerShell for node apps, you can do it, but just because you can do it, it doesn't mean we should, right? The future for us is we just don't know. We don't know what type of apps we're going to be building next. Maybe there's a new app that we have to build next week and we'll use Gulp for it. Maybe there's a new C sharp app and we'll use script CS for it. I'm just joking. The point here is that there's so much resources available out there. We can go and we can have a look at the Grunt plug-ins website. Everybody see that? You've got Contrib, you've got Watch, Ugly Fly, Concat, CSS, Min, Less, Karma, Coffee, Compass. They're all out there. Some of these have been downloaded a huge amount of times, 400,000 times nearly for JS Hint. Anything with Contrib in front means it's a core package maintained by the Grunt team. If it doesn't have Contrib in front, then it's actually outside of Grunt themselves. This comes with its own problems, right? If I go and I say NPM install, it goes off and it downloads the word. It goes off and it downloads the word. If you depend on those external packages, people do make breaking changes to them. Be wary. If you do go and use an open source tool like this in order to build stuff, there are changes that happen all the time. Sometimes that's okay. Just be wary. Be yard full about that's the case. Let's just cancel that. I have probably 20 minutes left. We're definitely not going to take 20 minutes. We're going to take five and then I'll take a couple of minutes for questions and we can run and get in the lunch queue first. I have some tips. The tips here are think about, be mindful about what might happen in the future. You may change completely what you're doing. Don't throw all your resource at creating these amazing build scripts. Have good build scripts and reliable build scripts, but evolve them over time. As your application grows and your company needs change and your team size grows, evolve your build scripts to evolve with the application itself. 100% do not centrally manage your build scripts. I can't stress this enough. I've been bitten by this where I've had people calling me at midnight saying the builds don't work. What do you mean it doesn't work? It doesn't build. What did you do to it? I added this new parameter. We would just have this never ending list of problems. I would get in in the morning and I'll change something before I go home and the San Francisco team are blocked because I've broken their part of the build scripts. I didn't know what they were using it for. Centrally managed is tough. It's really tough. Get lots of feedback. These build scripts, is anybody not using a continuous integration tool? Who uses Team City Jenkins, bamboo? Cool. If you're not using a continuous integration tool, get a continuous integration tool. Even TFS. Just listen. If you're using a tool, that's a good thing. We'll talk about the tool in another time, but that's something different. Use Team City. There we go. Just make it simple. Make your script simple that the way that it executes inside your continuous integration tool happens on your developer machine and Jeff's developer machine. They have to be consistent. The last one is have empathy for your other developers. Don't just go and make lots of changes and not tell anyone because that makes you look like a douchebag. When you have to get phoned because you've changed their build scripts, you're the one that has to suffer. You're the one that has to apologize to the team for stopping their application at the moment. Does anybody have any questions? You must have questions. You're a CI and CD guy. How do you feel about this? Of sole packaged with your application or centrally managed build scripts? Okay. The more you get into continuous integration and continuous delivery work, the more that you'll see that having a good build system is extremely important. You must be able to rely on it. You really must. Any other questions? Yeah. Saki. Yeah. 100%. That's why I said, depend on the type of organization you're in or what type of application you're in, there are all alternatives. You must use grunt. Grunt is the best. If you need to and you're 100% Microsoft shop but you don't want to use PowerShell, then use script. It's good for that, right? Is it? Is it good? Absolutely. So there you go. Bow is even better, right? This is more of a choose what tool you're comfortable with and choose what tool is simple, okay, but it's very effective in what's getting the job done. If I would, if I was still building C sharp and.NET apps, I would 100% still be using PowerShell because I just, I find it phenomenal. Every time they make a new release of PowerShell, it adds so much more to the language. I don't understand the C sharp building, C sharp thing. Hey, I'm a Ruby developer. I don't understand these things, but go off and try some things. Go off and try some tools. Go and get, if you're a.NET developer, go and try Gradle. There's like 26 chapters of documentation on Gradle. That'll be a fun reading before you go to bed one evening. But there's lots of tools out there. Choose a tool that, get advice. Twitter's a great place of, I have this application to be built. What technology should I build it in? You'll probably get 100 responses saying, gulp, gulp. And then you'll get a load of responses from the C sharp guys going script or PowerShell. But speak to people. Get some insight into how they've evolved their build script and how they've evolved their environment going forward. If anybody wants to send me any rant or tells me I'm wrong, please do. I haven't put my email on there because I'm awful at email. I have a backlog of emails to reply to. So tweet me because I am addicted to Twitter. I'm actually always on Twitter. So challenge me. Tell me why I shouldn't be building something in Grunt. I'll happily, happily have a conversation with people about it. Continuous integration, continuous delivery is something I'm very passionate about. And being able to communicate with other people on their experiences always helps me as well. There's always other people's views on this. I'm not the right, I'm not always right on this. You've quoted. But this is true, right? We all have our own ways of doing things. Let's go and get some lunch. Thanks guys. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.
 Okay, thank you all for coming to my talk. Are you sure you want to be here? Douglas  Crockford speaking, Mark Seaman are speaking. You know, some great speakers out there. Do  you want to really be here? So this is a talk about the journey from Pireshell to Grunt  for our build and deploy. Okay, my name is Paul Stack. I have some contact details on  the screen. If anybody takes offense with what I say or wants to discuss it further, then  please do get in contact with me. I'm an infrastructure engineer for OpenTable. After  the last session, someone said, what does an infrastructure engineer do? I don't know.  I seem to be away from the office an awful lot and I have an amazing team who are building  very cool tools for our infrastructure based around using Puppet for orchestration of changes  to our production systems. I'm a DevOps extremist. Over the past six, seven years, I loved CI.  After CI, I thought there's got to be something else and then I really get into continuous  delivery and in order to understand continuous delivery better, I started looking more in  towards DevOps and getting into the DevOps world and now I just believe that it's the  only way that companies can truly succeed in delivering amazing software in the best  manner. I'm a conference junkie. This is my eighth conference. I feel as though of this  year, it's only June. I feel as though I should go to a support group so that I can go, my  name's Paul. It's been two weeks since my last conference. I enjoy going and meeting  lots of new people. This is a description of where we were, where we got to, and where  we went and where we're at now. We're going to be showing lots of code examples so people  can see them. There's a ton of our code that's already open sourced. You'll actually be able  to see a lot of what we've already written. In the beginning, when I started at OpenTable,  just short of three years ago, we had a custom written build tool. It was a proprietary piece  of software that was a little console application that required to be installed onto a build  server. It was written in C sharp and SP.net. Two, it's probably not the best thing if we  look at it now for a build tool. Back then, it was really good because it was interacting  with our Git or SVN repository back then. Who still uses SVN? It was interacting with  our SVN repository and being able to pull tags and it was being able to create tags  for us and so on. It was extremely versatile because it took care of things like our own  internal web config transformation. Our main website has got nine different variants of  it, different languages across the world. This little tool managed to swap all the different  web config pieces into the right place when it required. It was actually very good. It  became extremely difficult to maintain. What we did is we had a build server, one build  server. On that build server was this console application. Also, on that build server was  Visual Studio. It became very difficult to maintain. We thought, let's start moving away  from that. This was a central agent for all the builds across our web platform. This was  quite a big deal. We had a lot of builds going on. When that server went down, that agent,  we were in real trouble. We had the rise of PowerShell. I'm a huge fan of PowerShell.  I always have been a huge fan of PowerShell. If people can understand what I'm actually  saying, that's Microsoft PowerShell. It's just my silly accent. Over the next couple  of months after I joined the company, my team really, we became responsible for building  a new web application. The application was ASP.NET MVC app. The old tool didn't build  that app. That's when we realized that things had to change. We needed to create new scripts.  I had just come from a previous company that I had just gone and implemented an entire  new build system. Actually, an MS build. Looking back, I don't know why I'd ever choose MS  build. I guess any MS build developers, anybody like MS build? By need. Who likes the brackets?  Everyone loves a bracket. I started to realize how amazing PowerShell was and how versatile  it was for Windows infrastructure. On top of PowerShell, there is a DSL, the main specific  language called Saki. It is not pronounced P-sake as everybody that I meet does. It's  a silent P. It's got a very similar style to rake. You describe things in tasks. The  best thing about it is it avoids the angle bracket tax of MS build. Does anybody know  Saki? I know a couple over there do. It's a pretty awesome tool. It was originally written  by a guy called James Kovacs as a version 1.0. Then it was re-released by George Matos  as a version 2. As I said, I was creating things in MS build for a long time. I spent  many sleepless nights trying to work out why my build scripts didn't work. It was because  of brackets. Brackets and escaping of characters. DSLs are a lot easier to use and they are  a little bit more fluid. They just make things a little bit better. Why Saki and not rake?  I'm a reformed Microsoft fanboy. I used to be a huge fanboy and it was all about Microsoft  tools for me. Because of that, I hated. I detested Ruby. I write Ruby on a regular basis  now. I'm like changed completely. PowerShell had to be the way forward. If it was an MS  build, and it had to be Microsoft, it had to be PowerShell. I know somebody in the crowd  has written their own build script tool. This was going back like three years ago. I didn't  know many other tools existed then. With all the power that PowerShell actually brings  it, this is extremely versatile at what it can do for builds and deploys. PowerShell  is a remote for your deployments. You can start jobs, you can set process weights, et  cetera, on your build. It becomes really good. The script, look, that follows. We have a  repository. The last time somebody is actually maintaining this. Originally, it was created  two years ago. We did all sorts of cool stuff, but our build script effectively looked like  this. We passed in some properties. We had some configuration, which was like the type  of configuration, so if it's debug or release or so on and so forth. Solution directories,  solution names, project names, whether it's actually, whether it's going to be packaged  or published or whether this is a part build, the build number. It just started to grow  exponentially. If you look at the git blame of this file, you'll see that probably five  or six different people have been touching pieces of it and breaking everything. We'll  discuss why that's the problem later. It was really easy. We had a task default, which  depends on build, unit test, and acceptance tests. The build basically said run MS build.  We had a wrapper's file, which I'll actually show you the wrappers. The wrappers is where  all the nastiness is. There we go. Run MS build. Again, this has got horrendous over time.  We would switch based on configuration. Because you're inside PowerShell and you can connect  to all the pieces of the system, we could just use exec MS build. We could actually trigger  from PowerShell and MS build script. Then you pass in all the parameters and then we  actually use the output parameters to Team City to tell us when the build was ready and  so on. But we'll come back to that later. After it finished the build, it would then  go through a series of steps based on the crap that people added to the script. I say  that in the lightest, hardest, the light hardest sense of the word crap. It just so happened  that these scripts other people wanted to use. I made the biggest cardinal mistake.  I made these a separate repository of their own. They were not part of my application.  So therefore anybody in the company who wanted to could go and change those scripts. That  was my worst mistake. We'll discuss why that was a bad mistake. Then at the end, if it  was a, if you want to package it, it would go off and package the build. It would do  some other DLLs and it would check some of the package. We want to make sure that the  package that, when we package that up for the first time, we want to record a checksum  and then when we deploy, we used to actually check that that checksum was the same because  we're a SOX controlled company and you have to prove that what you built and test is exactly  what is released. I don't know. Then we ran some unit tests. We had another wrapper called  run unit tests. Maybe not. They're in there somewhere. We just basically passed in some  configuration values of where the end unit exe is because we used to use end unit and  we would pass in the directory that you would run tests against. Then we actually just passed  in a couple of extra parameters where we said unit test result.xml. We want to get the result  back so that we can feed that into Team City. Then we passed in the type of test, unit test.  Looking back, that can 100% be refactored to the same method, just pass in having a wrapper  and pass the types in rather than copying and pasting. We wanted to separate the fact  that there were unit tests and there were acceptance tests and we wanted people to see  that. We wanted to see that there was a distinct difference. The build script in itself was  extremely simple. That's what Pyrochill gave us. The Saki notation gave us that simplicity.  When it came to deployments, it became even more simple. We originally just started deploying  this in a very small scale. We would just basically say get the site directory, get  the package directory, the deploy folder. You would just change some, this is just like  configuration, swap in the correct configuration into place. Then we would just copy the folder  across the network share onto the server and then we would remove all the temporary  deploy and then we would actually just do an IS reset. We would swap the system into  place. As soon as we had swapped into place, we'd done an IS reset and then cleaned up.  That is not a good deployment plan. It's really not a good deployment plan. That was like  a V1 and that one was added two years ago. Then we started to get a little bit more involved  with deployment. We had pre-deployment. We had set in load balancer statuses. We had  warm-ups. We had going off and getting our artifacts. A pre-deployment was, see, we started  to become much more professional with our Pyrochill scripts right here. Passing in and  help messages so that people could see what they needed to pass in. It was go off to get  your system from Artifactory. We use Artifactory for our packages. When you get, let me just  go to the bottom, deploy site. Deploy site would basically say for each server in the  list, because we could pass in a common delimited string of servers, for each one in the list,  go off, get the files, extract the files to the server. Does that make sense? Really simple.  We're not doing anything bad. After deploy site, we would then call the deploy configuration,  which would go off and it would swap in the correct configuration based on if it was production  and America or production in Japan. It would go and get the correct configuration values  and put those in place as well. That was our pre-deployment. Then we would take the server  off the load balancer. We would go off and we would interact with SQL server to take  our server completely out of the load balancer. When it went off the load balancer and we  got a good X-acode, a zero X-acode that it's worked, we would then do the final step, which  would be the actual deployment in itself. All we did was call final deploy.ps1, which  effectively swapped the server, swapped the folder systems around. We would take the old  one, we would rename it to be old or backup or temp, and we would take the new one and  rename it to be the actual folder itself. We would do an IS reset on that. Again, that  is not a good deployment plan. This is going back like two years ago. We were very much  as a company at the beginning of our continuous integration and continuous delivery start.  It's something that takes an awful long time to implement because each environment has  got its own different way of doing things, and each environment has its own stakeholders  that you have to consult in order to build that pipeline. This was the first phase of  it. We actually moved from a company that did manual deploys of these packages that  this old C-sharp application created across and started now having a real sort of a pipeline.  I call it a sort of a pipeline. Anybody any questions on those scripts? Does anybody want  those scripts? You want them? We were 100% Microsoft, so that is exactly why there was  no need for anything else. It was MS build and PowerShell or nothing. That was okay.  We hired ASP.NET developers. Our developers all had core C-sharp knowledge. We didn't  have anybody inside the company who was really pushing the bounds of other languages anyway.  But yes, it was on cross-platform in any way, shape, or form. If you do want these scripts,  let me know. You can have them. I won't even charge you for them. We could do all other  sorts of things in here. If I show you some of our warm-up scripts, sending requests across,  making sure that a get request returns a 200, and that the application warms itself up as  part of the deployment. Our pipeline actually became quite good, and it looked something  similar to... Sorry, that's the wrong one. We would pre-deploy the site, and then we  would deploy the site. Based on parameters that we passed in, we could then say, and  also warm the site up. Run that part of the script as well.  Very quickly, because of so many people... There we go. Because of so many people touching  this, let's go back to the actual slides. The scripts look okay. Fundamentally, there's  nothing wrong with them. It's probably not the best way of doing it. As I said, people  started to adapt them. One person would go, but my app needs to do this. Let's add a little  if statement in there. If it's my app, then I'll do it this way. My app has this build  configuration parameter. Let's add that into the case statement. All solid principles are  going out the window right there. Very quickly, we get into a massive spaghetti mess, huge  spaghetti mess. We ended up with a build in our system that takes 17 build parameters.  Out of all sorts of rubbish going in there. We'd have deploy directories. We'd have branches  because people were using branches for their things. You'd have project names. You'd have  some package locations, some artifact. You'd have some hard-coded IPs. You'd have whether  it's a service or a web app, it just became an absolute maintenance nightmare. But rewrites  completely suck. Anybody been involved in a software rewrite? Has it been fun? Have  you wanted to pull your teeth out? Yeah, they're not fun. They're really, really not fun. I'd  already written one set of build scripts. Why was I going to put us through writing  another set of build scripts? Do we really want another? Then we had a bit of a revolution  in the company. We were no longer a Microsoft house. We were actually able to start writing  applications in other languages. In the summer of 2013, we had an engineer joined us called  Andy Royal. Luckily, I managed to get him on loan to my team for the first couple of  months. We had just started to write a Node.js app. Somebody told me I could write a new  application. I was going to choose a new language. I was unleashed. Andy wanted to learn grunt.  Andy then decided why don't we start writing the build system in grunt? It's a new shiny  thing. This was a year ago. None of the other ones had really come out yet. We'll look at  some of the other ones a bit later. For anybody who doesn't know, grunt is a JavaScript-based  task runner. You register tasks and then you can call those tasks in place. It's got a  massive community ecosystem. When I rewrote the talk this morning, there were 2,954 grunt  plugins available. There's new ones appearing every day. Now, you go and search for a screenshot  or share or something like that. You'll probably get 20 variations of different packages, but  there's a huge community present. Of course, grunt works really well with Node. You do  NPM install grunt and you'll actually be able to start interacting with your Node application  from it. What do the scripts look like? Right. Everything has a grunt file. We'll skip that  top part. That's not really relevant. We go off and we go to a directory and we can say,  for every JavaScript file in that directory, register that file itself that you find as  a function, as a task that's available. At that point, you can start to, you don't have  to register everything explicitly. You can let recursion happen and let it register all  its own tasks. Then we can say, but register a task of default. If somebody is in my directory  and types grunt, it'll do the build. If somebody runs grunt build, it'll do a clean build,  a JS hint, it'll run my mock a unit test and it'll copy the build across for packaging.  If somebody just wants to run mock a, what our mock a test are actually doing here is  it's using an in-memory database. It's actually filling the database with known data and running  acceptance test against that data. It will clear the database down and refill it. If  you want to retest your code, you wouldn't want the process to start again. The last  one is, if you're just in development mode, you can just run JS hint and mock a. Let's  have a look. Everybody read the screen? Awesome. Grunt, simple grunt, it's gone off and it's  done everything. What it's done is it's JS hinted everything and it's filled my database  and it's run all my acceptance tests against the database. We have a read me that basically  says you need to do a brew install of Mongo, have that running and then this interacts  with Mongo in the background. At the end, it comes back and says 100 tests have passed  and 121 milliseconds. We've copied the build. If I do grunt dev, we just do a JS hint and  we clear the database. I can't connect to it at the minute. At that point, we can run  different pieces of the system. Andy wrote a blog post. His blog post was grunt your  deployments too. We were like, why do we get things built by grunt and then deployed by  another system? Why can't we just get grunt to deploy our system for us? He registered  a task called deploy. Deploy called a list of other tasks. It's gone off and got the  artifacts. It took the app offline. It stops the application. It makes the release directory.  It updates all the new sim links for the new deployment. We do an SFTP deploy. We do an  NPM update. We set some configuration. We start. We wait for the application to start.  We run our warm-up scripts. We verify. We put it back online and we have clean up afterwards.  This is a much better pipeline straight away. It's much more explicit about exactly the  tasks that it does. We're not hiding this away in Team City. This is not a slating of  build tools by any way. They can just be misused in a very big way. But we have the same task  locally that we can run against a test database or a test acceptance site that Team City would  run in our CI environment or our pre-prod environment or our production environment.  Why it looks in Team City is this. For build, we have a Team City step that says grunt.  The grunt task is build. We're not hiding anything away. It's as simple as it possibly  gets. There's no extra configuration parameters. What we like to use our CI tool as is just  somewhere to orchestrate a job. Everything else must be encapsulated. We can go and  we can have a look at the deploy step. There we go. The task is just deploy API. Again,  all the logic is held inside the grunt file. There was no hidden surprises when a developer  decided to run a command locally that didn't happen in production. If we have a look at  some of the contents of those. We have an artifact task. We have a clean. We have a  clear DB. We have get artifacts. We have HTTP. If we look at HTTP, it's just going off and  just running service status pages. We have a page on our internal systems that's like  service status just to make sure that the application is running. Our internal applications  only. Don't go and beat us on our website. I'll note to you. We just make sure we can  actually warm it up and we collect any errors if it returns an incorrect response code. It  doesn't do anything too bad at all. If we have a look at something like JS, JS hint,  we're basically just running a simple JS hint across all JavaScript files in the solution.  Others who are good at code were actually starting to use code in their build system  and in their scripting system. These are not complex scripts. Those seven lines right there,  that's all available open source. You Google how to JS hint with grunt. That's almost the  first result you'll get. Don't try it. Maybe it's not the first result. The point here is  is that why reinvent the wheel? We had a second chance at creating a good build system, a  good deploy system, and we could use that. We could use that second chance in order to  make it better. We could be a lot more interested in things. Then Andy was like, okay, so we  do our builds and we do our deploys. How can we run our acceptance tests? We don't want  every developer to have a copy of these five systems on their machine. We don't want to  be running our tests against Mac OS X when we deploy into a boot and production. What  do we do? He hooked into a tool called vagrant. We have another task called grunt acceptance.  What grunt acceptance does is at this point, it does a vagrant up, actually spins up a  physical machine using vagrant, sorry, a VM on my physical machine using vagrant. It  will run some tests against that VM and it will destroy it. If I'm in the directory,  I can say grunt acceptance and it's running the vagrant up task. It goes off and it clones  a VM and a boot to VM box from another repository inside my machine. It will install Mongo,  it will install engine X, it will install MPM and node and all these bits and pieces  and it will run all my tests against them. It takes like 10 minutes to run. Before a developer  checks in some code, they take 10 minutes to go grunt acceptance, this works against  a known operating system. That was huge, absolutely massive. He wrote a blog post about this called  grunt your acceptance too. What we're trying to show is that we're not doing anything.  We took this opportunity when we had a new app and we were like, right, what does our  app need to do? We continually added new pieces to the pipeline when we needed them. The main  thing, I'm just going to kill that because I don't want that spinning up, the main thing  is that the build files themselves were packaged with the app. When a developer checked out  the code from GitHub, they had not only the actual application code itself but they also  had the build code. It meant that everything could be done on the same checkout. Developer  could test everything locally. They had the vagrant file that they could test everything  with. They used Redis now in there as well. We're really starting to move forward. Any  questions? Awesome. Anybody just want me to shut up so we can go for lunch? We're almost  there, I promise. This was for a Node.js app. Can the scripts be reused? Yes. Yes. We're  reused. Yes and no. I said before that we didn't want these to be reused. We fell into  the trap before having central scripts. We did not want to fall into that same trap.  If another team who wanted to build and package things with Node.js app in the same way wanted  to use the scripts, they would have to go and clone our repository and they would have  to see what we're doing with it. That's a good thing and a bad thing because sometimes  it creates silos and sometimes it creates a non-similar way of doing things at all times.  But in an organization of 150 engineers, you're never all going to be doing things in the  same way, especially if you have lots of languages and you're doing cross-platform development  work. But there were pieces of the puzzle that could be reused. Things like pushing  the artifact, clearing down a database, getting things from artifact, HTTP warm-up scripts.  All of these are actually reusable scripts. If we really wanted to, we could create an  NPM repository inside our company and then the engineers could go NPM install OpenTable  HTTP and that would bring those down. But we're not at that point. In fact, what I can  show you now is, speaking about cross-platform, this promoted offer application is actually  a C-sharp application. In here, we have a grunt file right there. We have a build folder  right there. If we go into the build folder, we can see that we've got some other things  in here. We've got N unit. Dammit. Thank you. We have N unit. We have SQL. We have other  pieces of the puzzle in there. As I said, this is a C-sharp app. If we go inside our  grunt tasks, we can say here that we have build SQL. This goes off and this will build  a change set from SQL server and it will store that with the build artifact. Then we have  SQL command.js. We have package GitHub data, hip chat notifier, get last pin build number  from Team City. This is another app that's gone through a transformation. New pieces  of the pipeline were put in place because it was a more complex app to build. It wasn't  just a C-sharp app. There's another one, feature dashboard, which is an MVC app that  builds a mono. If it builds a mono, I can build it on my local machine using Mac. Let's  do that. Then we have grunt tasks for that. We've won at the bottom called xBuild because  we want to execute xBuild itself rather than MSBuild. All I have to do as a developer,  if I just do grunt build, it cleans the build first. It realizes it's actually doing a C-sharp  build. We're in a situation now where our packaging and our builds are in the same state  locally as they are in our environment. I'm the same for deploy. If I really wanted to,  right here, I could run a grunt deploy and pass in some environment data and it would  go off and it would connect to those environments and do the deploy for me. It would just take  a little longer because I'm going across the VPN to San Francisco. We can run any of these  scripts at all times. This was a very key thing for us. Are there alternatives? It's  really good to see some people here from ScriptCS because I actually put ScriptCS in there.  Let's see. Thank you. I told Justin that I would put it in there. It is actually an  alternative. He's going to take a picture of it because I troll these guys all the time.  They're awesome about being trolled, which is really funny. ScriptCS is actually there.  You can script stuff on there. I'm sorry, Adam. I should have put your tool on here as  well. You've got one called Bow. Is it Bow, you pronounce it? The new hotness right now  is Gulp. Anybody using Gulp? Anybody know what Gulp is? It's another JavaScript. They  claim to be a streaming JavaScript framework, build framework. There's always alternatives  out there. This is not saying you must go and use grunt. Grunt may not fit what you're  doing. It may not. There's Gradle. If you're in the Java word, you can go and rewrite stuff  in Gradle. You can continue to use PowerShell. Just be very good at what you do with it.  Or you can use Make. Does anybody use Make still?  Hadi Hariri wrote a blog post on basically cluttering the ecosystem with systems that  are written as alternatives to Make. Why don't we just stick with Make itself? A lot of people  are starting to begin to feel like that again. Scripting frameworks are the new JavaScript  frameworks. If you really want to, you can go and create one in a very simple amount  of time. It would be very immature and it probably wouldn't do an awful lot, but you  can do it. You can write one from scratch. Why reinvent the wheel though, right? If somebody's  already written quite a successful one, there's no point in rewriting the wheel. There's really  no point. Do I think that PowerShell is bad for scripting? 100% not. We've come from a  company where one or two people were responsible for the build script. It was like me and one  other person cared. When that was the case and everyone was doing things in exactly the  same way, building the same style applications in the same language, it worked fantastically.  As soon as you moved away from central manage, as soon as teams were given autonomy and teams  were able to go off and do bits and pieces in their own fashion, then there were variations  very quickly appeared into the system. What we had is a per design choice. Centrally managed  build scripts are not a good thing. Does anybody have centrally managed build scripts?  They're tough. They're really tough and they can break an awful lot. We also don't write  applications solely in ASP.NET or ASP.NET anymore. PowerShell for node apps, you can do it, but  just because you can do it, it doesn't mean we should, right?  The future for us is we just don't know. We don't know what type of apps we're going  to be building next. Maybe there's a new app that we have to build next week and we'll  use Gulp for it. Maybe there's a new C sharp app and we'll use script CS for it. I'm just  joking. The point here is that there's so much resources available out there. We can  go and we can have a look at the Grunt plug-ins website. Everybody see that? You've got Contrib,  you've got Watch, Ugly Fly, Concat, CSS, Min, Less, Karma, Coffee, Compass. They're all out  there. Some of these have been downloaded a huge amount of times, 400,000 times nearly  for JS Hint. Anything with Contrib in front means it's a core package maintained by the  Grunt team. If it doesn't have Contrib in front, then it's actually outside of Grunt  themselves. This comes with its own problems, right? If I go and I say NPM install, it goes  off and it downloads the word. It goes off and it downloads the word. If you depend on  those external packages, people do make breaking changes to them. Be wary. If you do go and  use an open source tool like this in order to build stuff, there are changes that happen  all the time. Sometimes that's okay. Just be wary. Be yard full about that's the case.  Let's just cancel that. I have probably 20 minutes left. We're definitely not going to  take 20 minutes. We're going to take five and then I'll take a couple of minutes for  questions and we can run and get in the lunch queue first.  I have some tips. The tips here are think about, be mindful about what might happen in the  future. You may change completely what you're doing. Don't throw all your resource at creating  these amazing build scripts. Have good build scripts and reliable build scripts, but evolve  them over time. As your application grows and your company needs change and your team  size grows, evolve your build scripts to evolve with the application itself. 100% do not centrally  manage your build scripts. I can't stress this enough. I've been bitten by this where  I've had people calling me at midnight saying the builds don't work. What do you mean it  doesn't work? It doesn't build. What did you do to it? I added this new parameter. We would  just have this never ending list of problems. I would get in in the morning and I'll change  something before I go home and the San Francisco team are blocked because I've broken their  part of the build scripts. I didn't know what they were using it for. Centrally managed  is tough. It's really tough. Get lots of feedback. These build scripts, is anybody not using  a continuous integration tool? Who uses Team City Jenkins, bamboo? Cool. If you're not  using a continuous integration tool, get a continuous integration tool. Even TFS. Just  listen. If you're using a tool, that's a good thing. We'll talk about the tool in another  time, but that's something different. Use Team City. There we go. Just make it simple.  Make your script simple that the way that it executes inside your continuous integration  tool happens on your developer machine and Jeff's developer machine. They have to be  consistent. The last one is have empathy for your other developers. Don't just go and make  lots of changes and not tell anyone because that makes you look like a douchebag. When  you have to get phoned because you've changed their build scripts, you're the one that has  to suffer. You're the one that has to apologize to the team for stopping their application  at the moment. Does anybody have any questions? You must have questions. You're a CI and CD  guy. How do you feel about this? Of sole packaged with your application or centrally managed  build scripts? Okay. The more you get into continuous integration and continuous delivery  work, the more that you'll see that having a good build system is extremely important.  You must be able to rely on it. You really must. Any other questions?  Yeah.  Saki. Yeah.  100%. That's why I said, depend on the type of organization you're in or what type of  application you're in, there are all alternatives. You must use grunt. Grunt is the best. If  you need to and you're 100% Microsoft shop but you don't want to use PowerShell, then  use script. It's good for that, right? Is it? Is it good?  Absolutely.  So there you go. Bow is even better, right? This is more of a choose what tool you're  comfortable with and choose what tool is simple, okay, but it's very effective in what's getting  the job done. If I would, if I was still building C sharp and.NET apps, I would 100% still be  using PowerShell because I just, I find it phenomenal. Every time they make a new release  of PowerShell, it adds so much more to the language.  I don't understand the C sharp building, C sharp thing. Hey, I'm a Ruby developer. I  don't understand these things, but go off and try some things. Go off and try some tools.  Go and get, if you're a.NET developer, go and try Gradle. There's like 26 chapters of  documentation on Gradle. That'll be a fun reading before you go to bed one evening. But there's  lots of tools out there. Choose a tool that, get advice. Twitter's a great place of, I  have this application to be built. What technology should I build it in? You'll probably get  100 responses saying, gulp, gulp. And then you'll get a load of responses from the C  sharp guys going script or PowerShell. But speak to people. Get some insight into how  they've evolved their build script and how they've evolved their environment going forward.  If anybody wants to send me any rant or tells me I'm wrong, please do. I haven't put my  email on there because I'm awful at email. I have a backlog of emails to reply to. So  tweet me because I am addicted to Twitter. I'm actually always on Twitter. So challenge  me. Tell me why I shouldn't be building something in Grunt. I'll happily, happily have a conversation  with people about it. Continuous integration, continuous delivery is something I'm very  passionate about. And being able to communicate with other people on their experiences always  helps me as well. There's always other people's views on this. I'm not the right, I'm not  always right on this. You've quoted. But this is true, right? We all have our own ways of  doing things. Let's go and get some lunch. Thanks guys.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.  Thank you.
Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_0_10907.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_10908_10955.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_10956_11279.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_11280_12623.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_12624_15203.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_15204_15335.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_15336_16991.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_16992_17063.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_17064_17387.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_17388_17591.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_17592_18395.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_18396_18743.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_18744_19919.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_19920_20819.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_20820_23831.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_23832_24827.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_24828_26411.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_26412_26639.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_26640_30179.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_30180_30275.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_30276_31583.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_31584_32999.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_33000_36275.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_36276_36827.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_36828_37727.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_37728_37847.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_37848_38255.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_38256_38567.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_38568_38663.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_38664_38711.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_38712_38987.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_38988_39263.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_39264_39311.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_39312_39383.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_39384_39611.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_39612_39863.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_39864_40115.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_40116_41279.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_41280_41339.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_41340_41699.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_41700_41879.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_41880_43283.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_43284_47051.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_47052_47459.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_47460_47831.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_47832_49691.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_49692_50591.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_50592_53471.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_53472_55331.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_55332_56303.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_56304_56567.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_56568_57323.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_57324_58499.png Paul_Stack_-_The_journey_from_Powershell_to_Grunt_for_Build_and_Deploy_58500_80645.png