🐷

[ Gitlab Runner ] CI / CD パイプラインを構築する➁(CD編)

2022/03/30に公開

はじめに

gitlab上でCDを実行するために行った設定手順を解説する。

設定ファイルのソース

https://github.com/takuyanagai0213/gitlab-runner-pipeline-setting

概要

当プロジェクトに導入しているCI/CDパイプラインについて当記事にて解説を行う。

設定手順

リポジトリに追加する設定ファイルについて

以下の設定ファイルを追加する。

.gitlab-ci.yml
image: original/image:latest

cache:
  key: one-key-to-rule-them-all
  paths:
    - vendor/
    - node_modules/

before_script:
  - chmod 700 ~/.ssh
  - echo "$SSH_KEY" >> ~/.ssh/id_rsa
  - chmod 600 ~/.ssh/id_rsa
  - eval "$(ssh-agent)"
  - ssh-add ~/.ssh/id_rsa
  - ssh-add -l
  - echo "$SSH_CONFIG" >> ~/.ssh/config
  - ssh://git@255.255.255.255:65535/web/sample_project.git
  - git remote -v
  - git remote update
  - git config --global user.name gitlab_runner
  - git config --global user.email gitlab.runner@cimx-initiative.com
stages:
  - build
  - formatter
  - deploy

formatter:
  stage: formatter
  script:
    - npm install
    - ssh -t -t web_app_db -f -N
    - lsof -i
    - composer install
    - cp .env.example .env
    - echo "$ENV_FILE" >> .env
    - php artisan key:generate
    - vendor/bin/phpunit tests/Feature/api_test.php
    - vendor/bin/phpunit tests/Feature/Api
    - SYNTAX_CHECK=0
    - for FILE in `git diff --name-only origin/master | grep -E '*php'` ; do
    - echo $FILE
    - ./vendor/bin/php-cs-fixer fix $FILE
    - echo 'PHPMDで未使用変数などのチェック'
    - if ! ./vendor/bin/phpmd $FILE text ruleset.xml; then
    -   SYNTAX_CHECK=1
    - fi
    - done
    - IS_ERROR=0
    - for FILE in `git diff --name-only origin/master | grep -E '*js'` ; do
    - if [ $FILE = '.eslintrc.json' ]; then
    -   echo $FILE
    -   echo "skip check"
    -   continue
    - fi
    - if [ $FILE = 'composer.json' ]; then
    -   echo $FILE
    -   echo "skip check"
    -   continue
    - fi
    - if [ $FILE = 'package-lock.json' ]; then
    -   echo $FILE
    -   echo "skip check"
    -   continue
    - fi
    - if [ $FILE = 'package.json' ]; then
    -   echo $FILE
    -   echo "skip check"
    -   continue
    - fi
    - if [ $FILE = WebGL_Release.framework.js ]; then
    -   echo $FILE
    -   echo "skip check"
    -   continue
    - fi
    - if [[ -n `./node_modules/.bin/eslint --fix $FILE` ]]; then
    -   ./node_modules/.bin/eslint --fix $FILE
    -   IS_ERROR=1
    - fi
    - done
    - git add -A
    - git status
    - if [[ -n "`git status --porcelain`" ]];then
    - git commit -m '[ci skip]Push by GitLab runner'
    - git push origin $CI_COMMIT_REF_NAME
    - fi
    - IS_ERROR_LOG_REMAIN_ERROR=0
    - for FILE in `git diff --name-only origin/master | grep -E '*php'`; do
    - echo $FILE
    - if [[ -n `git grep error_log -- $FILE` ]]; then
    -   echo -e "\e[31;43m デバッグコードが残っている可能性があります。'\n'削除してください \e[m"
    -   IS_ERROR_LOG_REMAIN_ERROR=1
    - else
    -   IS_ERROR_LOG_REMAIN_ERROR=0
    - fi
    - done
    - if [ $SYNTAX_CHECK -eq 0 -a $IS_ERROR_LOG_REMAIN_ERROR -eq 0 ]; then
    - exit 0
    - else
    - echo -e "\e[31;43m 修正を行った上で再度コミットしてください \e[m"
    - exit 1
    - fi
  except:
    - master

deploy_production:
  stage: deploy
  script:
    - echo "$SSH_CONFIG_ENVOY" >> ~/.ssh/config
    - git pull origin master
    - composer global require laravel/envoy
    - ~/.composer/vendor/bin/envoy run deploy_production --server=prd --branch=master
  only:
    - master
deploy_staging:
  stage: deploy
  script:
    - echo "$SSH_CONFIG_ENVOY" >> ~/.ssh/config
    - git pull origin master
    - composer global require laravel/envoy
    - ~/.composer/vendor/bin/envoy run deploy_staging --server=stg --branch=develop
  only:
    - develop
Envoy.blade.php
@servers(['prd' => '-A web-prd', 'stg' => '-A web-stg'])

@setup
    $repository = 'ssh://git@255.255.255.255:65535/sample_project.git';

    if($server === "prd"){
        $releases_dir = '/var/www/html/sample_project_prd/releases';
        $app_dir = '/var/www/html/sample_project_prd';
    }elseif ($server === "stg") {
        $releases_dir = '/var/www/html/sample_project_stg/releases';
        $app_dir = '/var/www/html/sample_project_stg';
    }

    $releases_dir = '/var/www/html/sample_project/releases';
    $app_dir = '/var/www/html/sample_project';
    $release = 'web_'.date('YmdHis');
    $new_release_dir = $releases_dir .'/'. $release;
