Kunoichi Marketドキュメント

CircleCI は継続的インテグレーションを支援するサービスです。GitHub などと連携して動作します。この記事では、GitHub と CircleCI を使って継続的インテグレーションのセットアップを行う手順をまとめました。

前提

この記事では、以下の前提で解説を行います。

  • GitHub でのアカウント登録が完了している
  • PHP のパッケージ管理ツールの Composer が利用できる状態になっている
  • PHPUnit で PHP のテストを作成して実行した経験がある
  • 開発済みまたは開発中の架空の WordPress テーマ Kunoichi Theme (kunoichi-themeというスラッグを持っているものとします) を対象にする

CircleCI について

CircleCI は広く利用されている CI サービスの1つです。2019 年 10 月 17 日現在のところ、Free プランでは以下の範囲の利用ができます。

  • 無料利用枠: 週あたり 2,500 クレジット相当分
  • 同時実行できる並列ジョブ数の制限: 1
  • 利用できるビルド環境: Linux・Windows

クレジットとは従量課金の単位で、は 1 分 x コンピューター 1 台あたり 10 クレジットが消費されます。CircleCI の動作環境になっている Docker レイヤーのキャッシュなどでもクレジットが消費されるようです。詳細は公式ドキュメントをご覧ください。

その他のプランの詳細については 公式サイト を参照してください。

CircleCI へのサインアップ

サインアップページ から GitHub の OAuth を使って CircleCI にサインアップできます。この際に CircleCI が必要とする GitHub 上の情報へのアクセスが列挙されますので、これらに問題がないと判断できたら CircleCI を認可してください。

テーマ開発環境のセットアップ

wp-cli のコマンドで、テーマのテストのセットアップと CI 連携に関係するファイルの追加ができます。

$ wp scaffold theme-tests kunoichi-theme --ci=circle
Success: Created test files.

コマンドが成功すると、テーマに以下のファイルが追加されます。

  • .circleci/config.yml # CircleCI の設定ファイル
  • bin/install-wp-tests.sh # テストを行うために WordPress を現在の環境にインストールするスクリプト
  • tests/bootstrap.php # テスト実行に先立って WordPress 環境でテーマをテスト可能な状態にする PHP プログラム
  • tests/test-sample.php # テストファイルのサンプル
  • .phpcs.xml.dist # PHP コードの静的解析ツール PHP_CodeSniffer の設定ファイル
  • phpunit.xml.dist # PHP のテストフレームワーク PHPUnit の設定ファイル

これで、CircleCI 上でテストを実行する準備が整いました。

ローカルで WordPress テーマのテストを実行する

CircleCI でテストを実行する前にローカル開発環境でテストを実行しておきます。以下のコマンドを実行してテスト用の WordPress をインストールします。

$ bash bin/install-wp-tests.sh <データベース名> <MySQL ユーザー名> <MySQL パスワード名> 127.0.0.1 latest

例えば テストに使うデータベース名が wordpress_test、MySQL のユーザー名とパスワードが root wordpress ならば、コマンドは以下になります。テスト用のデータベース名はテーマ開発に用いているものと別の物を使うように注意してください。同じデータベース名を指定すると、データベースが消去されます。

$ bash bin/install-wp-tests.sh wordpress_test root wordpress 127.0.0.1 latest

テストケースを作成する

サンプルのテストケースをコピー、またはリネームしてテストを作成します。 test-sample.php については PHPUnit の設定で除外されているため、ここに書かれたテストは実行されませんので注意してください。具体的なテストの書き方(テスト対象の設定やテストの粒度の設計)については、この記事では割愛します。

$ mv ./tests/test-sample.php ./tests/test-kunoichi.php

テストを実行する

PHPUnit を使ってテストを実行します。デフォルトの設定のまま実行できます。

$ phpunit
Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 5.6.0 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 3.35 seconds, Memory: 30.00MB

OK (1 test, 1 assertion)

テストが実行されました。

CI との連携設定を行う

テーマを GitHub にプッシュしておきます。

$ git add .
$ git commit -m"Add CI integration."
$ git push origin master

CircleCI のダッシュボードに移動し、ADD PROJECTS のタブに移動します。

ジョブ一覧。左側のタブから各設定ページに移動できる。

Kunoichi Theme が正しく GitHub にアップロードされている場合、そのリポジトリ名を検索して見つけることができるはずです。

プロジェクト管理画面。連携されている GitHub や Bitbucket のリポジトリが列挙される。

