Now that we have a scaffolding setup for our project, let's go to the final step, which is the setup GitHub actions. In here I'm going to select this actions icon. When I select the actions you'll notice that, not only are there some defaults here where you could go through and look at things like deploying node applications, deploying containers, deploying to the Google Cloud and their Kubernetes service. But you also can set it up from scratch. So that's what we're going to do. We're going to set up a default workflow here. You'll notice that it'll give you this YAML format file. So it's called main.yml. It'll say, this is a basic workflow. In a nutshell, the best way to think about this is that you're telling it when you push something to the master branch or the main branch, that it'll do a series of actions and if you've already got a makefile setup, then it really becomes trivial. So that's what I'm going to do. I'm going to use this default and swap it out with a makefile that I've already got set up. So let's go ahead and delete that, and then I'm going to go through here and put a default GitHub actions that I've used in the past year. Let's take a look at some of the parameters. First I say, Python application test with GitHub actions, and on every push or every event that makes a change, I'll go ahead and run this and I'll run it on this particular container, which is the latest version of Ubuntu. I'll also go through here and install Python 3.8. Then after that, I will do the series of steps that I set up earlier. So I'll run and make install. This will install the dependencies. So this actually tests whether I have the correct dependencies in my project. Next, I'll lint the code. So I'll go through and make sure that the syntax of my project is correct. What's beautiful about this is that every single time I make a change, it'll validate that my project works. Then I'll go through and I'll make a test, and then finally, I'll format the code. Let's go ahead and start this. You'll notice that it checks it into this directory.github workflows. The file is called main.yml. You can have as many of these files as you want. What this means is that, for every single file that runs, it will exactly do what you say. For example, if we want to later setup a Google based deployment, we can set that up. If we want to set up an Azure based testing project, we can go ahead and set that up. Now, how did we actually see where it runs? Well, if you go back to actions here and you look at this icon, it'll show you the results of a run that happened. Notice that it says one minute ago, it took about 29 seconds. Let's go ahead and take a look at this. So you can see that it was able to build this and I can look at every single step. So each of those lines and the YAML file, directly corresponds with each one of these lines. First we say set up job, and then it goes through here and it downloads the correct Virtual Environment, which is Ubuntu-18.04. Next, we go through here and we set up Python 3.8. So it goes through here and it installs the CPython version 3.86. I then go through and install it and dependencies. It really is very easy because, I have the makefile setup and all I have to do is say make install. Then I go to the next step which is I go in and I lint the code, and then this goes through here and it says make lint. Then finally, we can go through here and we can finish a test. Great. That's make tests command and then, it'll go through and it'll format the code. All this does is show me if I needed to make a change, I can later look at this output and say, oh, I need to make a change to my file. What we could do next here to add the final finishing touches is if I go to this icon over by the main part of the Build, you'll notice that it says Create status badge. This is always a good idea. If I go through here and I say, copy the status badge markdown, it'll actually allow me to give a badge inside of this Read Me file. So if we go through here and I put this inside, it'll let me see what the output is of every single operation. So if I have made a change, it'll show me whether the change is passing or if it's failing. So this is a really useful aspect of a SaaS based continuous integration system. Let's actually test this out though. So I saw it. We're able to see this working, but let's actually test out what happens when it fails. So, how can we do this? Well, what we could do is go back to our project here and do a get pull to pull the latest changes. Then what I'm going to do is I'm going to go to this hello file here. I'm going to add some bad code. So I'm going to add an empty variable, that's not complete. You'll notice it even says look, there's a problem. So I'm going to go through here and see that if I do a lint, the lint won't work because we know it's got a failure. Just to test it out, I'm going to add this failure, adding failure to test build. Great. Then I'll do a git add here of the hello and then run that line again. Then now do a git push. When I do this push, it'll automatically trigger the GitHub actions build again, and we can click on this icon. Notice that it's in orange here because it's running this again. So it's queued up. I can select it and in fact even look at the logs as they're being run. It'll tell me step-by-step what's happening. It's installing the dependencies. Great. When it gets to the lint, it's going to fail. That looks good. Scroll down here. Scroll down, and once it's done installing, it'll run the next step here, which is, we see that there is an issue, and so won't even go to the final steps. Notice how there is a slash here. It'll tell you that it failed at this step, which is really useful in debugging. If I go through here and I say hello, it'll say that line 4 character 5, there is invalid syntax. So it's actually really helpful in letting me debug the code. So, how do we fix this? Well, let's go back here and just comment this out. I can actually test it locally, make sure it works. Great, it works. Let's go ahead and do a git add of a low again. Then I can say, put a fix here and we'll say, adding fix to build. Then we'll commit this, and then it'll go through and run it again, and then fix this failure. You can see here how this build step really has a lot of value in terms of automatically checking to make sure your project works and then even giving you a verbose output. I think this is probably the biggest takeaway I would say is that, it's one of the most common mistakes that newcomers to Python, newcomers to Data Science, newcomers to programming make is that they don't do this automated testing because they think it's more work or they don't want to get involved with doing something where they don't see the value. But really this is something that just like a Python Virtual Environment, setting up a continuous integration is only going to help you have more high-quality code, go faster, and in fact, this will speed things up. So this is a required best practice for any software project involving Python.