2019-11-13

LaravelとGitHub ActionsでCI/CD環境を構築した話

leaf

こんにちは。スマートショッピングの@leafと申します。

今回はLaravelを利用してプロジェクトの構築からLaravel/envoyを利用したデプロイ、GitHub Actionsを利用したUnitTestの設定までを行なったのでその話をします。

LaravelとGitHub Actionsは検索してもあまり見つからなかったので、参考にしていただければ幸いです。

Laravelとは

LaravelはPHPの人気フレームワークで、フルスタックフレームワークでありながら学習コストが比較的低いところが特徴です。

今年の9月には最新のメジャーバージョンが6になり、アップデートも頻繁に行われているので、今後の発展も期待できると思います。

Laradockを利用したプロジェクト作成

今回環境を作成するにあたって、初めは全て一から構築することを検討していましたが、Laradockを利用すると簡単に環境を構築することができそうだったので、今回はLaradockを採用することになりました。

Laradockとは?

LaradockはDocker上で動作するLaravelの開発環境になります。

nginx・MySQLなども含まれているため、これだけで環境を作ることができます。

前提

  • 今回対象のOSはMacです。
  • Docker for Macがインストールされていること。
  • Gitがインストールされていること。

Laradockで環境構築

初めに、Laradockをcloneします。

私の場合は、~/project以下にLaradockをcloneしました。

$ git clone https://github.com/LaraDock/laradock.git

次にcloneしたディレクトリに移動して設定を変更していきます。

$ cd laradock
$ cp env-example .env

.envファイルを開いてMySQLの設定を変更します。

その他、nginxの設定やPHPのバージョン等もここで変更することができるので、必要に応じて変更を行ってください。

# MYSQL(内容は必要に応じて変更してください。)
MYSQL_VERSION=5.7
MYSQL_DATABASE=smartshopping_management
MYSQL_USER=default
MYSQL_PASSWORD=secret
MYSQL_PORT=3306
MYSQL_ROOT_PASSWORD=root

ここまで設定ができたら、一度プロジェクトを配置するコンテナを起動します。

※初回起動はなかなか時間がかかります。

$ docker-compose up -d workspace

コンテナが立ち上がったら下記コマンドで接続します。

$ docker-compose exec workspace bash

接続ができたらプロジェクトの作成を行います。

(プロジェクト名(smartshopping-management)は適当なものに置き換えてください。)

※これもライブラリのインストールがあるため長いです。

$ composer create-project laravel/laravel smartshopping-management

プロジェクトが作成できたらworkspaceから出て作業を行います。

$  exit

コンテナも設定変更時、再起動が必要となるので一度止めます。

$ docker-compose stop

現在いるディレクトリの上の階層に、作成したプロジェクトが出来ていることを確認します。

$ ls ../
laradock/  smartshopping-management/

laradoc内の.envを開いて、APP_CODE_PATH_HOSTを上記で確認したローカルのパスに編集します。

### Paths #################################################

# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=../smartshopping-management

次にプロジェクト内の.envの設定を変更します。

※ユーザー名とパスワードはここの設定を変更することで切り替えられますが、私が試した時は初回のmigration実行に失敗したので、初回はrootがいいと思います。

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=smartshopping_management
DB_USERNAME=root
DB_PASSWORD=root

これで環境設定はOKです。下記で起動します。

$ docker-compose up -d php-fpm nginx mysql

コンテナが立ち上がったら「http://localhost/ 」にアクセスし、サイトが表示されていることを確認します。

blog laravel1 確認ができたら環境構築は完了になります。

実装についてはまたの機会に。。。

envoyを利用したデプロイ

今回のデプロイは対象のサーバーも少なく、簡単に作成を行いたかったので、公式パッケージであるenvoyを利用して作成を行いました。

envoyとは?

Larval/envoyはリモートサーバーで実行するタスクを、LaravelのViewファイルで利用しているbladeと同様の構文で定義することができるタスクランナーになります。

Laravelでbladeを記述したことがあれば、学習コストがほぼなく、コマンド一つでデプロイが実現できるので、とても便利です。

(ちなみにLaravel以外でも使えます。)

envoyのインストール

envoyはcomposerでインストールを行うことができるので、下記を対象のプロジェクト配下で実行すれば完了です。

composer require laravel/envoy

envoyのタスク作成

envoyのタスクはプロジェクトルートにEnvoy.blade.phpというファイルを作成し、そこに定義を行なっていきます。

今回私が作成したタスクは下記の通りになります。

大体の流れとしては、「ローカルで実行→STGでビルド→本番環境に同期」です。

@servers(['web' => 'ec2-user@192.168.1.1'])

@task('deploy')
    // 対象ディレクトリに移動
    cd /var/www/html/smartshopping-management

    // gitから最新ソースを取得
    git pull origin master

    // envを本番用に切り替え
    cp .env.production .env

    // composerでライブラリを更新
    composer install

    // キャッシュ関連のクリア
    php artisan cache:clear
    php artisan config:clear
    php artisan route:clear
    php artisan view:clear

    // マイグレーションの実行
    php artisan migrate --force

    // npm実行
    source ~/.nvm/nvm.sh
    nvm use --lts
    npm run prod

    // 本番環境にビルドしたファイルを同期
    rsync -rlOtcv --delete -e ssh /var/www/html/smartshopping-management/ production:/var/www/html/smartshopping-management

@endtask

@finished
    @slack('webhookURL', '#deploy', 'デプロイ実行完了')
@endfinished

envoyのタスク解説

それでは設定の内容について簡単に解説していきたいと思います。

まず初めのブロックについてですが、ここで対象のサーバーについての情報を設定しています。(カンマ区切りで複数サーバー指定することもできます。)

