تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Redis Workflow Failure0:00

Well, as often is the case, the needs of our application have outgrown what our current workflow is capable of. You can see that on the latest run we received a Redis exception saying that the connection was refused. And no doubt you already have an idea of what's going on here. Since the last episode in the IDE, we're making use of the Redis facade, just as a page view counter, but that's one perfect use case for Redis. So because there's no Redis service available inside our GitHub workflow, when the Laravel application attempts to connect to Redis to use it, it burns. There's nothing it can do, and we receive the exception.

Using Service Containers0:40

application attempts to connect to Redis to use it, it burns. There's nothing it can do, and we receive the exception. Thankfully, GitHub has a solution for that. It's called a service container, and as the description states, we can use it to connect databases, web services, memory caches. Now what's Redis again? Redis is a memory cache. In fact, if we were to scroll down in the documentation here, they even have an example of setting up the Redis service. So tell you what, let's get this set up in our own application and see if it fixes the

Configuring Redis Service1:10

of setting up the Redis service. So tell you what, let's get this set up in our own application and see if it fixes the problem in our workflow. We define services on the job itself. So between runs on and steps, I'm going to use that services key. Then we define a unique identifier for this service, Redis sounds like a perfect option for this use case, followed by inside that service, the name of the Docker Hub image we want to use. Now if you go to the Docker Hub website, you can search for Redis, and you'll find there's an official Redis image we can make use of, literally is just called Redis, and I'm going

Now if you go to the Docker Hub website, you can search for Redis, and you'll find there's an official Redis image we can make use of, literally is just called Redis, and I'm going to provide a certain tag, a certain version of 7.4 at the time of this recording. So to do that, we'll go back to the IDE, and in image, I'll say Redis:7.4. So that's the image name itself, followed by the tag, the version that we actually want to pull. Now if you've not worked with Docker before, you don't need to panic. You don't need to go and research all about Docker. The bare minimum is necessary to get services working in GitHub Actions. But here's an important note, whenever you run a Docker service like Redis, it's going

The bare minimum is necessary to get services working in GitHub Actions. But here's an important note, whenever you run a Docker service like Redis, it's going to execute inside a little siloed container. We have to tell that container which ports we want access to, and we have to map those ports to local ports inside the GitHub workflow. It's very easy because there's a simple syntax for it in GitHub Actions itself. Underneath the image declaration, I'm going to use the ports property. This is an array of those port mappings, and if you go to .env.example, you'll see that the default port for Redis is 6379. So copy that port, jump back into test.yaml, and we're going to declare that port first.

the default port for Redis is 6379. So copy that port, jump back into test.yaml, and we're going to declare that port first of all. So 6379. Now the first item here is the port we want to expose inside that Docker service, inside the Redis container. Then we use a colon, and we need to say here, where does that port map to? Where does the port go in the local GitHub workflow? Which again, we can map to 6379. So now if our Laravel application attempts to talk to Redis on port 6379, it will be

Which again, we can map to 6379. So now if our Laravel application attempts to talk to Redis on port 6379, it will be rerouted to the Docker container in order to be able to find Redis there. And in fact, we don't need to do anything else with this service. It will just work now. As soon as we start the workflow, Redis will be booted inside Docker, the port mappings will be made available, and any time we try to connect to Redis, it will just use that Docker service. So let's get this pushed up. Let's run the workflow again and make sure it works.

So let's get this pushed up. Let's run the workflow again and make sure it works. You'll see there's a new step inside our workflow for initializing those containers to boot the services, and it did indeed start the Redis service container. Here's it pulling from Docker, downloading, verifying the checksum, and then a little further down, it goes ahead and starts the service. That's what's going on right here. So Redis 7.4 is up and running, and if we go to waiting for all services to be ready, the Redis service is healthy. So that worked.

Diagnosing Database Test Failures4:26

the Redis service is healthy. So that worked. However, if we scroll a little further down, you'll note that our tests still fail. Not as many, and for a different reason. In this case, it says, well, failed asserting that four is identical to three. Let's see if we can figure out what's going on. Here's the failing testing question. It provides users in random paginated order, but when I run this locally, it passes. There's no problems whatsoever. If you watch my recent Larabit on random paginated order, you'll remember that SQLite

There's no problems whatsoever. If you watch my recent Larabit on random paginated order, you'll remember that SQLite doesn't actually support random paginated order, which is important to note because in test.yaml, we're running the tests against an in-memory SQLite database. If I go to my .env file, well, I'm set up running my SQL locally. So that's the discrepancy. That's why it works on my machine, but it's not working in GitHub Actions. We need to set up another service, a MySQL service, so that we can execute against that instead of executing against SQLite. So let's get going.