Kunoichi Theme を選択すると詳細な設定画面に遷移します。今回は wp-cli を使って CI の設定を行ったため、このダッシュボード上での設定は不要です。

ビルドの詳細設定画面。使用する言語や、設定ファイルの追加方法が説明されている。

START BUILD のボタンを押すとビルドが始まります。

ビルドが実行されているところ。

ジョブのキューに入ったものから順に実行されているのがわかります。各ジョブをクリックするとログを確認することができます。緑色になったらテスト成功です。

ジョブ一覧ではビルドの状況を確認できる。

CD 設定を行う

CI でのテストが成功した後に、ファイルの転送などの処理を行いたい場合があります。プロダクション環境などの特定のサーバーや、GitHub の特定のブランチ (例えば release など)へのテーマのアップロードができればとても便利です。そのための方法について解説します。このようなデプロイの方法を CD (継続的デリバリ)などと呼ぶことがあります。GitHub のデプロイキーや、プロダクションサーバーにアクセスできる秘密鍵を CircleCI に埋め込むことでファイルをサーバーに転送することができます。
この項では、GitHub のデプロイキーを CircleCI に渡して GitHub に書き込みアクセスをする例を示します。

GitHub のデプロイキーを作成する

PEM 形式でデプロイキーを作成します。パスワードは無しで設定します。

$ ssh-keygen -t rsa -b 4096 -m pem -f circle_deploy

秘密鍵 circle_deploy と公開鍵 circle_deploy.pub という鍵ペアが生成されました。

重要 特に秘密鍵の circle_deploy は当該リポジトリに無制限に書き込みを行うことができる権限があるため、取り扱いに注意してください。プライベートリポジトリ出会ってもコミットしないほうがいいでしょう。

秘密鍵を CircleCI に登録する

秘密鍵は CircleCI の PERMISSIONS -> SSH Permissions から埋め込むことができます。Hostname には github.com を指定します。また、Private Key に秘密鍵を転写します。ここで表示される Fingerprintaa:bb:cc:dd:ee:ff:00:11:22:33:44:55:66:77:88:99 のような値)は後で利用しますので控えておいてください。

SSH 鍵の追加画面。CircleCI からアクセスさせるサーバーの秘密鍵を登録する

公開鍵を GitHub に登録する

公開鍵は、 GitHub のリポジトリの settings -> deploy keys から追加できます。Key に秘密鍵を転写し、Allow write access にチェックを入れて Add key をクリックします。

GitHub (アクセスされるサーバー)のUIから公開鍵を登録する。

CircleCI から GitHub にアクセスする

.circleci/config.yml に以下の記述を追加します。

# 以下の設定を workflows.main.jobs に追加
- deploy:
    requires:
      - php56-build
    # master へのコミットに対してのみ発火させる
    filters:
      branches:
        only: master
# jobs['php-56'].steps の最後に追加
# インデントに注意
- persist_to_workspace:
    root: .
    paths:
      - .
# jobs にデプロイ用のジョブを追加
# <username> <fingerpring> は各自の環境に合わせて書き換えてください
deploy:
  docker:
    - image: circleci/php:5.6
  steps:
    - attach_workspace:
        at: .
    # 以下は GitHub の当該リポジトリに release というブランチを作ってプッシュするコマンド
    - run: rm -rf .git .circleci bin tests .phpcs.xml.dist phpunit.xml.dist
    - run: git config --global user.name "circleci"
    - run: git config --global user.email "<username>@users.noreply.github.com"
    - run: git init
    - run: git add .
    - run: git commit -m"Circle deploy"
    - run: git checkout -b release
    - run: git remote add origin git@github.com:<username>/kunoichi-theme.git
    # SSH鍵を使う直前に add_ssk_keys というステップでどの SSH 鍵を使うかを指定してください
    - add_ssh_keys:
        fingerprints:
          - "<fingerprint>"
    - run: git push -f origin release

以上を踏まえた .circleci/config.yml の全体は次のようになります。必要に応じて書き換えてください。

workflows:
  version: 2
  main:
    jobs:
      - php56-build
      # - php70-build
      # - php71-build
      # - php72-build
      - deploy:
          requires:
            - php56-build
          filters:
            branches:
              only: master

version: 2

