ウェブ制作

バックエンド

GitHub ActionsでCIを設定しよう

お刺身@プログラマー

お刺身@プログラマー

#Oookey_blog_020

凝集度を考える

こんにちは。
皆さんはGithub Actionを使っていますでしょうか?
私は恥ずかしながら存在は知っていたものの、触れてこなかったのですが
最近ミスが頻発しだしたのでCI/CDの片方、CIを実践してみました。
まだまだ使い始めたばかりですが、触ってみると以外と簡単に設定でき、その割には効果が大きいと感じたため、
今回はActionsのCIについて、自分がLaravel開発で使っているものをご紹介します。

目次

CIとは?
Github Actionsとは?
Laravel CI
まとめ
参考

CIとは?

CIは略称であり、正式名はContinuous Integration(継続的インテグレーション)です。 簡単にいうと、頻繁に変更したコードをコードベースへ取り込んでビルドや検証をする仕組みになります。 このCIがあることで、本来隅から隅までやるアプリケーションの問題チェックが 全てとは言いませんが、頻繁に、かつある程度担保される。 システムの品質向上とバグ・警告の早期発見ができるもの。

Github Actionsとは?

Github Actionsは、リポジトリごとにCIとCD(継続的デプロイメント)を作ることができる、 Githubのワークフロー機能です。 残念ながら、私があまり有効に活用できていると公言できるレベルではないため、気になった方は是非公式サイトをご確認ください。

https://github.co.jp/features/actions

Laravel CI

↓これは私がLaravel個人制作で活用しているCIです。

.github/workflows/laravelCI.yml

Copied!

copyBtn
# ① フローの名前。自由記述。
name: Laravel CI

# ② フローのトリガー条件。今回はdevelopブランチへのプッシュとプルリクエストをトリガーに設定。複数設定可能。
on:
 pull_request:
   branches: [ develop ]
 push:
   branches: [ develop ]

# ③ ジョブの定義。自由記述
jobs:
 laravel-check:

   # ④ ジョブの実行環境。ubuntu-latest, windows-latest, macos-latestなどが指定可能。ubuntu-latestがおすすめ。
   runs-on: ubuntu-latest
   # ⑤ ジョブの戦略。matrixで複数バージョンのPHPでテストを実行するように設定。
   strategy:
     # ⑤-1 途中で失敗しても他のバージョンのテストを続行する設定。
     fail-fast: false
     # ⑤-2 テストするPHPのバージョン。8.4のみで実行するように設定。
     matrix:
       php: [ '8.4' ]

   # ⑥ ジョブのステップ。各ステップで実行する内容を定義。
   steps:
       # ⑥-1 リポジトリのコードをチェックアウト。
     - name: Checkout repository
       uses: actions/checkout@v4

       # ⑥-2 PHPのセットアップ。指定したバージョンのPHPと必要な拡張モジュールをインストール。
     - name: Setup PHP
       uses: shivammathur/setup-php@v2
       with:
         php-version: ${{ matrix.php }}
         extensions: mbstring, intl, pdo_sqlite, dom, fileinfo
         coverage: none

         # ⑥-3 Composerのキャッシュを設定。依存関係のインストール。
     - name: Cache Composer dependencies
       uses: actions/cache@v4
       with:
         path: src/vendor
         key: ${{ runner.os }}-php-${{ matrix.php }}-composer-${{ hashFiles('src/composer.lock') }}
         restore-keys: |
           ${{ runner.os }}-php-${{ matrix.php }}-composer-
           ${{ runner.os }}-php-

             # ⑥-4 Composerのインストール。最新バージョンのComposerをインストール。
     - name: Install Composer dependencies
       working-directory: src
       run: composer install --no-interaction --no-progress --prefer-dist

       # ⑥-5 .envファイルのコピー。テスト用に.env.exampleを.envとしてコピー。
     - name: Copy .env
       working-directory: src
       run: cp .env.example .env

       # ⑥-6 アプリケーションキーの生成。LaravelアプリケーションのAPP_KEYを生成。
     - name: Generate app key
       working-directory: src
       run: php artisan key:generate

       # ⑥-7 artisanコマンドの動作確認。artisanが正しく動作するか確認。
     - name: Check artisan works
       working-directory: src
       run: php artisan about

       # ⑥-8 SQLiteデータベースファイルの準備。テスト用のSQLiteデータベースファイルを作成。
     - name: Prepare SQLite database file
       working-directory: src
       run: |
         mkdir -p database
         touch database/database.sqlite

       # ⑥-9 .env.testingファイルの作成。テスト環境用の設定を.env.testingに記述。
     - name: Create .env.testing
       working-directory: src
       run: |
         cat > .env.testing << 'EOF'
         APP_ENV=testing
         CACHE_DRIVER=array
         SESSION_DRIVER=array
         QUEUE_CONNECTION=sync
         DB_CONNECTION=sqlite
         DB_DATABASE=database/database.sqlite
         EOF

       # ⑥-10 テスト用APP_KEYの設定。テスト環境用のAPP_KEYを生成して.env.testingに追記。
     - name: Set testing APP_KEY
       working-directory: src
       shell: bash
       run: |
         KEY=$(php artisan key:generate --show)
         printf "\nAPP_KEY=%s\n" "$KEY" >> .env.testing

       # ⑥-11 設定キャッシュのクリア。設定のキャッシュをクリアして最新の設定を反映。
     - name: Clear config cache
       working-directory: src
       run: php artisan config:clear

       # ⑥-12 データベースマイグレーションの実行。テスト環境でマイグレーションを実行。
     - name: Migrate
       working-directory: src
       run: php artisan migrate --env=testing --force

       # ⑥-13 テストの実行。PHPUnitを使ってテストを実行。
     - name: Run tests
       working-directory: src
       run: php artisan test