Adding MySQL Service5:29

instead of executing against SQLite. So let's get going. We'll define a new ID for this second service. MySQL sounds good. The image can be found on Docker Hub. There's an official MySQL image, literally just called MySQL, and why don't we make use of the 8.0 tag, seeing as I think that's what the majority of you will be using. So literally just MySQL:8.0, and we'll define some port mappings. The default port for MySQL is 3306, right? So 3306 in Docker will point to 3306 inside our GitHub Action.

The default port for MySQL is 3306, right? So 3306 in Docker will point to 3306 inside our GitHub Action. Okay. Once we have that defined, we need to add some environment configuration to this service. On the MySQL Docker Hub page, you'll note that there are various environment variables we can pass. So for example, we can pass the name of a MySQL database, which will be created when the image is first booted. We can also say that we don't want to use a password, which is not good for production, but will work perfectly for our testing environment.

We can also say that we don't want to use a password, which is not good for production, but will work perfectly for our testing environment. So let's make use of those two environment variables. We'll start with MySQL database. We'll go back to our yaml file, and under ports, I'm going to pass environment variables, which if you remember, we've already played with earlier on. If we go back to run tests a little further down, this is how we define various environment variables to pass to the step. So let's go back up, and we'll say we want to define MySQL database, and if we go back to .env.example, and let's go up to the database section, yeah, here are the defaults for Laravel,

So let's go back up, and we'll say we want to define MySQL database, and if we go back to .env.example, and let's go up to the database section, yeah, here are the defaults for Laravel, right? I'm going to uncomment that, and I'll change SQLite to MySQL. The DB_HOST is fine. The DB_PORT is fine. The DB_DATABASE is laravel, and the DB_USERNAME is root, with no password. So let's take the DB_DATABASE, laravel, and I'll set that as the value here. So we're instructing the container, look, when you boot, create a database called laravel. Okay, let's go back to the documentation and copy this value here, MySQL_ALLOW_EMPTY_PASSWORD,

So we're instructing the container, look, when you boot, create a database called Laravel. Okay, let's go back to the documentation and copy this value here, MYSQL_ALLOW_EMPTY_PASSWORD, and if it's set to a non-empty value like yes, then we don't have to provide a password at all. So we'll go back to our docker-compose.yml file. We'll set MYSQL_ALLOW_EMPTY_PASSWORD to yes, and again, I think this is more or less all the configuration we'll need. So when our workflow starts, it will boot up a MySQL 8.0 Docker container, mapping port 3306 in the Docker machine to port 3306 in the GitHub workflow. It's also going to ask Docker to create a database called Laravel and allow for an empty.

3306 in the Docker machine to port 3306 in the GitHub workflow. It's also going to ask Docker to create a database called Laravel and allow for an empty password out of the box. Okay, if we come a little bit further down, then when we actually run our tests, we're going to, at the moment, be passing SQLite and in-memory as the database options, but if we remove those options, then it's going to fall back to whatever we define in .env.example. And if we go into .env.example, well, we've already said that it should use a MySQL database connection on port 3306 with a database called Laravel, which matches what we've just created, and a username of root, which again is the default for MySQL. So with all those default options available, I would actually expect that we can successfully

and a username of root, which again is the default for MySQL. So with all those default options available, I would actually expect that we can successfully connect to this MySQL database to execute our tests. Let's push it up and see what happens. Hey, it worked. So MySQL service container was pulled. A little bit further down, you can see that container was started. And most importantly, if you come down to the tests, they pass with flying colors, which means our workflow now meets the requirements of our application. Little tip, by the way, anytime you use a service in a workflow, you'll have this new

Addressing Workflow Performance9:16

means our workflow now meets the requirements of our application. Little tip, by the way, anytime you use a service in a workflow, you'll have this new stop containers step where you can actually see the output from all of these services. So if you're getting issues, something's not quite working correctly, you can usually debug it by just reading through that output. There is still a little bit of a problem with our action. However, if you come back up to these steps here, take a look at how long it took to set up php and Composer, two minutes and 52 seconds. That just won't do. Now, the reason it's taking so long is essentially because of these extensions that we're installing.

That just won't do. Now, the reason it's taking so long is essentially because of these extensions that we're installing. We don't actually need all of them for now. In fact, we could remove the SQLite ones, seeing as we're no longer running on SQLite. There we go. That's two out of the way. But the fact of the matter is it will still be slow and sluggish, even if we clean these extensions up as much as possible, because it takes a while to install and enable extensions. But there's also a workaround for that. So let's tackle it in our next episode.

But there's also a workaround for that. So let's tackle it in our next episode. Thank you.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