【PHP版】CI(継続的インテグレーション)ツール導入ガイド:第6回 CIサーバーを使ってみよう(GitLab で CI を稼働させる)

前回は GitLab を利用して CIサーバーを構築した。(第5回 CIサーバーの構築 「GitLabを利用し、CIサーバーを構築する手順」)今回は構築したサーバーで実際に CI を動作させてみよう。

プロジェクトの作成

まずは動作確認のためのプロジェクトを作成しよう。

GitLab のトップページに移動し、’Create a project’ をクリックすると、以下のような画面に移動する。URLは ‘/projects/new’ だ。

‘Project name’ に ‘first_project’ と入力し、’Create project’ をクリックしよう。すると以下のような画面になり、新しいプロジェクトについての情報が表示される。

CIサーバーにリポジトリが作られたので、Git を利用してリポジトリの操作が可能になった。リポジトリのURLは、画面中央に表示されている通りだ。

ファイルの登録

作成したプロジェクトのリポジトリは、一般的な Git のリポジトリなので gitクライアントを利用して自由に操作できる。git の利用方法の詳細は割愛するが、以下の2つのファイルをclassディレクトリを作って保存し、pushして欲しい。内容は第3回で利用した物と同じだ。

class/SampleClass1.php

<?php
class Sample_Class1
{
  public function sample1($a, $b, $c, $d, $e, $f, $g, $h)
  {
     $check_num = 1;
     $out = 0;
     $tmp1 = 10000;
     $tmp2 = 10000;
     $tmp3 = 10000;
     $tmp4 = 10000;
     $tmp5 = 10000;
     $tmp6 = 10000;
     $tmp7 = 10000;
     $tmp8 = 10000;
     $tmp9 = 10000;
     if ($a == $check_num) {
        $out++;
     }
     if ($b == $check_num) {
        $out++;
     }
     if ($c == $check_num) {
        $out++;
     }
     if ($d == $check_num) {
        $out++;
     }
     if ($e == $check_num) {
        $out++;
     }
     if ($f == $check_num) {
        $out++;
     }
     if ($g == $check_num) {
        $out++;
     }
     if ($h == $check_num) {
        $out++;
     }
     $out = 1000 + $out;
     return $out;
  }
}

SampleClass2.php

<?php
class Sample_Class2
{
  public function sample1($a, $b, $c, $d, $e, $f, $g, $h)
  {
     $check_num = 2;
     $out = 0;
     $tmp1 = 10000;
     $tmp2 = 10000;
     $tmp3 = 10000;
     $tmp4 = 10000;
     $tmp5 = 10000;
     $tmp6 = 10000;
     $tmp7 = 10000;
     $tmp8 = 10000;
     $tmp9 = 10000;
     if ($a == $check_num) {
        $out++;
     }
     if ($b == $check_num) {
        $out++;
     }
     if ($c == $check_num) {
        $out++;
     }
     if ($d == $check_num) {
        $out++;
     }
     if ($e == $check_num) {
        $out++;
     }
     if ($f == $check_num) {
        $out++;
     }
     if ($g == $check_num) {
        $out++;
     }
     if ($h == $check_num) {
        $out++;
     }
     $out = 1000 + $out;
     return $out;
  }
}

ファイルの push を行った後に画面をリロードすると、以下のように登録されたファイルが表示される。


テストの登録

次に PHPUnit で利用するテストスクリプトを登録しよう。以下の2つのファイルを test ディレクトリを作って保存し、pushして欲しい。内容は第3回で利用した物と同じだが、Sample_Class2 クラスのテストも登録する事にした。

test/SampleClass1Test.php

<?php
require_once __dir__ . '/../class/SampleClass1.php';

class Sample_Class1Test extends PHPUnit\Framework\TestCase
{
    protected $object;

    protected function setUp()
    {
        $this->object = new Sample_Class1();
    }

    public function test_sample1_1()
    {
        $this->assertEquals($this->object->sample1(1,1,1,1,1,1,1,1), 1008);
    }

