[MUSIC] So if we start to use stages, stages lets us define a stages tag that helps us order the execution of our scripts. So by default, Travis treats this top-level script as the stage called test. So even though its not named internally, Travis has named this as test. So we can say, hey, we want the test stage to run every single time first. And because we used this matrix command here, if we add additional Node versions, all we have to do is uncomment this and this will publish an image for that version of Node as well. The next stage is going to be our npm-targets stage. And remember we had that lent test and coverage phases in the npm run command, well, the npm-targets will be a stage that can do each of those different commands for what we're executing. So lets create our first stage. So jobs, and we're going to include, and then we're going to create our stage. And this stage is going to be called npm-targets. So that means everything below this is going to be grouped into the npm-targets grouping. And we can name these stages, too. So in this particular case, we're going to name this stage, Test the 8-jessie And what we'll do is leave it at that. Okay, and then the install phase doesn't need to run. So you can specify install and say, hey, I'm skipping the install phase. So anything that's defaulted here will get skipped. And then the script phase is where we put the meat of our logic. And here we'll use the docker run command again. And this time, the name of the image that we're using is the one that we published. So let's copy this and paste it right there. And so then the command that we run is npm run. And then we'll use $NPM_TARGET. Now this is different than the matrix operation. We still use the environment variable option here, however, it's now not operating as a matrix operation, it's operating as a single job. And so, for this we're going to use NODE_VERSION. And we're going to make that equal to the version we want to test on, which is, 8-jessie. And we want to make this particular script step, or script job, the target for it, equal to test. Now I don't need any of this anymore, so we're going to get rid of this section. But that gives us a single job, and we actually have two jobs here. The first job is to build the image and the second job is going to be to run the NPM test target. And if we want to run additional jobs that do additional work, then all we simply have to do is add another stage with the same name so that it's grouped into the same grouping. So if we repeat that pattern of npm-targets, And I simply copy and paste this, And I have that exact same command, except this time, instead of doing the target test, we are going to do the target lint. And if I want to do the coverage, I just repeat that command. So I'm going to copy that again and make that coverage. So you notice all I'm doing is editing and I'm repeating this code. Now this is a little bit unfortunate and I'm hoping that Travis improves this over time. But I'm repeating these stages that basically do different targets. But had I have had a matrix operation in the env, under the stage, then I would've been able to max these particular scripts and execute three different targets within one single instantiation of this YAML. Or even at a higher level, but this is how it works for now. And this is how stages work. So that's what we needed to do to cover the Jessie 8 testing. Now what happens if I wanted to do the Jessie 10 testing? Well, I uncomment this, and then I can simply copy all of this and repeat it into the next line. And if I'm careful and go back to the very first line where I started targets, and I change the target from 8-jessie to 10-jessie, then I simply have to do this, 10. I'll make it 10 here. 10 and 10 there. In addition, if I only wanted to run the coverage if this was the master branch, then I could also include an if statement here and say hey, if: branch = master then only run that particular target for 10-jessie. So remember we can introduce conditionals at each one of these different stage commands. So let's save that and let's give it a run. So we have our Dockerfile and the travis.yml file. And we'll do example 4. And then choose the publish branch. So let's go give Travis a look. And we'll go back to More settings > Requests, make sure that it's syntactically correct. So example 4 is checking out, that's great. And we can choose branches, and we'll look at the build and see what we got. All right, great, so look at that. We have the two stages that we expected, the Test stage and the Npm-targets stage. And notice that each of these jobs, they have their own label. Now notice that the 8-jessie job, or 8-jessie label, has three jobs, while the 10-jessie has two jobs. Remember the conditional? The conditional says that if the branches is not equal to the name master, then that job won't run. And that's exactly what we're seeing, that job is not going to run. So what's happening now is that both the 8-jessie label and the 10-jessie label are building Docker images that we're going to use in publish to a Docker registry that's under our account. And so we can see that we've cloned the repository. We have started the build process, passed in the arguments and we're now pulling the 8-jessie image. And you can see the 8-jessie image being pulled here. And it's the 8-jessie image which is going to be used in this particular build to produce this version of our build. Now, I'm going to pause the video there and let this finish the completion, and the we'll look at the job logs once it's done. Okay, this build is finished. Hey, well, this is great. What happened? It looks like the NODE_VERSION=10-jessie failed. If we click on that and we go look at the job log and scroll down to the end, we can see that we're getting the pull. So it's pulling the Node 10 image, and we're seeing that pull happen. And then it's building. Hey, there's an incompatibility in our code with Node version 10. It looks like what we really need to do is fix our code so that it works with Node version 10. Otherwise, we're going to get this build error for Node version 10, and it definitely did use Node version 10 for us. So this is great. We can start seeing that our code isn't exactly portable from one version of Node to the other. Maybe what we really need is use an older version of Node and stick to that for now. So let's go make some of those updates. So if we go to Atom and we change from the 8 image to another image, let's say the 6th Jesse image. So that's Node version 6, a slightly older release. And we update all of our 10s to 6 here, Here, Oops. Okay, so we have the three stages that are doing our build for tests, For lint. And for coverage, all running the 6-jessie image. And then the 8 builds, let's remove the if statement so that we actually run this job as well. And the 8 builds for test. Actually, I still left one, for lint, for test, and for the coverage. So let's save these changes. Go to the GitHub desktop. And commit our changes and push them up. So if we go back to Travis, double check our syntax, we have the update to jessie 6 syntax. And look at the current build, look at that, we're now testing with jessie 6. And we're running the three extra jobs, including the coverage step. So let's let this job finish and look at the logs. Okay, the job finished. This particular build failed as well, except this time we failed the test cases on the 6-jessie image. And if we look at the log files for that, we can tell that the 6-jessie image was also pulled, and it has some errors here for Node 6. And it looks like our particular package is looking for a newer version of Node. So we know that this project won't work with Node 10 and it won't work with Node 6. So this is really great. You can imagine, if you had a software package that only worked with one particular version of Node, and there were security issues or problems that kept you from moving it forward, that you'd want to know in your CI system really quickly if that was going to be a problem for you. Now, this project, I'm not going to try and debug it any further. What's important here is that we learned about stages. We learned about the different jobs that we can create within stages. And we can go from a serial execution to parallel execution within our travis.yml file.