DaleStudy ์กฐ์ง์ ์๋ํ ์์ ์ ์ฒ๋ฆฌํ๋ GitHub App (https://github.com/apps/dalestudy)
DaleStudy ์กฐ์ง์ ์ฌ๋ฌ repository์์ ๋ฐ๋ณต์ ์ธ ์์ ๋ค์ ์๋ํํ๋ ํ์ฅ ๊ฐ๋ฅํ ํ๋ซํผ์ ๋๋ค.
Fork PR์์๋ ์๋ํ๋๋ก GitHub Projects v2์ Week ํ๋๋ฅผ ์กฐํํ๊ณ , Week ์ค์ ์ด ๋๋ฝ๋ PR์ ์๋์ผ๋ก ๊ฒฝ๊ณ ๋๊ธ์ ์์ฑํฉ๋๋ค.
ํธ๋ฆฌ๊ฑฐ ๋ฐฉ์:
- ์ค์๊ฐ: GitHub Organization Webhook (Week ์ค์ ๋ณ๊ฒฝ ์ฆ์ ๋ฐ์)
- ์๋: REST API ์ง์ ํธ์ถ
๋์: https://github.com/DaleStudy/leetcode-study
์ค์ ๊ฐ์ด๋: AGENTS.md์ "GitHub Organization Webhook ์ค์ " ์น์
์ฐธ๊ณ
๋จ์ผ Worker์ ์ฌ๋ฌ ์๋ํฌ์ธํธ๋ฅผ ์ถ๊ฐํ์ฌ ๋ค์ํ ์๋ํ ์๊ตฌ์ฌํญ์ ์ฒ๋ฆฌํ ์์ ์ ๋๋ค.
- https://dash.cloudflare.com ํ์๊ฐ์
- Workers ์น์ ์ผ๋ก ์ด๋
npm install -g wrangler
wrangler loginGitHub App์ credentials๋ฅผ Worker secrets์ ์ ์ฅ:
cd cloudflare-worker
# APP_ID ์ค์
wrangler secret put APP_ID
# ํ๋กฌํํธ์์ GitHub App ID ์
๋ ฅ
# PRIVATE_KEY ์ค์
wrangler secret put PRIVATE_KEY
# ํ๋กฌํํธ์์ GitHub App Private Key ์ ์ฒด ๋ด์ฉ ์
๋ ฅ
# (-----BEGIN RSA PRIVATE KEY----- ๋ถํฐ -----END RSA PRIVATE KEY----- ๊น์ง)wrangler deploy๋ฐฐํฌ ์๋ฃ ํ Custom Domain์ ํตํด ์ ๊ทผ ๊ฐ๋ฅํฉ๋๋ค:
https://github.dalestudy.com
Base URL: https://github.dalestudy.com
๋ชจ๋ Open PR์์ Week ์ค์ ์ ๊ฒ์ฌํ๊ณ ์๋์ผ๋ก ๋๊ธ ์์ฑ/์ญ์
Request:
์์ฒญ ๋ฐ๋์์ repo_owner๋ฅผ ์๋ตํ๋ฉด ์๋์ผ๋ก DaleStudy๊ฐ ์ฌ์ฉ๋ฉ๋๋ค.
{
"repo_name": "leetcode-study"
}Response:
{
"success": true,
"total_prs": 3,
"checked": 3,
"commented": 1,
"deleted": 1,
"results": [
{ "pr": 1970, "week": null, "commented": true },
{ "pr": 1969, "week": "Week 8", "commented": false, "deleted": true }
]
}์ด๋ ค์๋ ๋ต์ ์ ์ถ PR์ ์ผ๊ด ์น์ธํฉ๋๋ค. excludes ๋ฐฐ์ด์ ์ฌ์ฉํด ํน์ PR ๋ฒํธ๋ฅผ ์ ์ธํ ์ ์์ต๋๋ค. ์ด๋ฏธ ์น์ธ๋์๊ฑฐ๋ Draft/maintenance ๋ผ๋ฒจ์ด ๋ถ์ PR์ ์๋์ผ๋ก ์คํต๋ฉ๋๋ค.
Request:
{ "repo_name": "leetcode-study", "excludes": [1972] }Response:
{
"success": true,
"action": "approve",
"repo": "DaleStudy/leetcode-study",
"total_open_prs": 5,
"processed": 2,
"approved": 2,
"skipped": 0,
"results": [
{ "pr": 1970, "title": "week8 solutions", "approved": true },
{ "pr": 1971, "title": "week8 extras", "approved": true }
]
}์ด๋ ค์๋ PR์ ์ผ๊ด ๋ณํฉํฉ๋๋ค. ๊ธฐ๋ณธ ๋ณํฉ ๋ฐฉ์์ merge์ด๋ฉฐ, merge_method๋ก merge | squash | rebase ์ค ์ ํํ ์ ์์ต๋๋ค. excludes ๋ฐฐ์ด๋ก ํน์ PR์ ์ ์ธํ ์ ์์ต๋๋ค. ์ต์ 1๊ฐ์ ์น์ธ ๋ฆฌ๋ทฐ๊ฐ ์๊ฑฐ๋ Draft/maintenance ๋ผ๋ฒจ์ด ๋ถ์ PR์ ์คํต๋๋ฉฐ, GitHub์์ mergeable_state === "clean"์ธ PR๋ง ๋ณํฉ๋ฉ๋๋ค(behind, dirty, unknown ๋ฑ์ ์คํต). unknown/behind ์ํ๋ ์ต๋ 1์ด ํ ํ ์ฐจ๋ก ์ฌํ์ธํฉ๋๋ค.
Request:
{
"repo_name": "leetcode-study",
"excludes": [1972],
"merge_method": "squash"
}Response:
{
"success": true,
"action": "merge",
"repo": "DaleStudy/leetcode-study",
"merge_method": "squash",
"total_open_prs": 5,
"processed": 2,
"merged": 2,
"skipped": 0,
"results": [
{ "pr": 1970, "title": "week8 solutions", "merged": true, "sha": "abc123" },
{ "pr": 1971, "title": "week8 extras", "merged": true, "sha": "def456" }
]
}# ๊ฐ๋ฐ ์๋ฒ ์์
wrangler dev
# ๋ก์ปฌ ํ
์คํธ (๋ณ๋ ํฐ๋ฏธ๋)
curl -X POST http://localhost:8787/check-weeks \
-H "Content-Type: application/json" \
-d '{"repo_owner": "DaleStudy", "repo_name": "leetcode-study"}'curl -X POST https://github.dalestudy.com/check-weeks \
-H "Content-Type: application/json" \
-d '{"repo_owner": "DaleStudy", "repo_name": "leetcode-study"}'wrangler tail- DaleStudy organization๋ง ํ์ฉ
- CORS ํค๋ ์ค์ (๋ชจ๋ origin ํ์ฉ)
- GitHub App credentials๋ Worker secrets์ ์์ ํ๊ฒ ์ ์ฅ
- Rate limiting์ Cloudflare์์ ์๋ ์ฒ๋ฆฌ
Cloudflare Workers ๋ฌด๋ฃ ํฐ์ด:
- 100,000 requests/day
- 10ms CPU time per request
๋ฆฌํธ์ฝ๋ ์คํฐ๋ PR ์์ค์ด๋ฉด ๋ฌด๋ฃ ํฐ์ด๋ก ์ถฉ๋ถํฉ๋๋ค.
์๋ก์ด ์๋ํ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ค๋ฉด:
index.js์ ์ ์๋ํฌ์ธํธ ๋ผ์ฐํ ์ถ๊ฐ- ํธ๋ค๋ฌ ํจ์ ๊ตฌํ (๊ธฐ์กด
handleCheckAllPrs์ฐธ๊ณ ) - GitHub App ๊ถํ ํ์ธ ๋ฐ ํ์์ ์ถ๊ฐ
- ๋ฌธ์(AGENTS.md, README.md) ์ ๋ฐ์ดํธ
- ๋ก์ปฌ ํ
์คํธ ํ ๋ฐฐํฌ (
wrangler deploy)
์์ธํ ๊ฐ์ด๋๋ AGENTS.md๋ฅผ ์ฐธ๊ณ ํ์ธ์.
GitHub App credentials ํ์ธ:
wrangler secret listAPP_ID์ PRIVATE_KEY๊ฐ ๋ชจ๋ ์ค์ ๋์ด ์์ด์ผ ํฉ๋๋ค.
DaleStudy organization์ด ์๋ ๊ฒฝ์ฐ ์ฐจ๋จ๋ฉ๋๋ค.
- AGENTS.md: AI ์์ด์ ํธ๋ฅผ ์ํ ์์ธ ๊ฐ์ด๋ (๊ฐ๋ฐ์๋ ํ๋ !)
- DEPLOYMENT.md: ์ฒ์๋ถํฐ ๋ฐฐํฌํ๋ ์ ์ฒด ๊ฐ์ด๋
- GitHub App: https://github.com/organizations/DaleStudy/settings/apps/dalestudy