Automatically deploy Laravel project to server with Laravel Envoy Github Webhooks “part 1

Tram Ho

Introduce

As you know, deploying the application on the server is a job that seems simple but also risky.

If you do this in a classic way, you must:

  • Ssh to the server
  • Pull git
  • Run the library update command: composer install, yarn install, …
  • Run migrate: php artisan migrate
  • Run commands to build css, js

There are too many commands to execute. It is not easy to remember and execute all the above commands. If you run the wrong command or forget to run a command, your site may not work properly. Besides, when you are executing the command (assuming you have just finished git and finished running composer install), your site is not accessible. That is, the website will have downtime during the deployment of the new program code.

To solve these problems, we will learn how to set up an automated deployment system (auto deployment) on our laravel website on servers using Laravel envoy and Github webhook.

I will divide this issue into components to make it easier for you to follow and understand:

  • Deploy using Laravel envoy
  • Set up auto deploy using Github webhook

This article we will learn the first part: Deploy using Laravel envoy

Deploy using Laravel envoy

Laravel envoy

Laravel envoy you can simply understand it is a tool that helps us perform tasks on remote servers. Normally we have to ssh into the server and then run the command. But when using Laravel envoy, we just need to write those commands into a task (task A for example) of envoy. After running the envoy command that requires it to perform task A , all the commands you write in A will be executed on the designated server. The advantage of this is that we do not need to remember, do not need to type too many commands just remember each envoy statement, everything will be done exactly as we expected. And of course using Laravel envoy we will create a script to deploy our project on the server simply and easily .

The problem of laravel project implementation

Deploy is easy but deploy but the website’s downtime is 0 is very difficult.

Suppose you have a project running in the root directory of A. You want to deploy that project with newer code and without affecting what is running, you must create a folder B and then deploy on it. After installing the above B , you will convert the website’s root directory to B. You can go to config of Apache or Nginx to change the configuration file and then restart Apache / Nginx. But that is not true because it must use the server’s highest permissions ( sudo ) and it will lose the automation of your system. You can think about deleting folder A and renaming B to A. This is also a good idea but it takes time (because the size of the code folder may not be large but there are many files so the deletion process will take a long time) and unfortunately B will fail to return. Able .

There is an easier way to do this. You will use the ln statement to link the site’s root directory to the directory containing your program code. When accessing the root directory of the website it will jump to the directory containing your program code. If you want to change the directory containing the program, just link it back. In the above situation, we will link the root directory of the web to A. When deploying is completed, it will link to B. If B unfortunately fails, we link to A to handle the error at B. Now the system still runs normally on A. After processing the error, link to B again . The process of creating a link is very fast, so it can be said that this way will help deploy with 0 downtime.

However, if B is completely new, the uploaded user data (photos, videos, documents, etc.) will not be available in B. So we have to copy the directory containing such data to another place (for example, share folder). The resource directories in A and B will be linked to the corresponding folders in the share .

Consider a specific laravel project. After installation, we can see that our program will have a lot of folders containing different resources:

  • The framework of the laravel framework and its code: app , config , database , resources , public , routes
  • Folders contain libraries: node_modules , vendor
  • Folders contain user-uploaded resources: normally I will put in a subdirectory in the storage folder
  • Folders containing fixed resource files (eg a user guide with docx files): will be stored in the storage folder
  • The directory contains the session of the website: the default will be storage/framework/sessions
  • Folders containing data created by laravel (cache view, other types of cache, …): will remain in storage/framework

Now have to analyze and calculate which folders need to be shared and which folders are not needed. The resources for sharing must be the resource created when the user performs the operations on his system or is a static resource of the system that I will never change every deploy .

  • The directory of laravel framework and my code of course cannot be shared because each time I update, the content of the code will be different.
  • node_modules , vendor are very heavy directories of projects but should not be shared . Because every time you install a new library or delete the old library or just change the version of the library, the data in these 2 folders will sync according to the installation using your new library. So if you deploy a new version of your project, the old version cannot be used. I have to make sure I can go back to the old version to prevent the new version from having an unforeseen error. Closing is not sharing this folder.
  • The folder contains user uploaded resources: share now and always
  • The directory contains a fixed resource file: no share . Because suppose I want to add a new file to this directory. If you share, when you pull git, we will delete this folder and link it in share . At this point in the share folder will not be able to have the content I can enter.
  • Folder containing session: share . Suppose the user is logged in and has done something that saves the session. If I don’t share it , when I switch to the new version, the data is gone. It is also possible that the login status of the user is lost if you set to remember token. Users who are typing in something for example will fail because they are not logged in. If your project uses session to save something with a different data structure between the two versions, then you don’t share this folder.
  • Directory containing data created by laravel: do not share . Because when the view changes, for example, the cache data will change. If you share it, it may lead to error because you still use cache data from the old version.

