GitlabからのWebhook(Pipeline)の調査の話

Gitlabにおいて自動テストの実行パイプラインを監視するにはどうすれば良いでしょうか?
Gitlabではこの監視にWebhookを提供しているのでそれを調査をしてみました。

そもそもWebhookとは!

Webhookとは、Webアプリケーションに対して、特定のイベントが発生したら別のWebアプリケーションに通知を発行するよう利用者が指定する仕組み。

https://e-words.jp/w/Webhook.html

らしいです…

Gitlabのパイプラインステータスとメッセージ発信

Gitlabにおいてパイプラインのステータスをイメージします。
(操作している時の表示される状態だけでの推論)
このそれぞれの切り替えタイミングで何らかのメッセージが発信されると監視できるのにな

こんな感じでメッセージが来ると良いなぁ〜

答え : この通りでした

調査用Webhookを作る

Webhookの動作を確認するために調査用のWebhookの受け手を作ってみました。

フレームワークはLaravelを使いましたが…
そこまで高尚ではないです。
受けるだけならpure phpで十二分です。
POSTリクエストのヘッダーとボディが取得できれば良いだけです

開発のポイントは公式文章通りです。

GitlabのWebhook 公式文章 : https://docs.gitlab.com/ee/user/project/integrations/webhook_events.html#pipeline-events

イベントの判断

Webhookから来るPOSTリクエストのヘッダーに以下のカスタムヘッダーがあればGitlabからのWebhookとして判断できます。

X-Gitlab-Event: Pipeline Hook

あとは、本文のobject_kindにpipelineとなっていることでダブルチェックできます

イベント本文

内容はJSON形式で来ます…

パイプラインの情報やコミット情報も来ます。

{ “object_kind”: “pipeline”, “object_attributes”:{ “id”: 31, “ref”: “master”, “tag”: false, “sha”: “bcbb5ec396a2c0f828686f14fac9b80b780504f2”, “before_sha”: “bcbb5ec396a2c0f828686f14fac9b80b780504f2”, “source”: “merge_request_event”, “status”: “success”, “stages”:[ “build”, “test”, “deploy” ], “created_at”: “2016-08-12 15:23:28 UTC”, … 略

検証プログラム

プログラム本体

検証用に書いたプログラムは…

  • Pipeline Hook以外は無視
  • Pipelineの実行状態を取得(ログ出力)
  • 対象のPipeline IDを取得(ログ出力)

これだけを実現しています。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class WebhookController extends Controller
{
    public function test(Request $request ){
        Log::debug('header : ' . $request->headers->get('x-gitlab-event'));
        if($request->headers->get('x-gitlab-event') != 'Pipeline Hook'){
            return '';
        }
        Log::debug('object_kind : ' . $request->object_kind
            . ' ID : ' . $request->object_attributes['id']
            . ' status : ' . $request->object_attributes['status']);
        return "";
    }
}

アクセスをURL

アクセスURLを考えました。
ずばり…

api/webhook

このURLをアクセスすれば調査用Webhookが走ります

api.phpに以下を追加します

Route::any('webhook', [WebhookController::class,'test']);

プログラムの実行

今回のプログラムは artisan serve使って動かします。

IPを指定したartisanの実行方法は以下の様にhostを指定してください。
(hostがない場合は127.0.0.1となりますが、ローカルしかアクセスできません)

$ php artisan serve --host 192.168.1.1
Starting Laravel development server: http://192.168.1.1:8000
[Sun May 22 10:41:27 2022] PHP 8.0.10 Development Server (http://192.168.1.1:8000) started

GitlabのWebhook設定方法

GitlabでのWebhookの設定方法を書いておきます。

対象プロジェクト > 設定 > Webhooks

ここにWebhookの設定を書けばOKです。

URLには調査用プログラムのアクセスURL(“http://192.168.1.1:8000/api/webhook”)を指定します。

トリガーはパイプラインイベントだけを指定しました。
SSLとか色々は… いりません!

動作確認

動作確認はパイプラインを実行すればメッセージを発信されるはずです。
Gitlabにて対象プロジェクトのパイプラインを手動で動かします。
すると、調査用プログラムのログにパイプラインのIDとステータスが出力されれば調査完了です。

パイプラインを手動実行すると以下の順でメッセージの受信が確認できました。

  1. pendding
  2. running
  3. success/failed?

実際のログはこんな感じです

[2022-05-23 01:45:56] local.DEBUG: header : Pipeline Hook  
[2022-05-23 01:45:56] local.DEBUG: object_kind : pipeline ID : 506 status : pending  
[2022-05-23 01:45:57] local.DEBUG: header : Pipeline Hook  
[2022-05-23 01:45:57] local.DEBUG: object_kind : pipeline ID : 506 status : running  
[2022-05-23 01:46:26] local.DEBUG: header : Pipeline Hook  
[2022-05-23 01:46:26] local.DEBUG: object_kind : pipeline ID : 506 status : success  

終いに

今回はGitlabからパイプラインイベントってどうすれば取れるかなと思って調査しました。

実現するにはどうすればよいかなど、既成サービスやプラグインなどを調べました…

結果、自分で作った方が楽かなって結論になりました。
のでその作り方を簡単に覚書を書いておきました。

これで、Gitlabのパイプラインを監視できました。