GitLab CI/CDでSCP経由のデプロイを伴うComposerとNPMスクリプトの実行

このガイドでは、GitLabCI/CDを使ってNpmスクリプトでアセットをコンパイルしながら、PHPプロジェクトの依存関係を構築することについて説明します。

PHPとNode.jsのバージョンをカスタマイズして独自のイメージを作成することも可能ですが、ここでは簡潔にするため、PHPとNode.jsの両方がインストールされた既存のDockerイメージを使用します。

image: tetraweb/php

次のステップは、zip/unzipパッケージをインストールし、composerを利用できるようにすることです。これらをbefore_script

before_script:
  - apt-get update
  - apt-get install zip unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"

次に、composer install を実行してすべての PHP 依存パッケージを取得し、npm install を実行して Node.js パッケージをロードし、npm スクリプトを実行します。これらをbefore_script セクションに追加する必要があります:

before_script:
  # ...
  - php composer.phar install
  - npm install
  - npm run deploy

この特定のケースでは、npm deploy スクリプトは次のことを行う Gulp スクリプトです:

  1. CSSとJSのコンパイル
  2. スプライトの作成
  3. 様々なアセット(画像、フォント)をコピーしまくります。
  4. 文字列の置換

これらのオペレーションにより、すべてのファイルがbuild フォルダに格納され、ライブサーバにデプロイする準備が整います。

ライブサーバーへのファイル転送方法

rsync、SCP、SFTPなど複数の選択肢がありますが、ここではSCPを使います。

これを動作させるには、GitLab CI/CD 変数を追加する必要があります(gitlab.example/your-project-name/variablesでアクセス可能)。この変数はSTAGING_PRIVATE_KEY と呼ばれ、あなたのサーバーの SSH秘密鍵となります。

セキュリティ情報

更新が必要なフォルダのみにアクセスできるユーザーを作成します。

変数を作成したら、実行時にそのキーがDockerコンテナに追加されるようにする必要があります:

before_script:
  # - ....
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - mkdir -p ~/.ssh
  - eval $(ssh-agent -s)
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

順を追って言えば、これはつまり

  1. ssh-agent が利用可能かどうかを確認し、利用可能でない場合はインストールします。
  2. ~/.ssh フォルダを作成します。
  3. Bashを実行していることを確認します。
  4. ホストのチェックを無効にします(サーバーに最初に接続するときにユーザーのacceptを求めません。すべてのジョブが最初に接続するのと同じなので、これは必要です)。

そして、before_script

デプロイ方法

上述したように、Dockerイメージからbuild フォルダをサーバにデプロイする必要があります。そのために、新しいジョブを作成します:

stage_deploy:
  artifacts:
    paths:
      - build/
  only:
    - dev
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"

内訳は以下の通り:

  1. only:dev は、dev ブランチに何かがプッシュされたときにのみこのビルドが実行されることを意味します。 このブロックを完全に削除して、プッシュされるたびにすべてを実行させることもできます (しかし、おそらくこれは不要なことでしょう)。
  2. ssh-add ... ウェブUIで追加した秘密鍵をDockerコンテナに追加します。
  3. ssh 経由で接続し、新しい_tmp フォルダーを作成します。
  4. scp 経由で接続し、(npm スクリプトで生成された)build フォルダを、以前に作成した_tmp フォルダにアップロードします。
  5. ssh 経由で再度接続し、live フォルダーを_old フォルダーに移動し、_tmpliveに移動します。
  6. SSHに接続し、_old フォルダーを削除します。

アーティファクトはどうするのかというと、GitLab CI/CDにbuild ディレクトリを保持するように指示するだけです(後で必要に応じてダウンロードできます)。

なぜこの方法なのか

これをステージサーバーだけに使うのであれば、2つのステップでできます:

- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live

問題は、サーバー上にアプリがない期間が少しあるということです。

したがって、本番環境では、いつでも機能的なアプリが配置されていることを保証するために、追加のステップを使用します。

次の目的地

これはWordPressのプロジェクトだったので、実際のコードスニペットをあげました。 さらに追求できるアイデアもあります:

  • master ブランチ用に少し異なるスクリプトを用意しておくと、そのブランチから本番サーバーにデプロイしたり、他のブランチからステージサーバーにデプロイしたりできるようになります。
  • ライブでプッシュする代わりに、(SVNコミットを作成するなどして)WordPress公式リポジトリにプッシュすることができます。
  • その場で国際化テキストドメインを生成できます。

最終的な.gitlab-ci.yml

image: tetraweb/php

before_script:
  - apt-get update
  - apt-get install zip unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"
  - php composer.phar install
  - npm install
  - npm run deploy
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - mkdir -p ~/.ssh
  - eval $(ssh-agent -s)
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

stage_deploy:
  artifacts:
    paths:
      - build/
  only:
    - dev
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"