@endsetup

@story('deploy_production', ['on' => 'prd'])
    clone_repository
    run_composer
    copy_unity_build_dir
    copy_setting_file
    update_symlinks
    clean_old_releases
@endstory

@story('deploy_staging', ['on' => 'stg'])
    clone_repository
    run_composer
    copy_unity_build_dir
    copy_setting_file
    update_symlinks
    clean_old_releases
@endstory

@task('clone_repository')
    echo 'Cloning repository'
    [ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}

    @if ($branch)
        git clone -b {{ $branch }} {{ $repository }} {{ $new_release_dir }}
    @endif
    
    cd {{ $new_release_dir }}
    git reset --hard {{ $commit }}
@endtask

@task('run_composer')
    echo "Starting deployment ({{ $release }})"
    cd {{ $new_release_dir }}
    composer install --no-dev
@endtask

@task('update_symlinks')
    echo "Linking storage directory"
    rm -rf {{ $new_release_dir }}/storage
    ln -nfs {{ $app_dir }}/storage {{ $new_release_dir }}/storage

    echo 'Linking .env file'
    ln -nfs {{ $app_dir }}/.env {{ $new_release_dir }}/.env

    echo 'Linking current release'
    ln -nfs {{ $new_release_dir }} {{ $app_dir }}/current
@endtask

プロジェクト専用のGitLab Runnerを登録する。

  1. リポジトリのソースを参照できるページのサイドバーにて
    [Setting] → [CI/CD] で CI/CD専用の設定ページにアクセスする。
    「Runners」を選択した後に出てくる、「Specific runners」の項目の部分にて、「Register the runner with this URL:」(A) と「And this registration token:」(B) が記載されているので、こちらの2つを控える。

  2. GitLab Runner 専用のCIサーバーにログインする。

  3. 以下の様にGitlab Runnerの新規登録を行う。

[root@gitlab-runner ~]# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=18464 revision=775dd39d version=13.8.0
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com/
Enter the registration token:
aaaaaaaaaaaaaaaaaaaaaaaaaaa
Enter a description for the runner:
[gitlab-runner]:
Enter tags for the runner (comma-separated):

Registering runner... succeeded                     runner=fGaG43tQ
Enter an executor: docker-ssh, parallels, docker+machine, docker-ssh+machine, custom, docker, shell, ssh, virtualbox, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.6):
php:7.4-fpm
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
  • Enter the GitLab instance URL
    上記 1 の手順で控えた (A) のURLを入力する。

  • Enter the registration token:
    上記 1 の手順で控えた (B) のトークンを入力する。

  • Enter a description for the runner:
    特に記載内容がなければ、空欄のまま Enter

  • Enter tags for the runner (comma-separated):
    空欄のまま Enter

  • Enter an executor:
    docker と入力する。

  1. 上記設定後、以下コマンドでrestartを行う。
gitlab-runner restart

環境変数の設定

Setting] → [CI/CD] で CI/CD専用の設定ページにアクセスする。
「Variables」を選択した後に出てくる設定項目から設定を行う。「Add Variables」を押した後に各環境変数の設定を個別で行えるようになっている。

SSH_CONFIG_ENVOY

host *
  StrictHostKeyChecking no
  UserKnownHostsFile=/dev/null

Host web-prd-step
  HostName 165.76.149.78
  User deployer
  ForwardAgent yes

Host web-prd
  HostName 192.168.1.2
  User root
  ProxyCommand ssh -W %h:%p web-prd-step
  ForwardAgent yes

Host web-stg
  HostName 192.168.1.1
  User root
  ProxyCommand ssh -W %h:%p web-prd-step
  ForwardAgent yes

SSH_KEY

こちらには GitLab専用の秘密鍵をコピーして保存する。

authorized_keys について

自動デプロイの対象となるサーバーにて以下の設定を行う。
デプロイ対象となるサーバーに公開鍵を配置する。

vi ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Webサーバーのディレクトリについて

自動デプロイ対象のwebサーバーにて以下のディレクトリを作成する必要がある。

  • あらかじめ作成しておく必要があるディレクトリ及びwebアプリの設定ファイル
web
├── config-user.xml
├── config.php
├── config.xml 
└── releases

  • CI/CDの運用が開始されると以下の様なディレクトリ構成になる
web
├── config-user.xml
├── config.php
├── config.xml
├── current                             ※シンボリックリンクを張った際に自動的に作成される。 
└── releases
       ├── web_20220225_135238
       ├── web_20220301_011932
       └── web_20220228_093111

Webサーバーの設定

nginxのconfファイルを以下の内容に編集する。

server {
    listen 11000 ;

    root /var/www/html/web/current/public;
    server_name www.example.jp;

    access_log /var/log/nginx/web_access.log main;
    error_log /var/log/nginx/web_error.log warn;

    location / {
        root /var/www/html/web/current/public;
        index  index.php index.html index.htm;
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index  index.php,index.html;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

nginxの再起動を実行。

systemctl restart nginx

設定完了

参考資料

https://www.metrocode.co/blog/post/gitlab-ci-envoy

Discussion