①〜⑤はジョブの設定、⑥はステップの設定になります。
ジョブとは、ワークフロー内で実行される一連のタスクのことを指し、
ステップとは、ジョブ内で実行される個々のタスクのことを指します。

⑥のステップはLaravelをテストするために必要な一連の流れを定義しています。
例えば、⑥-3ではComposerの依存関係をキャッシュしてインストール。
⑥-9ではテスト環境用の.env.testingファイルを作成し、⑥-12でDBマイグレーションを実行。
最後に⑥-13でPHPUnitを使ってテストを実行しています。
これにより、developブランチにコードがプッシュされるたびに自動的にテストが実行され、コードの品質が保たれます。

使用時の注意点
私のリポジトリのディレクトリ構造が”リポジトリ/src”のため、パス指定に”src”や”working-directory: src”を記載しています。使用の際はご自身のディレクトリ環境に合わせてください。

他のテスト用ファイル設定も合わせて記載しておきます。

src/tests/Feature/ExampleTest.php

Copied!

copyBtn
<?php
namespace Tests\Feature;

use Tests\TestCase;

class ExampleTest extends TestCase
{
   /**
    * A basic test example.
    */
   public function test_the_application_returns_a_successful_response(): void
   {
       $response = $this->get('/');


       $response->assertStatus(200);
   }
}

src/tests/Feature/HealthCheckTest.php

Copied!

copyBtn
<?php
namespace Tests\Feature;

use Tests\TestCase;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\Group;

final class HealthCheckTest extends TestCase
{
   #[Test]
   #[Group('fast')]
   #[TestDox('GET /health returns 200 and {"status":"ok"}')]
   public function health_endpoint_returns_ok(): void
   {
       $res = $this->get('/health');


       $res->assertOk()
           ->assertJson(['status' => 'ok']);
   }
}

src/tests/Feature/UserCrudTest.php

Copied!

copyBtn
<?php
namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\Attributes\Group;

final class UserCrudTest extends TestCase
{
   use RefreshDatabase;

   #[Test]
   #[Group('database')]
   #[TestDox('UserモデルのCRUD操作が正常に動作する')]
   public function it_can_create_update_and_delete_user(): void
   {
       // CREATE
       $user = User::factory()->create([
           'name' => 'Taro',
           'email' => 'taro@example.com',
       ]);
       $this->assertDatabaseHas('users', ['email' => 'taro@example.com']);

       // UPDATE
       $user->update(['name' => 'Hanako']);
       $this->assertDatabaseHas('users', [
           'email' => 'taro@example.com',
           'name'  => 'Hanako',
       ]);

       // DELETE
       $user->delete();
       $this->assertDatabaseMissing('users', ['email' => 'taro@example.com']);
   }
}

src/routes/web.php(末尾に追加)

Copied!

copyBtn
Route::get('/health', function () {
   return response()->json(['status' => 'ok']);
});

Actionsの実行ログ/結果確認は、ヘッダーのActionsをクリックすると確認できます。

Actions

正常の場合はチェックマークが緑に、エラー時は赤のバツマークが表示されます。

Actions_log

今回は警告も特になく、無事成功しました!

まとめ

いかがでしたでしょうか?
GitHub Actionsを使ったCIの設定は比較的簡単に行え、コードの品質向上に役立ちます
今回はLaravelでCIを実行しましたが、Viteビルドや静的解析もCIで自動化すると快適な開発環境が整ってくるのではと思います。
まだまだ使い始めたばかりですが、CI/CDを導入することで、コードの品質向上とバグの早期発見が期待できるため、是非皆さんも導入を検討してみてはいかがでしょうか。
それではまた。

GItHub CI/CD実践ガイド --持続可能なソフトウェア開発を支えるGitHub Actionsの設計と運用

GitHub Actionsって何?触ってみて理解しよう!入門・逆引きリファレンス