Let's take a look at how you could set up a continuous integration ecosystem for microservices. Really just start out with your project, is the most important first step and this is a project structure that we'll go through in a second. But in general, it's the ability to test, to lint, and to format your code every time the human, the developer, that's you, pushes the changes into a Git based repository. This would be Git. In this case, I'm going to show you GitHub. But the real key characteristics here are that there is a makeFile that can do all of these actions. This makeFile corresponds to the lint, it corresponds to the format, it corresponds to this test. I do those locally, but then I can also replicate that by having this robot appear, which is the build server that always is making my project a high-quality, because it's checking for things like the lint of the code, the formatting of the code, the test in the code, and then later when I get to deploy the code. Really this is a key concept. Set up this local continuous integration environment so that your project is ready to go when you want to push that into production. Next, let's go ahead and take a look at how that would work in practice with a GitHub project. Let's take a look at a project structure that is really set up for you to do everything you need to do to do both continuous integration and then later continuous delivery. What are the key components? First up in this repo noahgift/continuous-integration, we have a GitHub workflows section. This is where the built system, in this case it will be GitHub actions, but it could be things like Jenkins or AWS code build or some other build system, it will go through and test my code and do exactly what I tell it to do. In this case, we can look at the commands by going to this main.yaml file. We can see that on every push or every change a human makes, it'll go through and it will spin up in Ubuntu Virtual Machine. It will use Python 3.8. It will do these steps, make install, make lint, and make test, and then later make format. This is a great structure I would recommend for all continuous integration projects, is to have this structure setup. Now, what we can do next here is take a look at the environment for the code itself. That would be a different sub-components of this project. We can see here that there is a README file, always a good idea, have a build system badge. I also have a really basic file here that adds to numbers. I also have a test file that was able to go through here and test our code, and then I also have a requirements file which has versioned packages. This is important so it's reproducible so that I know that the version I tested my Python project with will be reproducible for the build system. Finally, if we go ahead and we take a look at our makeFile itself, you can see that this structure is really a set of recipes. I make install, I make test, I make format, I make lint. That's the structure, but how would I uses in the real world? We can take a cloud-based development environment here, which is GitHub codespaces, and we can spin it up and take a look at it. From here, actually go through and exercise the components of the project. It can also see what happens if something fails and how it's easy to detect the failure because of the fact that we have this great scaffolding for our project. We're inside of this GitHub codespaces environment here, and notice that I have a terminal and I have all of the code here on the left, and notice there's a virtual environment that I created. You can create your own by using the virtual environment command, and then putting it in some location. In my situation, I actually edited my bashrc file here and I put in the source command directly into that bashrc file. We cover that in another lesson in the bash section, about how to edit your bashrc. But for now, I'm going to go through here and look at the structure. Again, you see all these files here. I'm going to run make all. When I do make all, we can take a look at this. What does it do? It installs, it lints, it test our code. What's great about all of this, is I get a great feedback loop that says, "Hey, everything works." Now, what happens if there's a problem in the code? In this case, this would be a great little bug, is that if I assign a variable to itself, it doesn't necessarily break our code, but it does cause a potential problem in the future. In this case, look, we can see that there's two different problems. We're assigning a variable to itself, plus I never actually made this variable do anything. I never assigned it. Now, if I change it, we can see that that variable is still got a warning problem. The first one was an exception or an error where the code will not run. The other one is just a warning. In either case, the lint was able to catch this bug. Now, let's go ahead and push this change. Great. Now, I'll go ahead and do a git push, and will push those changes. Perfect. Now, if I go back here and I say open repository or go to repository, we can watch this build system in action. This is the benefit of a continuous integration system, is it a robot that's watching our code? That's one of the best ways to think about it. It's sitting there constantly cleaning up things, looking for installation problems, linting problems, testing problems. It'll fail right here with this lint because we have a bad message. The code is actually had a linting problem. There's an issue. What do we do? Well, fortunately, it's very straightforward. I don't even need to go into my development environment. I can just go to this file right here and I can edit it, and I can say, this was a problem. I don't need these two lines of code. Let's go ahead and fix this and let's have our robot or build server. Go ahead and take a look at this and see if it can fix it. We're waiting for this Build Server to run the job. There we go. It's going to set up the code, install the dependencies. Then finally, now we see that the lint itself has actually gone through, the format, has gone through, everything has gone through. Really this is the processes, it's something that every project should have if you're doing microservice development, command line tool development, really anything in software development in Python. You can see how we can easily test those changes even inside of a GitHub project.