job-references:
  mysql_image: &mysql_image circleci/mysql:5.6

  setup_environment: &setup_environment
    name: "Setup Environment Variables"
    command: |
      echo "export PATH=$HOME/.composer/vendor/bin:$PATH" >> $BASH_ENV
      source /home/circleci/.bashrc

  install_dependencies: &install_dependencies
    name: "Install Dependencies"
    command: |
      sudo apt-get update && sudo apt-get install subversion
      sudo -E docker-php-ext-install mysqli
      sudo sh -c "printf '\ndeb http://ftp.us.debian.org/debian sid main\n' >> /etc/apt/sources.list"
      sudo apt-get update && sudo apt-get install mysql-client-5.7

  php_job: &php_job
    environment:
      - WP_TESTS_DIR: "/tmp/wordpress-tests-lib"
      - WP_CORE_DIR: "/tmp/wordpress/"
    steps:
      - checkout
      - run: *setup_environment
      - run: *install_dependencies
      - run:
          name: "Run Tests"
          command: |
            composer global require "phpunit/phpunit=5.7.*"
            composer global require wp-coding-standards/wpcs
            phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
            phpcs
            rm -rf $WP_TESTS_DIR $WP_CORE_DIR
            bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1 latest
            phpunit
            WP_MULTISITE=1 phpunit

jobs:
  php56-build:
    <<: *php_job
    docker:
      - image: circleci/php:5.6
      - image: *mysql_image
    steps:
      - checkout
      - run: *setup_environment
      - run: *install_dependencies
      - run:
          name: "Run Tests"
          command: |
            composer global require "phpunit/phpunit=5.7.*"
            composer global require wp-coding-standards/wpcs
            phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs
            phpcs
            SKIP_DB_CREATE=false
            rm -rf $WP_TESTS_DIR $WP_CORE_DIR
            bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1 latest $SKIP_DB_CREATE
            phpunit
            WP_MULTISITE=1 phpunit
            SKIP_DB_CREATE=true
            rm -rf $WP_TESTS_DIR $WP_CORE_DIR
            bash bin/install-wp-tests.sh wordpress_test root '' 127.0.0.1 trunk $SKIP_DB_CREATE
            phpunit
            WP_MULTISITE=1 phpunit
            SKIP_DB_CREATE=true
      - persist_to_workspace:
          root: .
          paths:
            - .

  php70-build:
    <<: *php_job
    docker:
      - image: circleci/php:7.0
      - image: *mysql_image

  php71-build:
    <<: *php_job
    docker:
      - image: circleci/php:7.1
      - image: *mysql_image

  php72-build:
    <<: *php_job
    docker:
      - image: circleci/php:7.2
      - image: *mysql_image

  deploy:
    docker:
      - image: circleci/php:5.6
    steps:
      - attach_workspace:
          at: .
      - run: mkdir -p ~/.ssh
      - run: echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
      - run: rm -rf .git .circleci bin tests .phpcs.xml.dist phpunit.xml.dist
      - run: git config --global user.name "circleci"
      - run: git config --global user.email "<username>@users.noreply.github.com"
      - run: git init
      - run: git add .
      - run: git commit -m"Circle deploy"
      - run: git checkout -b release
      - run: git remote add origin git@github.com:<username>/kunoichi-theme.git
      - add_ssh_keys:
          fingerprints:
            - "<fingerprint>"
      - run: git push -f origin release

PHP5.6 でのテストが成功した際に GitHub の release ブランチにコードをプッシュする設定になっています。また、プッシュに先立って本番環境での動作には不要なファイルを削除しています。この処理は別のものに置き換えたり追加したりすることが可能です。例えば次のような処理です。

  • npm run build のようなコマンドを使って Gulp でアセットファイルをビルドする
  • scprsync などのコマンドを使って特定のサーバーにファイルを転送する

このような CI の設定変更を含むコミットを master にプッシュすると、追加された Workflow が以下のように発火します。

ワークフローがグラフとして表示される。どのジョブがどのジョブに依存していてどのような順番でワークフローが設定されているのかが分かる。

deploy のジョブが成功すると、GitHub に release というブランチが作成され、release ブランチへのコミットが GitHub プッシュされます。

release ブランチにコミットがプッシュされていることが分かる。テストの設定ファイルなどはビルドの際に取り除いているのでコミットされていない。

これで GitHub の release ブランチを使ったリリースができました。

終わりに

今回は master ブランチへのコミットに対してCDを行う設定を試しました。CircleCI は柔軟なワークフローの制御を設定することができ、例えば v1.2.3 のような Git のタグに対してデプロイを発火させるような設定も可能です。詳細は CircleCI のドキュメントをご覧ください。