Laravel Envoy

8/13/2021 Laravel

# Desscription

Laravel Envoy (opens new window) là 1 công cụ giúp excute các task trong quá trình deploy app lên remote server sử dụng blade syntax. Thay vì gõ command hoặc đóng gói trong file ( như sh) thì có thể dùng Laravel Envoy để quản lí và thực thi dễ dàng hơn.

# Installation

composer require laravel/envoy --dev
1

# Usage:

Các thành phần chính có thể xem tại https://laravel.com/docs/8.x/envoy (opens new window), post chủ yếu focus vào vài điểm nổi bật và example về envoy.

Đầu tiên cần tạo 1 file Envoy.blade.php tại thư mục root.

VD 1 task đơn giản. Run tại local và mục đích là list các file, folder

@servers(['localhost' => '127.0.0.1'])

@task('test', ['on' => 'localhost'])
    ls
@endtask
1
2
3
4
5

Run envoy

php vendor/bin/envoy run test
1
  1. Importing: Trường hợp project nhiều task, cần chia nhiều file để quản lí thì có thể dùng @import

    /* Envoy.blade.php */
    @servers(['local' => '127.0.0.1'])
    @import('envoys/FirstTask.blade.php')
        
    /* FirstTask.blade.php */
    @task('test', ['on' => 'local'])
        ls
    @endtask
    
    1
    2
    3
    4
    5
    6
    7
    8
  2. Multiple Server: Deploy nhiều server,

    @servers(['local' => '127.0.0.1', 'stg' => '192.168.1.2'])
    
    @task('deploy', ['on' => ['local', 'stg']], 'parallel' => true)
        git pull origin master
        php artisan migrate --force
    @endtask
    
    1
    2
    3
    4
    5
    6

    Mặc định Envoy sẽ thực hiện lần lượt excute trên từng môi trường. Set param 'parallel' => true để có thể excute cùng lúc trên nhiều server.

  3. Variable: excute với variable

    @servers(['local' => '127.0.0.1', 'stg' => '192.168.1.2'])
    
    @setup
        $server = $server ? [$server] : ['local', 'stg'];
    @endsetup
    @task('test', ['on' => $server])
        ls
    @endtask
    
    1
    2
    3
    4
    5
    6
    7
    8

    Mặc định sẽ excute cả 2 server nhưng trường hợp cụ thể có thể chọn server để excute. VD chỉ excute ở local

    php vendor/bin/envoy run test --server=local
    
    1
  4. Completion Hooks:

    Laravel Envoy hổ trợ các hook @after, @error, @success, and @finished trong quá trình excute, finish các task.

    ..
    @story('deploy')
        test
        test2
    @endstory
    
    @task('test', ['on' => $server])
        // do something
    @endtask
    
    @task('test2', ['on' => $server])
         // do something
    @endtask
    
    @after
        echo "Task: {$task} completed";
    @endafter
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  5. Notifications:

    Envoy hổ trợ send notification (Slack, Discord, Telegram) khi excute.

    @finished
        @slack('webhook-url', '#bots', 'Hello, Slack.')
    @endfinished
    
    1
    2
    3

# Example:

Khi deploy laravel app lên server thường có các step: Get code từ repository, run composer, update symlinks, optimization, build asset, run migrate.

  1. Get repository:

    Với 1 repository, cần tạo 2 variable repository url và folder chứa src. Để dễ quản lí các release version và có thể rollback nếu phát sinh lỗi, mỗi release nên lưu vào 1 folder và tạo symlinks đến folder release mới nhất.

    @setup
        // example use github
        $repoUrl = 'git@github.com:<user>/<repository-name>.git';
        $baseDir = '/var/www/html';
        $releasesDir = $baseDir . '/releases';
    	$releaseDir = $releasesDir . '/' . date('YmdHis');
    @endsetup
    @task('get_git_repository')
        echo 'Cloning repository'
        // Tạo folder $releasesDir nếu chưa tồn tại
        [ -d {{ $releasesDir }} ] || mkdir {{ $releasesDir }}
        // Clone git repository 
    	git clone --depth 1 {{ $repoUrl }} {{ $releaseDir }}
    	cd {{ $releaseDir }}
    	git reset --hard origin/master
    @endtask
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  2. Run composer:

    @task('run_composer')
        echo 'Installing composer dependencies'
        cd {{ $releaseDir }}
        composer install --prefer-dist --no-scripts -q -o
    @endtask
    
    1
    2
    3
    4
    5
  3. Update symlinks

    @task('update_symlinks')
        // Tạo symlinks cho storage.
        // dữ liệu storage, env sẽ không thay đổi với mỗi lần deploy release.
        echo 'Linking storage'
        rm -rf {{ $releaseDir }}/storage
        ln -nfs {{ $baseDir }}/storage {{ $releaseDir }}/storage
    
        echo 'Linking .env'
        ln -nfs {{ $baseDir }}/.env {{ $releaseDir }}/.env
        
        echo 'Optimization'
        // Optimizing Configuration Loading
        php artisan config:cache
        // Optimizing Route Loading
        php artisan route:cache
        // Optimizing View Loading
        php artisan view:cache
    
        echo 'Linking current release'
        ln -nfs {{ $releaseDir }} {{ $baseDir }}/current
    
    @endtask
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22

    /current là path đã setting ở web server.

    VD: nginx

    server {
        root /var/www/html/current/public;
    	...
    }
    
    1
    2
    3
    4
  4. Build asset:

    @task('build_assets')
        echo 'building asset'
        cd {{ $releaseDir }};
        npm install
        npm run build
    @endtask
    
    1
    2
    3
    4
    5
    6
  5. Migration:

    @task('migration')
        echo 'Running migrations';
        cd {{ $releaseDir }};
        php artisan migrate --force;
    @endtask
    
    1
    2
    3
    4
    5
  6. Stories:

    @story('deploy')
    	get_git_repository
    	run_composer
    	update_symlinks
    	build_assets
    	migration
    @endstory
    
    1
    2
    3
    4
    5
    6
    7