Laravel + Bitbucket + HipChatのアラートを備えたセルフテストシステム

この記事では、laravelアプリケーションのテストサーバーへの新しいコードの自動プル、テストの自動実行、および対応する企業チャットでの結果の通知をすばやく設定する方法を説明します。 laravel.logで新しいエラーをキャッチするだけでなく



こんにちは、私の名前はDmitry Koretsです。小さな食料品会社のPHP開発者です。

Bitbucketをコードホスティングとして使用し、チームはHipChatを介して通信するため、彼らと連携します。



私たちが知っているように、継続的インテグレーションの実装の主な要件の1つは、システムのセルフテストです。 また、アプリケーションが大きすぎない場合、いくつかの独立したチームはそれを開発しません;さまざまなBambooとJenkinsのセットアップはかなり費用がかかります。



それで、私たちは何が欲しいのでしょうか?



リポジトリにプッシュすると、次のようになります。





さらに:





さあ始めましょう!



githubのように、ビットバケツには、いわゆるwebhookがあります。 これは、JSON形式の特定のデータを含むHTTP要求を、リポジトリの特定の変更を指定したURLに送信することを意味します。



[設定]-> [Webhook]-> [Webhookの追加]に移動します



画像



ご覧のとおり、リストは非常に大きくなっています。 これまでのところ、プッシュにのみ関心があり(ブランチをマージすると、プッシュイベントもトリガーされます)、必要なURLを指定して保存し、完了です!



これで、プッシュすると、上記のリクエストがリポジトリに送信されます。 アプリケーションで必要なルートをまだ構成していない場合でも、bitbucket自体からすべてを確認できます。設定-> Webhooks->作成したフックの反対側の要求を表示します。







詳細を表示して、実際に送信されたjsonオブジェクト、サーバーからの応答、ステータスコード、応答時間などを確認してみましょう。



HipChatルームに統合を追加する



hipchataには、bitbucketとの組み込みの統合があります。 ただし、使用できるのは、リポジトリの変更に関する通知を接続することだけです。 私の仕事は、特定のブランチを更新するときにのみ通知を受け取ることでした。私の会社では製品コアが絶えず開発されており、これと並行して、新しいプロジェクトが既存のカーネルでリリースされます。



したがって、開発段階では、カーネルのあるリポジトリ内にブランチの構造があります(条件付き)。





ルーム自体は、あなた自身が作成方法を知っており、そこに行き、統合を追加->独自の統合を構築をクリックすると、私たちは名前を思い付くと思います、メッセージはこの統合に代わってチャットに送信されます。 確認します。 次のページで最も重要なものを取得します-トークンとすぐにテスト用のcurlコマンドの例を含むURL。



curl -d '{"color":"green","message":"My first notification (yey)","notify":false,"message_format":"text"}' -H 'Content-Type: application/json' https://youcompany.hipchat.com/v2/room/{roomId}/notification?auth_token={token}







フックが構成され、HipChatルームが作成され、ロジックを記述します



ルートを作成します。



 <?php Route::group(['prefix' => LaravelLocalization::setLocale()], function () { Route::group( [ 'prefix' => 'development', ], function () { Route::group(['prefix' => 'bitbucket', 'namespace' => '\BE\Dev\Backend\Http\Controllers'], function () { Route::post('/', [ 'as' => 'bitbucket.push_event', 'uses' => 'BitbucketEventsController@pushEvent' ]); }); } ); } );
      
      





