소개
이 자습서에서는 웹후크 이벤트에 대한 응답으로 API 요청을 하는 GitHub App을(를) 만드는 코드를 작성하는 방법을 보여 줍니다. 특히 앱에 대한 액세스 권한이 부여된 리포지토리에서 끌어오기 요청이 열리면 앱은 끌어오기 요청 웹후크 이벤트를 받게 됩니다. 그런 다음 앱은 GitHub의 API를 사용하여 끌어오기 요청에 주석을 추가합니다.
이 자습서에서는 앱을 개발하는 동안 컴퓨터 또는 codespace를 서버로 사용합니다. 앱이 프로덕션 사용을 위해 준비되면 앱을 전용 서버에 배포해야 합니다.
이 자습서에서는 JavaScript를 사용하지만 서버에서 실행할 수 있는 모든 프로그래밍 언어를 사용할 수 있습니다.
웹후크 정보
GitHub App을(를) 등록할 때 웹후크 URL을 지정하고 웹후크 이벤트를 구독할 수 있습니다. GitHub의 활동이 앱이 구독되는 이벤트를 트리거하면 GitHub이(가) 웹후크 이벤트를 앱의 웹후크 URL로 보냅니다.
예를 들어 GitHub App을(를) 끌어오기 요청 웹후크 이벤트에 구독할 수 있습니다. 앱에 대한 액세스 권한이 부여된 리포지토리에서 끌어오기 요청이 열리면 GitHub은(는) 끌어오기 요청 웹후크 이벤트를 앱의 웹후크 URL로 보냅니다. 여러 작업이 이벤트를 트리거할 수 있는 경우 이벤트 페이로드에는 이벤트를 트리거한 작업 유형을 나타내는 action
필드가 포함됩니다. 이 예제에서는 끌어오기 요청이 열렸기 때문에 이벤트가 트리거된 이후 action
의 값은 opened
입니다.
앱이 이러한 웹후크 이벤트를 수신 대기하는 서버에서 실행되는 경우 앱은 웹후크 이벤트를 수신할 때 작업을 수행할 수 있습니다. 예를 들어 앱은 끌어오기 요청 웹후크 이벤트를 수신할 때 GitHub API를 사용하여 끌어오기 요청에 주석을 게시할 수 있습니다.
자세한 내용은 "GitHub 앱에 웹후크 사용"을(를) 참조하세요. 가능한 웹후크 이벤트 및 작업에 대한 자세한 내용은 "웹후크 이벤트 및 페이로드"을(를) 참조하세요.
필수 조건
이 자습서에서는 Node.js 버전 20 이상 및 npm 버전 6.12.0 이상을 실행하기 위한 컴퓨터 또는 codespace가 필요합니다. 자세한 내용은 Node.js를 참조하세요.
이 자습서에서는 JavaScript 및 ES6 구문에 대한 기본적인 이해가 있다고 가정합니다.
설정
다음 섹션에서는 다음 구성 요소를 설정하는 과정을 안내합니다.
- 앱에 대한 코드를 저장할 리포지토리
- 웹후크를 로컬로 받는 방법
- "끌어오기 요청" 웹후크 이벤트를 구독하고, 끌어오기 요청에 주석을 추가할 수 있는 권한이 있으며, 로컬에서 받을 수 있는 웹후크 URL을 사용하는 GitHub App 등록
앱에 대한 코드를 저장할 리포지토리 만들기
- 앱에 대한 코드를 저장할 리포지토리를 만듭니다. 자세한 내용은 "새 리포지토리 만들기"을(를) 참조하세요.
- 이전 단계에서 리포지토리를 복제합니다. 자세한 내용은 "리포지토리 복제"을(를) 참조하세요. 로컬 복제본 또는 GitHub Codespaces을(를) 사용할 수 있습니다.
- 터미널에서 복제본이 저장된 디렉터리로 이동합니다.
- 디렉터리에 아직
.gitignore
파일이 포함되어 있지 않으면.gitignore
파일을 추가합니다. 나중에 이 파일에 콘텐츠를 추가할 것입니다..gitignore
파일에 대한 자세한 내용은 "Ignoring files(파일 무시)"을(를) 참조하세요.
이후 단계에서 이 리포지토리에 코드를 더 추가할 것입니다.
웹후크 프록시 URL 가져오기
로컬로 앱을 개발하려면 웹후크 프록시 URL을 사용하여 웹후크를 GitHub에서 컴퓨터 또는 codespace로 전달할 수 있습니다. 이 자습서에서는 Smee.io 사용하여 웹후크 프록시 URL를 제공하고 웹후크를 전달합니다.
- 브라우저에서 https://smee.io/로 이동합니다.
- 새 채널 시작을 클릭합니다.
- "웹후크 프록시 URL"에서 전체 URL을 복사합니다. 이 URL은 이후 단계에서 사용합니다.
GitHub App 등록하기
이 자습서에서는 다음과 같은 GitHub App 등록이 있어야 합니다.
- 웹후크 활성 상태
- 로컬로 수신할 수 있는 웹후크 URL 사용
- "끌어오기 요청" 리포지토리 권한 있음
- "끌어오기 요청" 웹후크 이벤트 구독
다음 단계에서는 이러한 설정으로 GitHub App을(를) 등록하는 방법을 안내합니다. GitHub Apps 설정에 대한 자세한 내용은 "GitHub 앱 등록"을 참조하세요.
- GitHub Enterprise Server의 페이지 오른쪽 위 모서리에서 프로필 사진을 클릭합니다.
- 계정 설정으로 이동합니다.
- 개인 계정 소유한 앱의 경우 설정을 클릭합니다.
- 조직이 소유한 앱의 경우:
- 사용자의 조직을 클릭합니다.
- 조직 오른쪽에서 설정을 클릭합니다.
- 왼쪽 사이드바에서 개발자 설정을 클릭합니다.
- 왼쪽 사이드바에서 GitHub Apps 을 클릭합니다.
- 새 GitHub 앱을 클릭합니다.
- "GitHub 앱 이름"에서 앱의 이름을 입력합니다. 예를 들어
USERNAME-webhook-test-app
에서USERNAME
은 GitHub 사용자 이름입니다. - "홈페이지 URL"에서 앱의 URL을 입력합니다. 예를 들어 생성한 리포지토리의 URL을 사용하여 앱에 대한 코드를 저장할 수 있습니다.
- 이 자습서의 "사용자 식별 및 권한 부여" 및 "설치 후" 섹션은 건너뜁니다. 이러한 설정에 대한 자세한 내용은 "GitHub 앱 등록"을(를) 참조하세요.
- "웹후크"에서 활성이 선택되어 있는지 확인합니다.
- "웹후크 URL"에서 이전 웹후크 프록시 URL을 입력합니다. 자세한 내용은 "웹후크 프록시 URL 가져오기"를 참조하세요.
- "웹후크 비밀"에서 임의의 문자열을 입력합니다. 해당 문자열은 이후에 사용합니다.
- "리포지토리 권한"의 "끌어오기 요청" 옆에 있는 읽기 및 쓰기를 선택합니다.
- "이벤트 구독"에서 끌어오기 요청을 선택합니다.
- "이 GitHub 앱을 설치할 수 있는 위치"에서 이 계정만을 선택합니다. 나중에 앱을 게시하려는 경우 이를 변경할 수 있습니다.
- GitHub 앱 만들기를 클릭합니다.
앱의 코드 작성하기
다음 섹션에서는 앱이 웹후크 이벤트에 응답하도록 코드를 작성하는 방법을 안내합니다.
종속성 설치
이 자습서에서는 GitHub의 octokit
모듈을 사용하여 웹후크 이벤트를 처리하고 API 요청을 수행합니다. Octokit.js에 대한 자세한 내용은 "REST API 및 JavaScript를 사용하여 스크립팅" 및 Octokit.js 추가 정보를 참조하세요.
이 자습서에서는 dotenv
모듈을 사용하여 .env
파일에서 앱에 대한 정보를 읽습니다. 자세한 내용은 dotenv를 참조하세요.
이 자습서에서는 Smee.io 사용하여 웹후크를 GitHub에서 로컬 서버로 전달합니다. 자세한 내용은 smee-client를 참조하세요.
- 터미널에서 복제본이 저장된 디렉터리로 이동합니다.
- npm 기본값을 사용하여
package.json
파일을 만들려면npm init --yes
를 실행합니다. npm install octokit
를 실행합니다.npm install dotenv
를 실행합니다.npm install smee-client --save-dev
를 실행합니다. 앱을 개발하는 동안에 Smee.io만 사용하여 웹후크를 전달하므로 이는 개발 종속성입니..gitignore
파일에node_modules
를 추가 합니다.
앱의 식별 정보 및 자격 증명 저장
이 자습서에서는 앱의 자격 증명과 식별 정보를 .env
파일의 환경 변수로 저장하는 방법을 보여 줍니다. 앱을 배포할 때 자격 증명을 저장하는 방법을 변경하려고 할 것입니다. 자세한 내용은 앱 배포를 참조하세요.
자격 증명을 로컬로 저장하므로 이러한 단계를 수행하기 전에 안전한 컴퓨터를 사용 중인지 확인합니다.
-
터미널에서 복제본이 저장된 디렉터리로 이동합니다.
-
이 디렉터리의 최상위 수준에
.env
라는 파일을 만듭니다. -
.gitignore
파일에.env
를 추가 합니다. 이렇게 하면 실수로 앱의 자격 증명을 커밋하는 것을 방지할 수 있습니다. -
.env
파일에 다음 콘텐츠를 추가합니다.YOUR_HOSTNAME
을 GitHub Enterprise Server 인스턴스의 이름으로 바꿉니다. 이후 단계에서 다른 값을 업데이트합니다.Text APP_ID="YOUR_APP_ID" WEBHOOK_SECRET="YOUR_WEBHOOK_SECRET" PRIVATE_KEY_PATH="YOUR_PRIVATE_KEY_PATH" ENTERPRISE_HOSTNAME="YOUR_HOSTNAME"
APP_ID="YOUR_APP_ID" WEBHOOK_SECRET="YOUR_WEBHOOK_SECRET" PRIVATE_KEY_PATH="YOUR_PRIVATE_KEY_PATH" ENTERPRISE_HOSTNAME="YOUR_HOSTNAME"
-
앱의 설정 페이지로 이동합니다.
-
GitHub Enterprise Server의 페이지 오른쪽 위 모서리에서 프로필 사진을 클릭합니다.
-
계정 설정으로 이동합니다.
- 개인 계정 소유한 앱의 경우 설정을 클릭합니다.
- 조직이 소유한 앱의 경우:
- 사용자의 조직을 클릭합니다.
- 조직 오른쪽에서 설정을 클릭합니다.
-
왼쪽 사이드바에서 개발자 설정을 클릭합니다.
-
왼쪽 사이드바에서 GitHub Apps 을 클릭합니다.
-
앱 이름 옆에 있는 편집을 클릭합니다.
-
-
앱의 설정 페이지에서 "앱 ID" 옆에 있는 앱의 앱 ID를 찾습니다.
-
.env
파일에서YOUR_APP_ID
를 앱의 앱 ID로 바꿉니다. -
앱의 설정 페이지에서 "프라이빗 키"에서 프라이빗 키 생성을 클릭합니다. 컴퓨터에 다운로드된 PEM 형식의 프라이빗 키가 표시됩니다. 자세한 내용은 "GitHub 앱에 대한 프라이빗 키 관리"을(를) 참조하세요.
-
codespace를 사용하는 경우 codespace가 파일에 액세스할 수 있도록 다운로드한 PEM 파일을 codespace로 이동합니다.
-
.env
파일에서YOUR_PRIVATE_KEY_PATH
의 전체 경로를.pem
확장명을 포함한 프라이빗 키로 바꿉니다. -
.env
파일에서YOUR_WEBHOOK_SECRET
을 앱의 웹후크 비밀로 바꿉니다. 웹후크 비밀을 잊어버린 경우 "웹후크 비밀(선택 사항)"에서 비밀 변경을 클릭합니다. 새 비밀을 입력한 다음 변경 내용 저장을 클릭합니다.
웹후크 이벤트에 응답하는 코드 추가
복제본이 저장된 디렉터리의 최상위 수준에서 앱에 대한 코드를 보관할 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, Octokit} 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; const enterpriseHostname = process.env.ENTERPRISE_HOSTNAME; // 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 }, Octokit: Octokit.defaults({ baseUrl: `https://${enterpriseHostname}/api/v3`, }), }); // 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, Octokit} 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;
const enterpriseHostname = process.env.ENTERPRISE_HOSTNAME;
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
},
Octokit: Octokit.defaults({
baseUrl: `https://${enterpriseHostname}/api/v3`,
}),
});
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, Octokit} 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;
const enterpriseHostname = process.env.ENTERPRISE_HOSTNAME;
// 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
},
Octokit: Octokit.defaults({
baseUrl: `https://${enterpriseHostname}/api/v3`,
}),
});
// 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
파일에서 값module
과 함께 최상위 키type
을 추가합니다. 예시:{ // rest of the JSON object, "version": "1.0.0", "description": "", "type": "module", // rest of the JSON object, }
package.json
파일은 다음과 같습니다. dependencies
및 devDependencies
에서 name
값과 버전 번호는 다를 수 있습니다.
{
"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"
}
}
테스팅
다음 단계에 따라 위에서 만든 앱을 테스트합니다.
앱 설치
앱이 리포지토리의 끌어오기 요청에 대한 주석을 남기려면 리포지토리를 소유하고 해당 리포지토리에 대한 액세스 권한을 부여한 계정에 앱을 설치해야 합니다. 앱은 비공개이므로 앱을 소유한 계정에만 설치할 수 있습니다.
-
만든 앱을 소유한 계정에서 앱을 설치할 새 리포지토리를 만듭니다. 자세한 내용은 "새 리포지토리 만들기"을(를) 참조하세요.
-
앱의 설정 페이지로 이동합니다.
-
GitHub Enterprise Server의 페이지 오른쪽 위 모서리에서 프로필 사진을 클릭합니다.
-
계정 설정으로 이동합니다.
- 개인 계정 소유한 앱의 경우 설정을 클릭합니다.
- 조직이 소유한 앱의 경우:
- 사용자의 조직을 클릭합니다.
- 조직 오른쪽에서 설정을 클릭합니다.
-
왼쪽 사이드바에서 개발자 설정을 클릭합니다.
-
왼쪽 사이드바에서 GitHub Apps 을 클릭합니다.
-
앱 이름 옆에 있는 편집을 클릭합니다.
-
-
공개 페이지를 클릭합니다.
-
설치를 클릭합니다.
-
리포지토리만 선택을 선택합니다.
-
리포지토리 선택 드롭다운 메뉴를 선택하고 이 섹션의 시작 부분에서 선택한 리포지토리를 클릭합니다.
-
설치를 클릭합니다.
서버 시작
테스트를 위해 컴퓨터 또는 codespace를 서버로 사용합니다. 앱은 서버가 실행 중일 때만 웹후크에 응답합니다.
-
터미널에서 앱의 코드가 저장된 디렉터리로 이동합니다.
-
Smee.io에서 전달된 웹후크를 받으려면
npx smee -u WEBHOOK_PROXY_URL -t http://localhost:3000/api/webhook
를 실행 합니다.WEBHOOK_PROXY_URL
을 이전의 웹후크 프록시 URL로 바꿉니다. URL을 잊어버린 경우 앱 설정 페이지의 "웹후크 URL" 필드에서 찾을 수 있습니다.다음과 같은 출력이 표시됩니다. 여기서
WEBHOOK_PROXY_URL
은 웹후크 프록시 URL입니다.Forwarding WEBHOOK_PROXY_URL to http://localhost:3000/api/webhook Connected WEBHOOK_PROXY_URL
-
두 번째 터미널 창에서 앱의 코드가 저장된 디렉터리로 이동합니다.
-
npm run server
를 실행합니다. 터미널에Server is listening for events at: http://localhost:3000/api/webhook
라고 표시되어야 합니다.
앱 테스트
이제 서버가 실행 중이고 전달된 웹후크 이벤트를 수신했으므로 앱을 설치할 때 선택한 리포지토리에서 끌어오기 요청을 열어 앱을 테스트합니다.
-
앱을 설치할 때 선택한 리포지토리에서 끌어오기 요청을 엽니다. 자세한 내용은 "끌어오기 요청 만들기"을(를) 참조하세요.
앱의 코드가 저장된 리포지토리가 아니라 앱을 설치할 때 선택한 리포지토리를 사용해야 합니다. 자세한 내용은 앱 설치를 참조하세요.
-
smee.io의 웹후크 프록시 URL로 이동합니다.
pull_request
이벤트가 표시됩니다. 이는 끌어오기 요청을 만들 때 GitHub이(가) 끌어오기 요청 이벤트를 성공적으로 전송했음을 나타냅니다. -
npm run server
를 실행한 터미널에 "#1에 대한 끌어오기 요청 이벤트 수신됨"과 같은 항목이 표시됩니다. 여기서#
뒤의 정수는 사용자가 연 끌어오기 요청의 수입니다. -
끌어오기 요청의 타임라인에 앱의 주석이 표시됩니다.
-
두 터미널 창에서 Ctrl+C를 입력하여 서버를 중지하고 전달된 웹후크 수신을 중지합니다.
다음 단계
이제 웹후크 이벤트에 응답하는 앱이 있으므로 앱의 코드를 확장하고, 앱을 배포하고, 앱을 공개할 수 있습니다.
앱 코드 수정
이 자습서에서는 끌어오기 요청이 열릴 때 끌어오기 요청에 주석을 게시하는 방법을 보여 줍니다. 다양한 유형의 웹후크 이벤트에 응답하거나 웹후크 이벤트에 대한 응답으로 다른 작업을 수행하도록 코드를 업데이트할 수 있습니다.
만들려는 API 요청 또는 수신하려는 웹후크 이벤트에 대한 추가 권한이 앱에 필요한 경우 앱의 권한을 업데이트해야 합니다. 자세한 내용은 "GitHub 앱의 권한 선택"을(를) 참조하세요.
이 자습서에서는 모든 코드를 단일 파일에 저장했지만 함수와 구성 요소를 별도의 파일로 이동할 수 있습니다.
앱 배포
이 자습서에서는 로컬에서 앱을 개발하는 방법을 보여 줍니다. 앱을 배포할 준비가 되면 앱을 제공하고 앱의 자격 증명을 안전하게 유지하기 위해 변경해야 합니다. 수행하는 단계는 사용하는 서버에 따라 다르지만 다음 섹션에서는 일반적인 지침을 제공합니다.
서버에서 앱 호스트
이 자습서에서는 컴퓨터 또는 codespace를 서버로 사용했습니다. 앱이 프로덕션 사용을 위해 준비되면 앱을 전용 서버에 배포해야 합니다. 예를 들어 Azure App Service를 사용할 수 있습니다.
웹후크 URL 업데이트
GitHub에서 웹후크 트래픽을 수신하도록 설정된 서버가 있으면 앱 설정에서 웹후크 URL을 업데이트합니다. 프로덕션경에서 웹후크를 전달는 데 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';
앱의 자격 증명 보호
앱의 프라이빗 키 또는 웹후크 비밀은 절대 공개해서는 안 됩니다. 이 자습서에서는 앱의 자격 증명을 gitignored .env
파일에 저장했습니다. 앱을 배포할 때 자격 증명을 저장하고 코드를 업데이트하여 값을 적절하게 가져오는 안전한 방법을 선택해야 합니다. 예를 들어 Azure Key Vault와 같은 비밀 관리 서비스를 사용하여 자격 증명을 저장할 수 있습니다. 앱이 실행되면 자격 증명을 검색하여 앱이 배포된 서버의 환경 변수에 저장할 수 있습니다.
자세한 내용은 "GitHub App을 만드는 모범 사례"을(를) 참조하세요.
앱 공유
앱을 다른 사용자 및 조직과 공유하려면 앱을 퍼블릭으로 설정하세요. 자세한 내용은 "공개 또는 비공개 GitHub 앱 만들기"을(를) 참조하세요.
모범 사례 준수
GitHub App을(를) 사용하는 모범 사례를 따르는 것을 목표로 해야 합니다. 자세한 내용은 "GitHub App을 만드는 모범 사례"을(를) 참조하세요.