After a long analysis, we will share the uploading data of users and sessions. In addition, I also have to share an extremely important file. That is the .env file. This is the general configuration file for all versions when I deploy.

Install and use Laravel envoy

Installing Laravel envoy is easy, just run the command

After installation is complete, you can use envoy too. Using envoy is simple. Its syntax is similar to blade template syntax, so it is very intuitive and easy to use. You write the following code into the Envoy.blade.php file in the project root directory.

Then run the envoy run foo command so that the command in task foo will be run on the web server.

Please refer to the envoy docs page for details on how to use it.

Guide to building video call app using Easyrtc framework
Automated self-testing with Appium- Introducing Appium and installation instructions (Part 1)

Design deploy tools

To deploy laravel project to server from github, you have to follow the steps:

  • Data Clone : Clone github repository into a directory. The folder name will be set according to the deploy time
  • Create a shared folder : Create folders, share files if they do not exist
  • Link shared folders : Delete shared folders in the new clone folder from the github and link them to the corresponding folders in the share.
  • Link file .env : Create link with .env file in share
  • Install libraries : run composer install , yarn install
  • Run other commands : php artisan migrate --force , php artisan storage:link , yarn prod
  • Decentralization : grant more permissions for necessary directories
  • Web root switch : link the root directory of the web site to the already deployed directory

Directory structure of deploy system will be as follows:

  • current : is the root of the web. It will link to the deployed directory in the releases
  • releases : will contain deployments
  • share : contains shared folders between deploy versions

Configure vitual host in the apache config file: DocumentRoot will be the public directory in the current directory

Using Laravel envoy must first create the Envoy.blade.php file in the directory that will run the envoy command, including story deploy and the tasks that perform the above tasks:

Note: if the task has no command, envoy will report an error so please comment on any unused tasks during the task writing process.

Clone data

For each different deploy, you can specify which branch to deploy, deploy to which release directory. So we have to design the statement how to clone any branch from git to a certain directory .

The data clone command from github will look like this:

I will create variables to make it easier when I want to change: $gitRepo (repository github link), $defaultBrand (default brand – you can use the -brand attribute to specify which pull brand to use) , $release (the directory name you will clone code to), $path (root directory).

Add clone command to git task.

The {{ $branch ?? $defaultBrand }} makes it possible to use the -brand attribute to specify which pull brand to use (for example, envoy run deploy --branch=develop ). After the clone is complete, all program data will be placed in the $release folder.

Link shared resources

In my project, there is a folder to store user avatar images ( storage/app/public/avatars ) I will install to share that folder. In addition, there will be a storage/framework/sessions , storage/logs folder that will also be shared. When deploying for the first time, the default in share will have no folders or files at all. I have to initialize the initial directory as well as create the shared file. For example, the .env file must be copied from the file .env.example . After initializing, delete those folders in the release version. Finally, create directory symlinks in release version with folder in share .

For easier operation, I will create an array of shared folders that need to create symlinks

Browse all the share folders to create a symlink, create a directory if needed. The .env file will be initialized from .env.example .

Install the library

When a new task is run, the working directory will be converted to the root directory (the folder containing that Envoy.blade.php file). So if you want to manipulate any directory, you must move to that directory with the cd command.

Note: When installing composer, it may happen that the package has many supported versions or conflicts with certain packages, we must choose the appropriate installation package. That is, I have to interact with the terminal during the install process. To remove the interaction, for composer to perform automatically, we have to add the attribute --no-interaction .

Run other commands

In this section, I will run the installation related commands of javascript libraries and build css and js files.

Authorization

Licensing folders makes it easy to keep both security and the web running. I will have an article to discuss this issue further. As you know apache on ubuntu runs under the user www-data . The way I deploy will give users www-data owning code directory. For folders that need permission, you will grant full rights to users who own it ( www-data ).

Usually we use the statements we have commented because it is short and easy to remember. Example {{-- chmod -R ug+rwx {{ $release }}/storage --}} . This command will authorize all files and subdirectories contained in {{ $release }}/storage . This seems unnecessary, just granting permissions to the directory is enough. Because usually the directory containing data like this will be empty by default. The data in it will be generated during the run.

Web root switch

When everything goes smoothly, it will proceed to delete the old current file and create a link to a new release .

Result

That’s it. You can view the full program at https://github.com/HoangHoi/envoy-deploy .

When you want to deploy, just run the envoy run deploy command and go right away to make a milo to wait. It’s easy and simple, isn’t it?

Conclude

So we have built the system deployment tool together using Laravel envoy. My article ends here. Hope to help you. Have a good day!

Seeder and Model Factory in Laravel

Let’s build Laravel + Vuejs website in details for new learners 1
Share the news now

Source : viblo