コントローラー:



 <?php namespace BE\Dev\Backend\Http\Controllers; use App\Http\Controllers\Controller; use BE\Dev\Services\Bitbucket\BitbucketPushEventService; use BE\Dev\Services\HipChat\HipChatService; use Illuminate\Http\Request; class BitbucketEventsController extends Controller { <?php namespace BE\Dev\Backend\Http\Controllers; use App\Http\Controllers\Controller; use BE\Dev\Services\Bitbucket\BitbucketPushEventService; use BE\Dev\Services\HipChat\HipChatService; use Illuminate\Http\Request; class BitbucketEventsController extends Controller { /** * @var $hipchatService HipChatService */ protected $hipchatService; /** * @var $pushService BitbucketPushEventService */ protected $pushService; protected $config; public function __construct(Request $request) { $this->config = config('be_dev'); $this->hipchatService = app(HipChatService::class); $this->pushService = app(BitbucketPushEventService::class, [$request->all()]); } public function pushEvent(Request $request) { $data = $request->all(); //      staging -    if ($this->pushService->getBranch() != 'staging') { return false; } //   $comment = strtolower($data['push']['changes'][0]['commits'][0]['message']); //    $author = $data['actor']['display_name']; $data = [ 'color' => 'green', 'message' => "<strong>{$author}</strong>      BE   \"{$comment}\"", 'notify' => true, 'message_format' => 'html', ]; //   $this->hipchatService->sendNotification($data); //      no tests -    if (strpos($comment, 'no tests')) { return response()->json([ 'success' => true, 'message' => 'tests was not executed' ])->setStatusCode(200); } // git pull +   +    $service = new \BE\Dev\Services\RuntTestsInQueueAndNotifyHipChatRoom(); $service->handle(); return response()->json([ 'success' => true ])->setStatusCode(200); } }
      
      





それを理解しましょう。 ここでは、コントローラーに多くのロジックを入れないように、すぐにサービスのコードを少し分散しました。 ほとんどのアクションは、RuntTestsInQueueAndNotifyHipChatRoomで綴られています。



RuntTestsInQueueAndNotifyHipChatRoomの内容:



 <?php namespace BE\Dev\Services; use BE\Dev\Services\HipChat\HipChatService; use Illuminate\Bus\Queueable; use BE\Jobs\Job; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Queue\ShouldQueue; class RuntTestsInQueueAndNotifyHipChatRoom extends Job implements ShouldQueue { use Queueable, SerializesModels; /** * @var $deployService DeployService */ protected $deployService; /** * @var $tests RunTests */ protected $tests; /** * @var $hipchatService HipChatService */ protected $hipchatService; public function __construct() { $this->deployService = app(DeployService::class); $this->tests = app(RunTests::class); $this->tests = app(HipChatService::class); } /** * Execute the job. * * @return void */ public function handle() { try { // git pull   $this->deployService->pullPackagesChanges(); //   $outputTests = $this->tests->run(); if ($outputTests === true) { $outputTests = '  '; $colorTests = 'green'; } else { $colorTests = 'red'; } //           $this->hipchatService->sendNotification([ 'color' => $colorTests, 'message' => $outputTests, 'notify' => true, 'message_format' => 'html', ]); } catch (\Exception $exception) { \Log::error($exception->getMessage()); } } }
      
      





コマンドラインでサーバー上でコマンドを実行するにはどうすればよいですか? LaravelはSymfony Processコンポーネントを使用しています( ドキュメント )。 重要な点は、コマンドを起動するユーザーに代わって、このことに留意してください!



サービスのコメント付きのさらなるコード。



bitbucketから変更をプルする:



 <?php namespace BE\Dev\Services; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; class DeployService { public function pullPackagesChanges() { // cd ../ ,     index.php    public, //        $process = new Process('cd ../ && git pull'); $process->run(); // executes after the command finishes if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } return $process->getOutput(); } }
      
      





テストを実行します。



 <?php namespace BE\Dev\Services; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; class RunTests { /** * @return string */ public function run() { $process = new Process('cd ../ && vendor/bin/phpunit --tap'); $process->run(); // executes after the command finishes if (!$process->isSuccessful()) { return $process->getIncrementalOutput(); } return true; } }
      
      





通知の送信は通常のcurl要求によって行われ、json_encode()をデータ配列に適用します



 <?php namespace BE\Dev\Services\HipChat; class HipChatService { /** * @var $config array Service config */ protected $config; public function __construct() { $this->config = config('be_dev.hipchat'); } public function sendNotification($data) { // create curl resource $ch = curl_init(); // set url curl_setopt($ch, CURLOPT_URL, $this->config['url']); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); //return the transfer as a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); // $output contains the output string $output = curl_exec($ch); // close curl resource to free up system resources curl_close($ch); return $output; } }
      
      





あなたが得るべきものの例:







さて、最後に、別のイベントを追加します。



 Log::getMonoLog()->pushHandler(new \Monolog\Handler\HipChatHandler( 'AUTH_TOKEN', 'ROOM_ID', 'hipchat-app', true, \Monolog\Logger::CRITICAL, true, true, 'text', 'COMPANY_NAME'.hipchat.com, 'v2' ));
      
      





ここで、タイプCRITICALのメッセージをlaravel.logに追加するたびに、メッセージを自分の部屋に送信します。 このコードは、サービスプロバイダーのいずれかに配置する必要があります。 ログに次のタイプのメッセージがあることを思い出させてください。



  1. デバッグ
  2. 情報
  3. 気づく
  4. 警告
  5. エラー
  6. 批判的
  7. 警戒
  8. 緊急事態


おわりに



それだけです。 私の最初の投稿では、情報の構造化がうまくいかないことをおaびします。 コードはこちらから入手できます 。 私は別の作曲家としてパッケージを作りませんでした、怠inessが私を引き継ぎました。 また、追加のロジックを追加できます。 たとえば、ビットバッグとヒップホップに加えてアトラシアン製品を積極的に使用している場合は、ギラもあります。コミットテキストにジグソーコードが含まれている場合、刑務所内のタスクを自動的に閉じてレビューのためにテスターに​​転送する機能を追加できます。 または、1つのgit pullプロジェクトではプロジェクトに十分ではない場合、構成を公開し、データベースを再構築し、初期データを入力するなどする必要があります。その後、プロジェクトデプロイメントのbashスクリプトを記述し、コミットテキストに特定のサブストリングが含まれている場合はそれを実行できます。



ご清聴ありがとうございました!



All Articles