    public function test_sample1_2()
    {
        $this->assertEquals($this->object->sample1(2,2,2,2,2,2,2,2), 1000);
    }

    public function test_sample1_3()
    {
        $this->assertEquals($this->object->sample1(1,2,1,2,1,2,1,2), 1004);
    }
}

test/SampleClass2Test.php

<?php
require_once __dir__ . '/../class/SampleClass2.php';

class Sample_Class2Test extends PHPUnit\Framework\TestCase
{
    protected $object;

    protected function setUp()
    {
        $this->object = new Sample_Class2();
    }

    public function test_sample1_1()
    {
        $this->assertEquals($this->object->sample1(1,1,1,1,1,1,1,1), 1000);
    }

    public function test_sample1_2()
    {
        $this->assertEquals($this->object->sample1(2,2,2,2,2,2,2,2), 1008);
    }

    public function test_sample1_3()
    {
        $this->assertEquals($this->object->sample1(1,2,1,2,1,2,1,2), 1004);
    }
}

push 実行後に画面をリロードすると、以下のような感じになり、class ディレクトリと test ディレクトリが登録されている事が分かるだろう。それぞれのディレクトリ名をクリックすれば、登録されているファイルの確認も可能だ。この辺の操作は GitHub とほとんど一緒だ。


ジョブの設定

次はいよいよ CI だ。GitLab ではリポジトリのルートに設置された ‘.gitlab-ci.yml’ というYAMLファイルで CI を制御する。’.gitlab-ci.yml’ を作成し、以下の内容を記述しよう。

.gitlab-ci.yml

image: phptest
stages:
  - test
phpcpd_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpcpd class
phpmd_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpmd class text cleancode,codesize,design,unusedcode
phpunit_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpunit test

それぞれの意味は以下の通りである。

image: phptest

image は実行する docker イメージの名前を指定する。

 sudo docker commit 

で登録した名前になるので、ここでは

 phptest 

を指定している。

stages:
  - test

ステージとは CI の工程を示す物だ。この配列で指定された順番にステージが実行される。それぞれのステージには複数のジョブを登録可能だ。今回は

 test 

というひとつのステージしか登録していないが、 build, test, deploy 等工程ごとに複数のステージを登録するのが一般的な利用方法である。

phpcpd_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpcpd class

ここでは PHPCPD のジョブを登録している。ジョブの名前は任意の物が利用できるが、image, stage等、予約されている名前は利用できない。末尾に ‘_job’等を付けておけば予約名と被る事は無いだろう。

stage

には

stages

で登録したステージのうちのひとつを記述し、このジョブがどのステージに属しているのかを指定する。

script

には実行するコマンドを指定する。配列形式で指定可能で、複数のスクリプトを登録できる。

phpmd_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpmd class text cleancode,codesize,design,unusedcode

PHPMD のジョブを登録している。

phpunit_job:
  stage: test
  script:
    - ~/.composer/vendor/bin/phpunit test

PHPUnit のジョブを登録している。

‘.gitlab-ci.yml’ には他にもさまざまな項目が指定できる。詳細は以下の公式ページを見て欲しい。

gitlab-ci.yml 公式: https://docs.gitlab.com/ce/ci/yaml/README.html

CI の開始

‘.gitlab-ci.yml’ をリポジトリに push して登録すると、すぐさまジョブが実行される。push したらすぐにサイドメニューの “CI/CD” をクリックしてみよう。URLは ‘/root/first_project/pipelines’ だ。すると、以下のような画面になる。

これは CI のジョブを実行中である事を表している。しばらく待つと以下のような画面になる。

これは CI のジョブが失敗してしまったという事を表している。

faild

をクリックするとさらに詳細な情報が表示される。

ここでは PHPCPD と PHPMD は失敗したが、PHPUnit だけは成功していると表示されている。このように個別のジョブが成功したか失敗したかを確認可能だ。さらにそれぞれのジョブ名をクリックすると詳細な情報が表示されている。


プログラムの修正

