はじめに
このチュートリアルでは、Webhook イベントに応答して API 要求を行う GitHub App を作成するコードを記述する方法について説明します。 具体的には、アプリにアクセス権が付与されているリポジトリで pull request が開かれると、アプリは pull request の Webhook イベントを受け取ります。 次に、アプリは GitHub の API を使って、pull request にコメントを追加します。
このチュートリアルでは、アプリの開発中にご自身のコンピューターまたは codespace をサーバーとして使います。 アプリを運用環境で使用する準備ができたら、アプリを専用サーバーにデプロイする必要があります。
このチュートリアルでは JavaScript を使いますが、サーバーで実行できる任意のプログラミング言語を使用できます。
webhook について
GitHub App を登録するときに、Webhook URL を指定して、Webhook イベントをサブスクライブできます。 GitHub 上のアクティビティによってアプリがサブスクライブされているイベントがトリガーされると、GitHub からアプリの Webhook URL に Webhook イベントが送信されます。
たとえば、pull request の Webhook イベントに対して、GitHub App をサブスクライブすることができます。 アプリにアクセス権が付与されているリポジトリで pull request が開かれると、GitHub からそのアプリの Webhook URL に pull request の Webhook イベントが送信されます。 複数のアクションでそのイベントをトリガーできる場合は、イベントをトリガーしたアクションの種類を示す action
フィールドがイベント ペイロードに含まれます。 この例では、pull request が開かれたためにイベントがトリガーされたので、action
の値は opened
になります。
これらの Webhook イベントをリッスンしているサーバー上でアプリが実行されている場合は、アプリで Webhook イベントを受け取ったときにアクションを実行できます。 たとえば、pull request の Webhook イベントを受け取ったときに、アプリで GitHub API を使って pull request にコメントを投稿できます。
詳しくは、「GitHub Apps での Webhook の使用」を参照してください。 使用できる Webhook イベントとアクションについて詳しくは、「Webhook のイベントとペイロード」を参照してください。
前提条件
このチュートリアルでは、お使いのコンピュータまたは codespace で Node.js バージョン 20 以降と npm バージョン 6.12.0 以降が実行されている必要があります。 詳しくは、Node.js のページを参照してください。
このチュートリアルでは、JavaScript と ES6 の基本的な構文を理解していることを前提としています。
セットアップ
以下のセクションでは、次のコンポーネントを設定します。
- アプリのコードを格納するリポジトリ
- Webhook をローカルで受信する方法
- "pull request" Webhook イベントにサブスクライブされ、pull request にコメントを追加するアクセス許可を持ち、ローカルで受信できる Webhook URL を使う、GitHub App 登録
アプリのコードを格納するリポジトリを作成する
- アプリのコードを格納するリポジトリを作成します。 詳しくは、「新しいリポジトリの作成」を参照してください。
- 前の手順のリポジトリをクローンします。 詳しくは、「リポジトリをクローンする」を参照してください。 ローカル クローンまたは GitHub Codespaces を使用できます。
- ターミナルで、クローンが格納されているディレクトリに移動します。
- ディレクトリに
.gitignore
ファイルがまだ含まれていない場合は、.gitignore
ファイルを追加します。 後でこのファイルにコンテンツを追加します。.gitignore
ファイルについて詳しくは、「ファイルを無視する」を参照してください。
後の手順で、このリポジトリにさらにコードを追加します。
Webhook プロキシ URL を取得する
アプリをローカルで開発するには、Webhook プロキシ URL を使って、GitHub からお使いのコンピューターまたは codespace に Webhook を転送できます。 このチュートリアルでは、Smee.io を使って Webhook プロキシ URL を指定し、Webhook を転送します。
- ブラウザーで https://smee.io/ にアクセスします。
- [Start a new channel] (新しいチャネルの開始) をクリックします。
- [Webhook Proxy URL] (Webhook プロキシ URL) の下にある完全な URL をコピーします。 この URL は、後の手順で使用します。
GitHub App を登録する
このチュートリアルでは、次のような GitHub App 登録が必要になります。
- Webhook がアクティブになっている
- ローカルで受信できる Webhook URL を使用する
- "pull request" リポジトリのアクセス許可がある
- "pull request" Webhook イベントをサブスクライブする
以下の手順では、これらの設定で GitHub App を登録する方法について説明します。 GitHub App の設定について詳しくは、「GitHub App の登録」をご覧ください。
-
GitHub の任意のページの右上隅にある、自分のプロファイル写真をクリックします。
-
アカウント設定にアクセスしてください。
- 個人用アカウントが所有するアプリの場合は、[設定] をクリックします。
- 組織が所有するアプリの場合:
- [自分の組織] をクリックします。
- 組織の右側にある [設定] をクリックします。
- Enterprise が所有するアプリの場合:
- Enterprise Managed Users を使用する場合は、[Enterprise] をクリックして Enterprise アカウントの設定に移動します。
- 個人用アカウントを使用する場合は、[Enterprise] をクリックしてから、Enterprise の右側にある [設定] をクリックします。
-
GitHub App 設定にアクセスしてください。
- 個人用アカウントまたは組織が所有するアプリの場合:
- 左側のサイドバーで、 [開発者向け設定] をクリックし、 [GitHub Apps] をクリックします。
- Enterprise が所有するアプリの場合:
- 左側のサイドバーで、 [設定] から GitHub Apps をクリックします。
- 個人用アカウントまたは組織が所有するアプリの場合:
-
[新しい GitHub App] をクリックします。
-
[GitHub App 名] に、アプリの名前を入力します。 たとえば、
USERNAME-webhook-test-app
です。USERNAME
はご自身の GitHub ユーザー名です。 -
[ホームページの URL] の下に、アプリの URL を入力します。 たとえば、アプリのコードを格納するために作成したリポジトリの URL を使用できます。
-
このチュートリアルでは、[ユーザーの特定と認可] と [インストール後] のセクションはスキップします。 これらの設定について詳しくは、「GitHub App の登録」を参照してください。
-
[Webhook] の下で [アクティブ] が選択されていることを確認します。
-
[Webhook URL] の下に、前の Webhook プロキシ URL を入力します。 詳しくは、「Webhook プロキシ URL を取得する」を参照してください。
-
[Webhook シークレット] に、ランダムな文字列を入力します。 この文字列は後で使用します。
-
[リポジトリのアクセス許可] で、[pull request] の横にある [読み取りおよび書き込み] を選択します。
-
[イベントのサブスクライブ] で、 [pull request] を選択します。
-
[この GitHub App をインストールできる場所] で、 [このアカウントのみ] を選択します。 これは、後でアプリを公開する場合変更できます。
Note
GitHub App が Enterprise に登録されている場合、この手順は適用されません。
-
[GitHub App を作成する] をクリックします。
アプリのコードを記述する
以下のセクションでは、アプリが Webhook イベントに応答するようにコードを記述する方法について説明します。
依存関係のインストール
このチュートリアルでは、GitHub の octokit
モジュールを使って Webhook イベントを処理し、API 要求を行います。 Octokit.js の詳細については、「REST API と JavaScript を使用したスクリプト」と Octokit.js の README を参照してください。
このチュートリアルでは、dotenv
モジュールを使って、.env
ファイルからアプリに関する情報を読み取ります。 詳しくは、dotenv に関するページを参照してください。
このチュートリアルでは、Smee.io を使って Webhook を GitHub からローカル サーバーに転送します。 詳しくは、smee-client に関するページを参照してください。
- ターミナルで、クローンが格納されているディレクトリに移動します。
npm init --yes
を実行して、npm の既定値を使ってpackage.json
ファイルを作成します。npm install octokit
を実行します。npm install dotenv
を実行します。npm install smee-client --save-dev
を実行します。 アプリの開発中は Webhook の転送に Smee.io だけを使うので、これは開発の依存関係です。.gitignore
ファイルにnode_modules
を追加します。
アプリの識別情報と資格情報を格納する
このチュートリアルでは、アプリの資格情報と識別情報を環境変数として .env
ファイルに格納する方法を示します。 アプリをデプロイするときに、資格情報の保存方法を変更することをお勧めします。 詳しくは、「アプリのデプロイ」を参照してください。
資格情報をローカルに格納するため、以下の手順を実行する前に、ご自分がセキュリティで保護されたコンピュータで作業していることを確認してください。
-
ターミナルで、クローンが格納されているディレクトリに移動します。
-
このディレクトリの最上位レベルに
.env
という名前のファイルを作成します。 -
.gitignore
ファイルに.env
を追加します。 こうすることで、アプリの資格情報を誤ってコミットするのを防ぐことができます。 -
次の内容を
.env
ファイルに追加します。 値は後の手順で更新します。Text APP_ID="YOUR_APP_ID" WEBHOOK_SECRET="YOUR_WEBHOOK_SECRET" PRIVATE_KEY_PATH="YOUR_PRIVATE_KEY_PATH"
APP_ID="YOUR_APP_ID" WEBHOOK_SECRET="YOUR_WEBHOOK_SECRET" PRIVATE_KEY_PATH="YOUR_PRIVATE_KEY_PATH"
-
アプリの設定ページに移動します。
-
GitHub の任意のページの右上隅にある、自分のプロファイル写真をクリックします。
-
アカウント設定にアクセスしてください。
- 個人用アカウントが所有するアプリの場合は、[設定] をクリックします。
- 組織が所有するアプリの場合:
- [自分の組織] をクリックします。
- 組織の右側にある [設定] をクリックします。
- Enterprise が所有するアプリの場合:
- Enterprise Managed Users を使用する場合は、[Enterprise] をクリックして Enterprise アカウントの設定に移動します。
- 個人用アカウントを使用する場合は、[Enterprise] をクリックしてから、Enterprise の右側にある [設定] をクリックします。
-
左側のサイドバーで [ 開発者設定] をクリックします。
-
左側のサイドバーで、 [GitHub Apps] をクリックします。
-
アプリの名前の横にある [編集] をクリックします。
-
-
アプリの設定ページで、[アプリ ID] の横にある自分のアプリのアプリ ID を確認します。
-
.env
ファイルで、YOUR_APP_ID
を自分のアプリのアプリ ID に置き換えます。 -
アプリの設定ページの [秘密キー] で、 [秘密キーの生成] をクリックします。 お手元のコンピュータにダウンロードされた PEM フォーマットの秘密鍵が表示されます。 詳しくは、「GitHub Apps の秘密キーの管理」を参照してください。
-
codespace を使用している場合は、ダウンロードした PEM ファイルを codespace に移動して、codespace がファイルにアクセスできるようにします。
-
.env
ファイルで、YOUR_PRIVATE_KEY_PATH
を秘密キーへの完全なパス (.pem
拡張子を含む) に置き換えます。 -
.env
ファイルで、YOUR_WEBHOOK_SECRET
をアプリの Webhook シークレットに置き換えます。 Webhook シークレットを忘れた場合は、[Webhook シークレット (省略可能)] の下の [シークレットの変更] をクリックします。 新しいシークレットを入力し、 [変更の保存] をクリックします。
Webhook イベントに応答するコードを追加する
クローンが格納されているディレクトリの最上位レベルに、アプリのコードを保持する JavaScript ファイルを作成します。 このチュートリアルでは、ファイルに app.js
という名前を付けます。
次のコードを app.js
に追加します。 コードには、各部分を説明する注釈が含まれています。
// These are the dependencies for this file. // // You installed the `dotenv` and `octokit` modules earlier. The `@octokit/webhooks` is a dependency of the `octokit` module, so you don't need to install it separately. The `fs` and `http` dependencies are built-in Node.js modules. import dotenv from "dotenv"; import {App} from "octokit"; import {createNodeMiddleware} from "@octokit/webhooks"; import fs from "fs"; import http from "http"; // This reads your `.env` file and adds the variables from that file to the `process.env` object in Node.js. dotenv.config(); // This assigns the values of your environment variables to local variables. const appId = process.env.APP_ID; const webhookSecret = process.env.WEBHOOK_SECRET; const privateKeyPath = process.env.PRIVATE_KEY_PATH; // This reads the contents of your private key file. const privateKey = fs.readFileSync(privateKeyPath, "utf8"); // This creates a new instance of the Octokit App class. const app = new App({ appId: appId, privateKey: privateKey, webhooks: { secret: webhookSecret }, }); // This defines the message that your app will post to pull requests. const messageForNewPRs = "Thanks for opening a new PR! Please follow our contributing guidelines to make your PR easier to review."; // This adds an event handler that your code will call later. When this event handler is called, it will log the event to the console. Then, it will use GitHub's REST API to add a comment to the pull request that triggered the event. async function handlePullRequestOpened({octokit, payload}) { console.log(`Received a pull request event for #${payload.pull_request.number}`); try { await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", { owner: payload.repository.owner.login, repo: payload.repository.name, issue_number: payload.pull_request.number, body: messageForNewPRs, headers: { "x-github-api-version": "2022-11-28", }, }); } catch (error) { if (error.response) { console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`) } console.error(error) } }; // This sets up a webhook event listener. When your app receives a webhook event from GitHub with a `X-GitHub-Event` header value of `pull_request` and an `action` payload value of `opened`, it calls the `handlePullRequestOpened` event handler that is defined above. app.webhooks.on("pull_request.opened", handlePullRequestOpened); // This logs any errors that occur. app.webhooks.onError((error) => { if (error.name === "AggregateError") { console.error(`Error processing request: ${error.event}`); } else { console.error(error); } }); // This determines where your server will listen. // // For local development, your server will listen to port 3000 on `localhost`. When you deploy your app, you will change these values. For more information, see "[Deploy your app](#deploy-your-app)." const port = 3000; const host = 'localhost'; const path = "/api/webhook"; const localWebhookUrl = `http://${host}:${port}${path}`; // This sets up a middleware function to handle incoming webhook events. // // Octokit's `createNodeMiddleware` function takes care of generating this middleware function for you. The resulting middleware function will: // // - Check the signature of the incoming webhook event to make sure that it matches your webhook secret. This verifies that the incoming webhook event is a valid GitHub event. // - Parse the webhook event payload and identify the type of event. // - Trigger the corresponding webhook event handler. const middleware = createNodeMiddleware(app.webhooks, {path}); // This creates a Node.js server that listens for incoming HTTP requests (including webhook payloads from GitHub) on the specified port. When the server receives a request, it executes the `middleware` function that you defined earlier. Once the server is running, it logs messages to the console to indicate that it is listening. http.createServer(middleware).listen(port, () => { console.log(`Server is listening for events at: ${localWebhookUrl}`); console.log('Press Ctrl + C to quit.') });
import dotenv from "dotenv";
import {App} from "octokit";
import {createNodeMiddleware} from "@octokit/webhooks";
import fs from "fs";
import http from "http";
These are the dependencies for this file.
You installed the dotenv
and octokit
modules earlier. The @octokit/webhooks
is a dependency of the octokit
module, so you don't need to install it separately. The fs
and http
dependencies are built-in Node.js modules.
dotenv.config();
This reads your .env
file and adds the variables from that file to the process.env
object in Node.js.
const appId = process.env.APP_ID;
const webhookSecret = process.env.WEBHOOK_SECRET;
const privateKeyPath = process.env.PRIVATE_KEY_PATH;
This assigns the values of your environment variables to local variables.
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
This reads the contents of your private key file.
const app = new App({
appId: appId,
privateKey: privateKey,
webhooks: {
secret: webhookSecret
},
});
This creates a new instance of the Octokit App class.
const messageForNewPRs = "Thanks for opening a new PR! Please follow our contributing guidelines to make your PR easier to review.";
This defines the message that your app will post to pull requests.
async function handlePullRequestOpened({octokit, payload}) {
console.log(`Received a pull request event for #${payload.pull_request.number}`);
try {
await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number: payload.pull_request.number,
body: messageForNewPRs,
headers: {
"x-github-api-version": "2022-11-28",
},
});
} catch (error) {
if (error.response) {
console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
}
console.error(error)
}
};
This adds an event handler that your code will call later. When this event handler is called, it will log the event to the console. Then, it will use GitHub's REST API to add a comment to the pull request that triggered the event.
app.webhooks.on("pull_request.opened", handlePullRequestOpened);
This sets up a webhook event listener. When your app receives a webhook event from GitHub with a X-GitHub-Event
header value of pull_request
and an action
payload value of opened
, it calls the handlePullRequestOpened
event handler that is defined above.
app.webhooks.onError((error) => {
if (error.name === "AggregateError") {
console.error(`Error processing request: ${error.event}`);
} else {
console.error(error);
}
});
This logs any errors that occur.
const port = 3000;
const host = 'localhost';
const path = "/api/webhook";
const localWebhookUrl = `http://${host}:${port}${path}`;
This determines where your server will listen.
For local development, your server will listen to port 3000 on localhost
. When you deploy your app, you will change these values. For more information, see "Deploy your app."
const middleware = createNodeMiddleware(app.webhooks, {path});
This sets up a middleware function to handle incoming webhook events.
Octokit's createNodeMiddleware
function takes care of generating this middleware function for you. The resulting middleware function will:
- Check the signature of the incoming webhook event to make sure that it matches your webhook secret. This verifies that the incoming webhook event is a valid GitHub event.
- Parse the webhook event payload and identify the type of event.
- Trigger the corresponding webhook event handler.
http.createServer(middleware).listen(port, () => {
console.log(`Server is listening for events at: ${localWebhookUrl}`);
console.log('Press Ctrl + C to quit.')
});
This creates a Node.js server that listens for incoming HTTP requests (including webhook payloads from GitHub) on the specified port. When the server receives a request, it executes the middleware
function that you defined earlier. Once the server is running, it logs messages to the console to indicate that it is listening.
// These are the dependencies for this file.
//
// You installed the `dotenv` and `octokit` modules earlier. The `@octokit/webhooks` is a dependency of the `octokit` module, so you don't need to install it separately. The `fs` and `http` dependencies are built-in Node.js modules.
import dotenv from "dotenv";
import {App} from "octokit";
import {createNodeMiddleware} from "@octokit/webhooks";
import fs from "fs";
import http from "http";
// This reads your `.env` file and adds the variables from that file to the `process.env` object in Node.js.
dotenv.config();
// This assigns the values of your environment variables to local variables.
const appId = process.env.APP_ID;
const webhookSecret = process.env.WEBHOOK_SECRET;
const privateKeyPath = process.env.PRIVATE_KEY_PATH;
// This reads the contents of your private key file.
const privateKey = fs.readFileSync(privateKeyPath, "utf8");
// This creates a new instance of the Octokit App class.
const app = new App({
appId: appId,
privateKey: privateKey,
webhooks: {
secret: webhookSecret
},
});
// This defines the message that your app will post to pull requests.
const messageForNewPRs = "Thanks for opening a new PR! Please follow our contributing guidelines to make your PR easier to review.";
// This adds an event handler that your code will call later. When this event handler is called, it will log the event to the console. Then, it will use GitHub's REST API to add a comment to the pull request that triggered the event.
async function handlePullRequestOpened({octokit, payload}) {
console.log(`Received a pull request event for #${payload.pull_request.number}`);
try {
await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
owner: payload.repository.owner.login,
repo: payload.repository.name,
issue_number: payload.pull_request.number,
body: messageForNewPRs,
headers: {
"x-github-api-version": "2022-11-28",
},
});
} catch (error) {
if (error.response) {
console.error(`Error! Status: ${error.response.status}. Message: ${error.response.data.message}`)
}
console.error(error)
}
};
// This sets up a webhook event listener. When your app receives a webhook event from GitHub with a `X-GitHub-Event` header value of `pull_request` and an `action` payload value of `opened`, it calls the `handlePullRequestOpened` event handler that is defined above.
app.webhooks.on("pull_request.opened", handlePullRequestOpened);
// This logs any errors that occur.
app.webhooks.onError((error) => {
if (error.name === "AggregateError") {
console.error(`Error processing request: ${error.event}`);
} else {
console.error(error);
}
});
// This determines where your server will listen.
//
// For local development, your server will listen to port 3000 on `localhost`. When you deploy your app, you will change these values. For more information, see "[Deploy your app](#deploy-your-app)."
const port = 3000;
const host = 'localhost';
const path = "/api/webhook";
const localWebhookUrl = `http://${host}:${port}${path}`;
// This sets up a middleware function to handle incoming webhook events.
//
// Octokit's `createNodeMiddleware` function takes care of generating this middleware function for you. The resulting middleware function will:
//
// - Check the signature of the incoming webhook event to make sure that it matches your webhook secret. This verifies that the incoming webhook event is a valid GitHub event.
// - Parse the webhook event payload and identify the type of event.
// - Trigger the corresponding webhook event handler.
const middleware = createNodeMiddleware(app.webhooks, {path});
// This creates a Node.js server that listens for incoming HTTP requests (including webhook payloads from GitHub) on the specified port. When the server receives a request, it executes the `middleware` function that you defined earlier. Once the server is running, it logs messages to the console to indicate that it is listening.
http.createServer(middleware).listen(port, () => {
console.log(`Server is listening for events at: ${localWebhookUrl}`);
console.log('Press Ctrl + C to quit.')
});
アプリのコードを実行するスクリプトを追加する
-
package.json
ファイル内のscripts
オブジェクトに、node app.js
を実行するserver
という名前のスクリプトを追加します。 次に例を示します。JSON "scripts": { "server": "node app.js" }
"scripts": { "server": "node app.js" }
app.js
以外のアプリのコードを保持するファイルを呼び出した場合は、app.js
を、アプリのコードを保持するファイルへの相対パスに置き換えます。 -
package.json
ファイルに、最上位レベルのキーtype
を値module
で追加します。 次に例を示します。{ // rest of the JSON object, "version": "1.0.0", "description": "", "type": "module", // rest of the JSON object, }
package.json
ファイルは次のようになります。 name
の値と、dependencies
と devDependencies
のバージョン番号は、お客様のものとは異なる場合があります。
{
"name": "github-app-webhook-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"server": "node app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^16.0.3",
"octokit": "^2.0.14"
},
"devDependencies": {
"smee-client": "^1.2.3"
}
}
テスト
次の手順に従って、上記で作成したアプリをテストします。
アプリのインストール
アプリでリポジトリの pull request にコメントを残すには、リポジトリを所有するアカウントでアプリをインストールし、そのリポジトリへのアクセス許可を付与する必要があります。 アプリはプライベートであるため、アプリを所有するアカウントでのみインストールできます。
-
作成したアプリを所有するアカウントで、アプリをインストールする新しいリポジトリを作成します。 詳しくは、「新しいリポジトリの作成」を参照してください。
-
アプリの設定ページに移動します。
-
GitHub の任意のページの右上隅にある、自分のプロファイル写真をクリックします。
-
アカウント設定にアクセスしてください。
- 個人用アカウントが所有するアプリの場合は、[設定] をクリックします。
- 組織が所有するアプリの場合:
- [自分の組織] をクリックします。
- 組織の右側にある [設定] をクリックします。
- Enterprise が所有するアプリの場合:
- Enterprise Managed Users を使用する場合は、[Enterprise] をクリックして Enterprise アカウントの設定に移動します。
- 個人用アカウントを使用する場合は、[Enterprise] をクリックしてから、Enterprise の右側にある [設定] をクリックします。
-
左側のサイドバーで [ 開発者設定] をクリックします。
-
左側のサイドバーで、 [GitHub Apps] をクリックします。
-
アプリの名前の横にある [編集] をクリックします。
-
-
[パブリック ページ] をクリックします。
-
[インストール] をクリックします。
-
[選択したリポジトリのみ] を選択します。
-
[リポジトリの選択] ドロップダウン メニューを選択し、このセクションのはじめに選択したリポジトリをクリックします。
-
[インストール] をクリックします。
サーバーを起動する
テストのために、ご自身のコンピュータまたは codespace をサーバーとして使います。 アプリは、サーバーが実行中のときにのみ Webhook に応答します。
-
ターミナルで、アプリのコードが格納されているディレクトリに移動します。
-
Smee.io から転送された Webhook を受信するには、
npx smee -u WEBHOOK_PROXY_URL -t http://localhost:3000/api/webhook
を実行します。WEBHOOK_PROXY_URL
を、以前の Webhook プロキシ URL に置き換えます。 URL を忘れた場合は、アプリの設定ページの [Webhook URL] フィールドで確認できます。次のような出力が表示されます。
WEBHOOK_PROXY_URL
は Webhook プロキシ URL です。Forwarding WEBHOOK_PROXY_URL to http://localhost:3000/api/webhook Connected WEBHOOK_PROXY_URL
-
2 つ目のターミナル ウィンドウで、アプリのコードが格納されているディレクトリに移動します。
-
npm run server
を実行します。 ターミナルにServer is listening for events at: http://localhost:3000/api/webhook
と表示されるはずです。
アプリをテストする
これでサーバーが実行され、転送された Webhook イベントを受信するようになったので、アプリのインストール時に選択したリポジトリで pull request を開いてアプリをテストします。
-
アプリのインストール時に選択したリポジトリで pull request を開きます。 詳しくは、「pull request の作成」を参照してください。
アプリのコードが格納されているリポジトリではなく、アプリのインストール時に選択したリポジトリを必ず使用してください。 詳しくは、「アプリのインストール」を参照してください。
-
smee.io の Webhook プロキシ URL に移動します。
pull_request
イベントが表示されます。 これは、pull request を作成したときに GitHub から正常に pull request イベントが送信されたことを示しています。 -
npm run server
を実行したターミナルには、"#1 の pull request イベントを受信しました" のようなメッセージが表示されます。#
の後の整数は、開いた pull request の番号です。 -
pull request のタイムラインに、アプリからのコメントが表示されます。
-
両方のターミナル ウィンドウで、Ctrl+C キーを押してサーバーを停止し、転送された Webhook のリッスンを停止します。
次の手順
これで Webhook イベントに応答するアプリを作成できたので、アプリのコードを拡張し、アプリをデプロイし、アプリを公開することができます。
アプリのコードを変更する
このチュートリアルでは、pull request が開かれたときに pull request にコメントを投稿する方法を示しました。 コードを更新して、さまざまな種類の Webhook イベントに応答したり、Webhook イベントに応答して異なる処理を行ったりすることができます。
行いたい API 要求や受信したい Webhook イベントのためにアプリに追加のアクセス許可が必要になる場合は、忘れずにアプリのアクセス許可を更新してください。 詳しくは、「GitHub アプリのアクセス許可を選択する」を参照してください。
このチュートリアルでは、すべてのコードを 1 つのファイルに保存しましたが、関数とコンポーネントを別のファイルに移動することもできます。
アプリのデプロイ
このチュートリアルでは、アプリをローカルで開発する方法を示しました。 アプリをデプロイする準備ができたら、アプリを提供し、アプリの資格情報をセキュリティで保護するために変更を加える必要があります。 実行する手順は使うサーバーによって異なりますが、以下のセクションでは一般的なガイダンスを提供します。
サーバーでアプリをホストする
このチュートリアルでは、コンピュータまたは codespace をサーバーとして使用しました。 アプリを運用環境で使用する準備ができたら、アプリを専用サーバーにデプロイする必要があります。 たとえば、Azure App Service を使用できます。
Webhook URL を更新する
GitHub から Webhook トラフィックを受信するようにサーバーを設定したら、アプリの設定で Webhook URL を更新します。 運用環境では Webhook を転送するために Smee.io を使用しないでください。
port
定数と host
定数を更新する
アプリをデプロイするときに、サーバーがリッスンするホストとポートを変更する必要があります。
たとえば、サーバーの PORT
環境変数を設定して、サーバーがリッスンするポートを示すことができます。 サーバーの NODE_ENV
環境変数を production
に設定できます。 次に、コードで port
定数と host
定数を定義している箇所を更新して、サーバーがデプロイ ポートでローカル ネットワーク インターフェイス (localhost
) ではなく、使用可能なすべてのネットワーク インターフェイス (0.0.0.0
) をリッスンするように設定することができます。
const port = process.env.PORT || 3000; const host = process.env.NODE_ENV === 'production' ? '0.0.0.0' : 'localhost';
const port = process.env.PORT || 3000;
const host = process.env.NODE_ENV === 'production' ? '0.0.0.0' : 'localhost';
アプリの資格情報をセキュリティで保護する
アプリの秘密キーや Webhook シークレットは絶対に公開しないでください。 このチュートリアルでは、gitignore の .env
ファイルにアプリの資格情報を格納しました。 アプリをデプロイする際に、資格情報を保存する安全な方法を選び、それに応じて値を取得するようにコードを更新する必要があります。 たとえば、Azure Key Vault などのシークレット管理サービスを使って資格情報を格納できます。 アプリを実行するときに、アプリで資格情報を取得し、アプリがデプロイされているサーバー上の環境変数に格納できます。
詳しくは、「GitHub App を作成するためのベスト プラクティス」を参照してください。
アプリを共有する
アプリを他のユーザーや組織と共有したい場合は、アプリを公開します。 詳しくは、「GitHub Appをパブリックまたはプライベートにする」を参照してください。
ベスト プラクティスに従う
GitHub App に関するベスト プラクティスに従うようにする必要があります。 詳しくは、「GitHub App を作成するためのベスト プラクティス」を参照してください。