このシリーズの第4部では、継続的インテグレーション(CI)と継続的デプロイメント(CD)をGitHub Actionsで設定し、バックエンドをHerokuにテストおよびデプロイします。

はじめに
このシリーズの目標は、具体的な問題、つまりオンラインコースの採点システムを解決することで、現代のバックエンドにおける様々なパターン、問題、アーキテクチャを探求し、デモンストレーションすることです。この問題は、多様なリレーションタイプを持ち、実際のユースケースを表現するのに十分な複雑さを持っているため、選ばれました。
ライブストリームの録画は上にあり、この記事と同じ内容をカバーしています。
このシリーズで扱う内容
このシリーズでは、バックエンド開発のあらゆる側面におけるデータベースの役割に焦点を当て、以下の内容をカバーします。
最初の記事では、問題領域のデータモデルを設計し、Prisma Clientを使用してデータをデータベースに保存するシードスクリプトを作成しました。
シリーズの2番目の記事では、最初の記事のデータモデルとPrismaスキーマの上にREST APIを構築しました。Hapiを使用してREST APIを構築し、HTTPリクエストを介してリソースに対するCRUD操作を実行できるようにしました。
シリーズの3番目の記事では、HapiとJSON Web Tokens (JWT)を使用して、REST APIを保護するためのメールベースのパスワードレス認証と認可を実装しました。さらに、ユーザーが何を行うことを許可されているかを定義するために、リソースベースの認可を実装しました。
今日の学習内容
この記事では、テストを実行し、バックエンドとPostgreSQLデータベースをホストするHerokuにバックエンドをデプロイするワークフローを定義することで、GitHub ActionsをCI/CDサーバーとして設定します。
HerokuはPlatform as a Service (PaaS) です。サーバーレスデプロイメントモデルとは対照的に、Herokuではリクエストがない場合でもアプリケーションが継続的に稼働します。サーバーレスには低コストや運用上のオーバーヘッドが少ないといった多くの利点がありますが、このアプローチでは、サーバーレスアプローチに一般的なデータベース接続のチャーンやコールドスタートの課題を回避できます。
Prismaを使用するアプリケーションのデプロイパラダイム間のトレードオフについては、Prismaデプロイメントドキュメントをご覧ください。
注: このガイド全体を通して、手順を正しく実行したかどうかを検証できる様々なチェックポイントがあります。
前提条件
GitHub Actionを使用してバックエンドをHerokuにデプロイするには、以下が必要です。
- Herokuアカウント。
- Heroku CLIがインストールされていること。
- シリーズのパート3で作成した、メール送信用のSendGrid APIトークン。
継続的インテグレーションと継続的デプロイメント
継続的インテグレーション(CI)は、個々の開発者の作業をメインのコードリポジトリに統合し、統合バグを早期に発見し、共同開発を加速するための技術です。通常、CIサーバーはGitリポジトリに接続されており、コミットがリポジトリにプッシュされるたびにCIサーバーが実行されます。
継続的デプロイメント(CD)は、変更を迅速かつ一貫してデプロイできるように、デプロイプロセスを自動化することに関心があるアプローチです。
CIとCDは異なる責任を負いますが、関連性があり、しばしば同じツールを使用して処理されます。この記事では、CIとCDの両方をGitHub Actionsを使用して処理します。
継続的インテグレーションパイプライン
継続的インテグレーションにおいて、主要な構成要素はパイプラインです。パイプラインは、変更によってバグやリグレッションが導入されないことを保証するために定義する一連のステップです。例えば、パイプラインにはテストの実行、コードリンター、TypeScriptコンパイラのステップが含まれる場合があります。いずれかのステップが失敗した場合、CIサーバーは停止し、失敗したステップをGitHubに報告します。
プルリクエストを使用してコード変更が導入されるチームで作業する場合、CIサーバーは通常、すべてのプルリクエストに対してパイプラインを自動的に実行するように設定されます。
前の手順で記述したテストは、APIのエンドポイントへのリクエストをシミュレートすることで機能します。これらのエンドポイントのハンドラーはデータベースと対話するため、テストの期間中、バックエンドのスキーマを持つPostgreSQLデータベースが必要になります。次のステップでは、テストデータベース(CI実行中のみ)を実行し、テストデータベースがPrismaスキーマと一致するようにマイグレーションを実行するようにGitHub Actionsを設定します。
注: CIは、作成したテストの質に依存します。テストカバレッジが低い場合、テストがパスしても誤った信頼感を生む可能性があります。
GitHub Actionsでワークフローを定義する
GitHub Actionsは、継続的インテグレーションに使用できる自動化プラットフォームです。GitHubでのイベントに基づいてワークフローをオーケストレーションするためのAPIを提供し、GitHubからコードをビルド、テスト、デプロイするために使用できます。
GitHub Actionsを設定するには、yamlを使用してワークフローを定義します。ワークフローは、コミットがリポジトリにプッシュされた時や、プルリクエストが作成された時など、様々なリポジトリイベントで実行されるように設定できます。
各ワークフローには複数のジョブを含めることができ、各ジョブは複数のステップを定義します。ジョブの各ステップはコマンドであり、テスト対象の特定のコミットのソースコードにアクセスできます。
注: CIサービスではパイプラインに対して異なる用語を使用します。例えば、GitHub Actionsでは同じものを指すのにワークフローという用語を使用します。
この記事では、リポジトリにあるgrading-app
ワークフローを使用します。
ワークフローを見てみましょう
grading-app
ワークフローには、test
とdeploy
の2つのジョブがあります。
テストジョブは以下を行います。
- リポジトリをチェックアウトします。
- Node.jsを設定します。
- 依存関係をインストールします。
services
を使用して開始されるテストデータベースにデータベーススキーマを作成します。- テストを実行します。
注:
services
は追加のサービスを実行するために使用できます。上記のテストジョブでは、テスト用のPostgreSQLデータベースを作成するために使用されています。
デプロイジョブは以下を行います。
- リポジトリをチェックアウト
- 依存関係をインストール
- 本番データベースに対してマイグレーションを実行
- Herokuにデプロイ
注:
on: push
は、プッシュされたコミットごとにワークフローをトリガーします。if: github.event_name == 'push' && github.ref == 'refs/heads/master'
条件は、deploy
ジョブがmasterブランチに対してのみトリガーされることを保証します。
リポジトリをフォークしてワークフローを有効にする
GitHub Actionsを設定するために、まずGitHubリポジトリをフォークすることから始めます。
注: すでにリポジトリをフォークしている場合は、元のリポジトリのmasterブランチから変更をマージしてください。
フォークしたら、GithubのActionsタブに移動します。
「Enable」ボタンをクリックしてワークフローを有効にします。
これで、リポジトリにコミットをプッシュすると、GitHubがワークフローを実行します。
Heroku CLIログイン
Heroku CLIでHerokuにログインしていることを確認してください。
Herokuアプリの作成
バックエンドアプリケーションをHerokuにデプロイするには、Herokuアプリを作成する必要があります。クローンしたリポジトリのフォルダから以下のコマンドを実行します。
注:
YOUR_APP_NAME
の代わりに、任意のユニークな名前を使用してください。
チェックポイント: Heroku CLIは、アプリが正常に作成されたことをログに記録するはずです。
Heroku上でPostgreSQLデータベースをプロビジョニングする
以下のコマンドでデータベースを作成します。
チェックポイント: データベースが作成されたことを確認するには、以下が表示されるはずです。
注: Herokuは、アプリケーションのランタイムのために
DATABASE_URL
環境変数を自動的に設定します。Prisma Clientは、Prismaスキーマで設定された環境変数と一致するため、DATABASE_URL
を使用します。
GitHubでビルド時のシークレットを定義する
GitHub Actionsが本番データベースのマイグレーションを実行し、バックエンドをHerokuにデプロイできるように、GitHubのワークフローで参照されている4つのシークレットを作成します。
注: ビルド時のシークレットとランタイムシークレットには区別があります。ビルド時のシークレットはGitHubで定義され、GitHub Actionsの実行中に使用されます。一方、ランタイムシークレットはHerokuで定義され、バックエンドによって使用されます。
シークレット
HEROKU_APP_NAME
: 前の手順で選択したアプリの名前。HEROKU_EMAIL
: Herokuにサインアップした際に使用したメールアドレス。HEROKU_API_KEY
: Heroku APIキーDATABASE_URL
: デプロイ前に本番データベースのマイグレーションを実行するために必要なHeroku上の本番PostgreSQL URL。
本番のDATABASE_URL
を取得する
データベースプロビジョニング時にHerokuによって設定されたDATABASE_URL
を取得するには、以下のHeroku CLIコマンドを使用します。
チェックポイント: 出力にURLが表示されるはずです(例: postgres://username:password@ec2-12.eu-west-1.compute.amazonaws.com:5432/dbname
)。
HEROKU_API_KEY
を取得する
Heroku APIキーは、Herokuアカウント設定から取得できます。
GitHubでシークレットを作成する
4つのシークレットを作成するには、リポジトリ設定に移動し、Secretsタブを開きます。
New secretをクリックし、シークレット名に名前フィールド(例: HEROKU_APP_NAME
)を使用し、値を設定します。
チェックポイント: 4つのシークレットを作成した後、以下が表示されるはずです。
Herokuで環境変数を定義する
バックエンドは、ランタイムに環境変数としてアプリケーションに渡される3つのシークレットを必要とします。
SENDGRID_API_KEY
: SendGrid APIキー。JWT_SECRET
: JWTトークンに署名するために使用されるシークレット。DATABASE_URL
: Herokuによって自動的に設定されたデータベース接続URL。
注:
JWT_SECRET
は、ターミナルで以下のコマンドを実行して生成できます:node -e "console.log(require('crypto').randomBytes(256).toString('base64'));"
Heroku CLIでそれらを設定するには、以下のコマンドを使用します。
チェックポイント: 環境変数が設定されたことを確認するには、以下が表示されるはずです。
テストを実行してデプロイするワークフローをトリガーする
ワークフローが設定され、Heroku上にアプリが作成され、すべてのシークレットが設定されたので、テストを実行してデプロイするワークフローをトリガーできるようになりました。
ビルドをトリガーするには、空のコミットを作成してプッシュします。
コミットをプッシュしたら、GitHubリポジトリのActionsタブに移動すると、以下が表示されるはずです。
コミットメッセージのあるテーブルの最初の行をクリックします。
test
ジョブのログを表示する
test
ジョブのログを表示するには、test
をクリックすると、テストの結果を表示できます。例えば、下のスクリーンショットでは、テストの結果を見ることができます。
Herokuへのデプロイを確認する
deploy
ジョブがHerokuに正常にデプロイされたことを確認するには、左側のdeploy
をクリックし、Deploy to Heroku
ステップを展開します。ログの最後に以下の行が表示されるはずです。
ブラウザからAPIにアクセスするには、クローンしたリポジトリフォルダから以下のHeroku CLIコマンドを使用します。
これにより、https://YOUR_APP_NAME.herokuapp.com/
を指すブラウザが開きます。
チェックポイント: ブラウザに{"up":true}
と表示されるはずです。これは、ステータスエンドポイントによって提供されています。
バックエンドのログを表示する
バックエンドのログを表示するには、クローンしたリポジトリフォルダから以下のHeroku CLIコマンドを使用します。
ログインフローをテストする
ログインフローをテストするには、REST APIに2回呼び出しを行う必要があります。
まず、APIのURLを取得します。
curlでログインエンドポイントにPOST呼び出しを行います。
メールで8桁のトークンを確認し、次に2回目の呼び出しを行います。
チェックポイント: レスポンスには200の成功ステータスコードが含まれ、JWTトークンを含むAuthorization
ヘッダーがあるはずです。
まとめ
バックエンドがデプロイされ、稼働しました。よくできました!
GitHub Actionsワークフローを定義し、Herokuアプリを作成し、PostgreSQLデータベースをプロビジョニングし、GitHub Actionsを使用してバックエンドをHerokuにデプロイすることで、継続的インテグレーションとデプロイメントを設定しました。
リポジトリにコミットして変更をプッシュすることで新しい機能を導入すると、テストとTypeScriptコンパイラが自動的に実行され、成功すればバックエンドがデプロイされます。
Herokuダッシュボードにアクセスすると、メモリ使用量、応答時間、スループットなどのメトリクスを表示できます。これは、バックエンドが異なるトラフィック量をどのように処理するかを把握するのに役立ちます。例えば、バックエンドへの負荷が増加すると、応答時間が遅くなる可能性があります。
TypeScriptをPrisma Clientと共に使用することで、通常ランタイムで検出されデバッグを必要とする型エラーのクラスを排除できます。
バックエンドの完全なソースコードはGitHubで確認できます。
Prismaはリレーショナルデータベースとの作業を容易にすることを目指していますが、基盤となるデータベースとHerokuの具体的な詳細を理解することは有益です。
ご質問があれば、お気軽にTwitterでご連絡ください。
次回の投稿もお見逃しなく!
Prismaニュースレターに登録