最初のジョブを無事に実行できたが、残念ながら結果は失敗である。PHPUnit の実行結果は成功しているので現状の動作には問題ないが、PHPCPD, PHPMD によってソースコードの記述方法に問題があると指摘されてしまった。指摘内容の詳細は第3回で説明しているので、そちらを見てもらいたい。

これらの問題を解決するためにクラスを修正しよう。Sample_Class1 クラスと Sample_Class2 クラスはほぼ似た機能を持っているので、共通の抽象クラスを用意しよう。また、不要な変数等は削除しておきたい。クラスの命名や設計自体も修正の余地があるのだが、それについては取り合えず置いておこう。新たに SampleAbstractClass.php を用意し、SampleClass1.php と SampleClass2.php も以下のように修正する事とする。

class/SampleAbstractClass.php

<?php
abstract class Sample_AbstractClass
{
    protected function core($check, $vals)
    {
        $out = 0;
        foreach ($vals as $v) {
            if ($v == $check) {
                $out++;
            }
        }
        $out = 1000 + $out;
        return $out;
    }
    abstract public function sample1($a, $b, $c, $d, $e, $f, $g, $h);
}

class/SampleClass1.php

<?php
require_once __dir__ . '/SampleAbstractClass.php';

class Sample_Class1 extends Sample_AbstractClass
{
    public function sample1($a, $b, $c, $d, $e, $f, $g, $h)
    {
        return parent::core(1, [$a, $b, $c, $d, $e, $f, $g, $h]);
    }
}

class/SampleClass2.php

<?php
require_once __dir__ . '/SampleAbstractClass.php';

class Sample_Class2 extends Sample_AbstractClass
{
    public function sample1($a, $b, $c, $d, $e, $f, $g, $h)
    {
        return parent::core(1, [$a, $b, $c, $d, $e, $f, $g, $h]);
    }
}

修正結果の確認

プログラムを修正したら push しよう。 CI は push と同期して実行されるためすぐにジョブは開始される。左サイドメニューの “CI/CD” をクリックしてしばらく待つと、以下のような画面になるはずだ。

再びジョブが失敗してしまった。’failed’ をクリックし、詳細を確認しよう。

今度は PHPCPD と PHPMD が成功しているのに PHPUnit が失敗している。詳細を見ると以下の通りだ。

Sample_Class2 クラスのテストで2つのテストが失敗している。これは Sample_Class2::sample1() メソッド内で、parent::core() メソッドをコールする時、第1引数に2を指定しなければならないのに1を指定してしまったのが原因だろう。コードを以下のように修正して再び push しよう。

class/SampleClass2.php

<?php
require_once __dir__ . '/SampleAbstractClass.php';

class Sample_Class2 extends Sample_AbstractClass
{
    public function sample1($a, $b, $c, $d, $e, $f, $g, $h)
    {
        return parent::core(2, [$a, $b, $c, $d, $e, $f, $g, $h]);
    }
}

push したらもう一度左サイドメニューの “CI/CD” をクリックしよう。しばらく待つと以下の画面になるはずだ。

今度は成功を示す ‘passed’ が表示されている。このようにプログラムの動作を変えずに構造を修正する事を「リファクタリング」と言うが、ユニットテストが登録されていると非常に便利だ。十分なテストが登録されていれば大胆なリファクタリングも安心して行う事ができるだろう。

最後に

今回は実際に GitLab で CI を稼働させる様子を紹介した。駆け足になってしまった部分もあるが、CI がどのように動作していくかの雰囲気を掴んでもらえれば幸いである。


社内サーバにリモートリポジトリを作るのも一つですが、「開発にまつわる面倒事」をこの際全部、tracpath(トラックパス)に任せてみませんか?
バージョン管理サービス・プロジェクト管理サービスの「tracpath(トラックパス)」では、
ユーザー5名、リポジトリ数3つまで、無料で利用可能です。

さっそく実務でも使って見ましょう。
自らも開発を行う会社が作ったからこそ、開発チームの「作る情熱」を支える、やるべきことに集中出来るサービスになっています。
エンタープライズ利用が前提のASPサービスなので、セキュリティも強固です。