@servers(['web' => 'ec2-user@192.168.1.1'])

次に定義しているのが実行されるタスクの定義になります。

今回は対象のサーバーが少なかったためタスクをまとめていますが、分割して定義することもできる様なので、気になる方は調べてみてください。

@task('deploy')
    // 対象ディレクトリに移動
    cd /var/www/html/smartshopping-management

    // gitから最新ソースを取得
    git pull origin master

    // envを本番用に切り替え
    cp .env.production .env

    // composerでライブラリを更新
    composer install

    // キャッシュ関連のクリア
    php artisan cache:clear
    php artisan config:clear
    php artisan route:clear
    php artisan view:clear

    // マイグレーションの実行
    php artisan migrate --force

    // npm実行
    source ~/.nvm/nvm.sh
    nvm use --lts
    npm run prod

    // 本番環境にビルドしたファイルを同期
    rsync -rlOtcv --delete -e ssh /var/www/html/smartshopping-management/ production:/var/www/html/smartshopping-management

@endtask

最後に処理後に実行されるブロックになります。

Slackであれば専用のものが用意されているので、下記の様に設定すればタスク終了時に通知を行うことができます。

@finished
    @slack('webhookURL', '#deploy', 'デプロイ実行完了')
@endfinished

envoyの実行

実行は対象のディレクトリから下記のコマンドを実行することで動作します。

(最後のdeployは作成したタスクの名前で読み替えてください。)

envoy run deploy

これでenvoyを利用したデプロイの設定も完了となります。

envoyは導入やデプロイを比較的簡単に行うことができるので、今後も整備して活用してみたいと思います。

GitHub Actionsを利用したUnitTest

プロジェクト作成後、プルリクにフックさせてUnitTestを実行させる検討を行っていました。

ちょうどその頃にGitHub Actionsが利用できる様になったので、今回はGitHub Actionsを採用することになりました。

GitHub Actionsとは

GitHubのリポジトリに対するイベントに応じて、タスクを実行できるサービスです。

最近では資料も増えてきており、使いやすくなってきたと思います。

GitHub Actionの設定作成

まず初めに定義ファイルを作成していきます。

GitHubにアクセスし、対象のリポジトリのActionsタブを開きます。

今回はいい感じのテンプレートがなかったので、右上のボタンを押して初期定義のみが記載されているファイルを生成します。 スクリーンショット 2019-11-12 15.35.43

この画面で設定を記述していきます。

ファイル名はよしなに変更してあげてください。

スクリーンショット 2019-11-12 15.57.29

下記が今回設定した内容になります。

name: UnitTest

on:
  pull_request:
    branches:
      - master
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: Copy ENV Laravel Configuration for CI
      run: php -r "file_exists('.env') || copy('.env.ci', '.env');"
    - name: Install Dependencies (PHP vendors)
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Create DB and schemas
      run: |
        mkdir -p database
        touch database/database.sqlite
        php artisan migrate
    - name: Run Test
      run: phpunit

GitHub Actionの設定解説

それでは設定の内容について簡単に解説していきたいと思います。

最初のnameは名前を定義しているだけなのでよしなに。。。

name: UnitTest

次にonで始まるブロックですが、ここはトリガーに関する定義を行なっています。

今回であれば、プルリクをトリガーにUnitTestを実行したいので、masterブランチに対してプルリクが作成されたタイミングで実行される様に定義を作成しています。

on:
  pull_request:
    branches:
      - master

最後にjobsのブロックですが、ここは実行する環境とタスクについての定義となります。

runs-onで指定を行なっているのが実行する環境になります。

stepsでテストを実行するために必要なライブラリの準備を行い、UnitTestを実行しています。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # 対象のソースをcheckout
    - uses: actions/checkout@v1 

    # UnitTest用にenvファイルを切り替え
    - name: Copy ENV Laravel Configuration for CI
      run: php -r "file_exists('.env') || copy('.env.ci', '.env');"
      
    # composerでライブラリの更新
    - name: Install Dependencies (PHP vendors)
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-suggest --no-progress --prefer-dist
      
    # プロジェクトを動かすためにアプリケーションキーの生成
    - name: Generate key
      run: php artisan key:generate
      
    # テスト用DBの作成、マイグレーション実行
    - name: Create DB and schemas
      run: |
        mkdir -p database
        touch database/database.sqlite
        php artisan migrate
        
    # テスト実行
    - name: Run Test
      run: phpunit

テストDBについて

現在、本番環境ではAuroraを利用していますが、IP制限の都合でGitHub Actionsからアクセスを避けたかったので、sqliteをGitHub Actionsのタスクを実行するたびに作成しています。

ci用にenvを切り分けて設定しているのもそのためになります。

# .env.ci
APP_NAME=SmartShopping
APP_ENV=ci
APP_KEY=
APP_DEBUG=true
APP_URL=https://smartshopping

LOG_CHANNEL=stack

DB_CONNECTION=sqlite
DB_DATABASE=database/database.sqlite

実行結果について

ここまで設定をファイルに記載し、プルリクを作成すると、プルリクに実行結果が表示される様になります。

スクリーンショット 2019-11-12 16.29.26

実行のログなどはActionsのタブから確認することができるので、失敗した場合はそちらを確認して対応していくことになります。

これでGitHub Actionsを利用したUnitTestの設定も完了です。

最後に

Laravelのプロジェクト立ち上げが初めてということもあり、色々とやり残したこともありますが、なんとか一通り作り上げることができました。

今後は、デプロイとテストのジョブを統合・本番とテスト用のDB統一・本番環境のコンテナ化などを進めていきたいと考えています。

区切りがついた段階でまたブログを書きたいと思いますので、その際はよろしくお願いします。

最新の記事