๋ฐฐ๊ฒฝ
ํ์ฌ ๊ฐ๋ฐ ํ๋ก์ธ์ค์์ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ๋ณ๊ฒฝ์ฌํญ์ ์ด์ ๋ฐฐํฌ ์ ์ ๊ฒ์ฆํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
ํ์ฌ ํ๋ฆ:
์ฝ๋ ๋ณ๊ฒฝ โ main ๋ณํฉ โ Cloudflare Workers ์ด์ ๋ฐฐํฌ โ leetcode-study์์ ์ค์ ๋์ ํ์ธ
์ด์ ํ๊ฒฝ์ ๋ฐฐํฌ๋ ํ์์ผ webhook ๋์์ ํ์ธํ ์ ์์ด์, ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ค์ ์คํฐ๋ ์ฐธ์ฌ์์๊ฒ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ์ต๊ทผ 3๊ฐ์ PR์ด ์ฐ์ ๋ฆฌ๋ฒํธ๋ ์ด๋ ฅ(#17, #18, #19)์ด ์ด๋ฅผ ์ ๋ณด์ฌ์ค๋๋ค.
์ํ๋ ํ๋ฆ:
์ฝ๋ ๋ณ๊ฒฝ โ ์คํ
์ด์ง ๋ฐฐํฌ โ ํ
์คํธ PR๋ก ๊ฒ์ฆ โ ํ์ธ ์๋ฃ โ main ๋ณํฉ โ ์ด์ ๋ฐฐํฌ
์ ์ฝ ์กฐ๊ฑด
- ๋ณ๋ ํ
์คํธ ๋ ํฌ๋ฅผ ๋ง๋ค์ง ์๋๋ค โ ๊ด๋ฆฌ ํฌ์ธํธ๊ฐ ๋์ด๋๋ ๊ฒ์ ์ต์ํ
- ๊ธฐ์กด leetcode-study ๋ ํฌ ์์์ ํ
์คํธ ๊ฐ๋ฅํด์ผ ํ๋ค
- ํ๋ก๋์
์์ปค ์ฝ๋์ ๋ํ ๋ณ๊ฒฝ์ ์ต์ํํ๋ค
์ ํํ ์ ๊ทผ ๋ฐฉ์
๋ผ๋ฒจ ๊ธฐ๋ฐ ์คํ
์ด์ง ๋ผ์ฐํ
leetcode-study ๋ ํฌ์์ ํ
์คํธ์ฉ PR์ ์์ฑํ ๋ staging ๋ผ๋ฒจ์ ๋ถ์ด๋ฉด, ํ๋ก๋์
์์ปค๊ฐ ํด๋น ์ด๋ฒคํธ๋ฅผ ์คํ
์ด์ง ์์ปค๋ก ํฌ์๋ฉํ๋ค.
leetcode-study PR (๋ชจ๋ webhook ์ด๋ฒคํธ)
โ
โผ
Production Worker (github.dalestudy.com)
โ
โโ staging ๋ผ๋ฒจ ๊ฐ์ง?
โ YES โโโบ Forward โโโบ Staging Worker (๋ณ๋ ์ธ์คํด์ค)
โ NO โโโบ ์ ์ ์ฒ๋ฆฌ
์ Production์ ๊ฑฐ์ณ์ผ ํ๋๊ฐ?
GitHub App์ webhook URL์ ์ฑ ์ค์ ์์ ํ๋๋ง ์ง์ ๊ฐ๋ฅํ๋ค. PR ๋จ์๋ก ๋ค๋ฅธ URL์ ๋ณด๋ด๋ ๊ธฐ๋ฅ์ด ์๋ค. ๋ฐ๋ผ์ ๋ชจ๋ webhook ์ด๋ฒคํธ๋ Production Worker(github.dalestudy.com)๋ก ๋จผ์ ๋์ฐฉํ๋ค.
Production Worker์ Staging Worker๋ ์๋ก ๋ค๋ฅธ URL์ ๊ฐ์ง ์์ ํ ๋
๋ฆฝ๋ ์๋ฒ ์ธ์คํด์ค์ด๋ค (์ฝ๋, Secrets, ๋ฉ๋ชจ๋ฆฌ ๋ชจ๋ ๋ณ๊ฐ). Staging Worker๋ GitHub์ด ์กด์ฌ๋ฅผ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ ์ง์ webhook์ ๋ฐ์ ์ ์๋ค.
๊ทธ๋์ Production Worker๊ฐ staging ๋ผ๋ฒจ์ ๊ฐ์งํ๋ฉด fetch("https://github-staging.xxx/webhooks", ...)๋ก Staging Worker์ HTTP ์์ฒญ์ ๋ณด๋ด๋ ๋ฐฉ์์ผ๋ก ์ค๊ณํ๋ค. ์ฝ๋ ๋ด๋ถ ๋ถ๊ธฐ๊ฐ ์๋๋ผ, ์๋ฒ A โ ์๋ฒ B๋ก์ ๋คํธ์ํฌ ํต์ ์ด๋ค.
์ด ๋ฐฉ์์ ์ ํํ ์ด์
- ๋ณ๋ ๋ ํฌ ๋ถํ์: leetcode-study ์์์ ๋ผ๋ฒจ ํ๋๋ก ๊ตฌ๋ถ
- ํ๋ก๋์
๋ณ๊ฒฝ ์ต์ํ: ๋ผ์ฐํ
๋ก์ง์ ๋จ์ forward ๋ถ๊ธฐ ํ๋
- ์์ ๋ถ๋ฆฌ๋ ์์ปค: Cloudflare Workers environments๋ก Production/Staging์ด ๋
๋ฆฝ ์ธ์คํด์ค๋ก ๋ฐฐํฌ๋จ
- ๋ฆฌ์ผํ ํ
์คํธ: ์ค์ GitHub webhook ์ด๋ฒคํธ๋ฅผ ๊ทธ๋๋ก ๋ฐ์์ ์ฒ๋ฆฌ
๊ตฌํ ์คํ
1. Cloudflare Workers ํ๊ฒฝ ๋ถ๋ฆฌ
wrangler.jsonc์ staging ํ๊ฒฝ ์ถ๊ฐ:
wrangler deploy # โ Production Worker
wrangler deploy --env staging # โ Staging Worker (๋ณ๋ ์ธ์คํด์ค)
2. ์คํ
์ด์ง ๋ฐฐํฌ: GitHub Actions (workflow_dispatch)
์คํ
์ด์ง ๋ฐฐํฌ๋ ์๋์ด ์๋ ์๋ ํธ๋ฆฌ๊ฑฐ๋ก ์ํ๋ ๋ธ๋์น๋ฅผ ์ ํํด์ ๋ฐฐํฌํ๋ค.
name: Deploy Staging ๐
on:
workflow_dispatch:
inputs:
branch:
description: "๋ฐฐํฌํ ๋ธ๋์น"
required: true
type: string
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.branch }}
- run: npx wrangler deploy --env staging
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
์๋ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ ํํ ์ด์ :
- ์คํ
์ด์ง์ ํญ์ ๋๋ฆด ํ์ ์์ด ํ
์คํธํ ๋๋ง ๋ฐฐํฌํ๋ฉด ๋จ
- ์ด๋ค ๋ธ๋์น๋ฅผ ๋ฐฐํฌํ ์ง ๋ช
์์ ์ผ๋ก ์ ์ด ๊ฐ๋ฅ
- ์ด๋ฏธ
management.yaml์์ workflow_dispatch ํจํด์ ์ฐ๊ณ ์์ด์ ํ์ ์ต์
3. Production Worker์ ๋ผ์ฐํ
๋ก์ง ์ถ๊ฐ
/webhooks ํธ๋ค๋ฌ ์ต์๋จ์ staging ๋ผ๋ฒจ ๊ฐ์ง ๋ฐ ํฌ์๋ฉ:
const labels = payload.pull_request?.labels?.map(l => l.name) || [];
if (labels.includes("staging")) {
return fetch(env.STAGING_WORKER_URL + "/webhooks", request);
}
STAGING_WORKER_URL์ ํ๊ฒฝ๋ณ์๋ก ๊ด๋ฆฌ
- ํฌ์๋ฉ ์คํจ ์์๋ ํ๋ก๋์
์ฒ๋ฆฌ์ ์ํฅ ์์
4. Secrets ์ค์
Staging Worker Secrets (3๊ฐ)
Cloudflare Workers secrets๋ write-only๋ก, ๊ธฐ์กด Production ๊ฐ์ ์กฐํ/๋ณต์ ํ ์ ์๋ค. Org owner ๋๋ Worker owner์๊ฒ ์๋ 3๊ฐ ๊ฐ์ ํ์ธํด์ผ ํ๋ค:
| Secret |
ํ์ธ ๋ฐฉ๋ฒ |
๋น๊ณ |
APP_ID |
GitHub App ์ค์ ํ์ด์ง์์ ํ์ธ (์ซ์) |
๋น๋ฐ ์ ๋ณด ์๋ |
PRIVATE_KEY |
์๋ณธ PEM ํ์ผ ํ์. ์์ผ๋ฉด GitHub App ์ค์ ์์ ์ ํค ๋ฐ๊ธ ๊ฐ๋ฅ |
์ ํค ๋ฐ๊ธ ์ ๊ธฐ์กด ํค์ ๋ณ๊ฐ๋ก ์ถ๊ฐ๋จ |
OPENAI_API_KEY |
OpenAI ๋์๋ณด๋์์ ํ์ธ ๋๋ ์ ํค ๋ฐ๊ธ |
|
npx wrangler secret put APP_ID --env staging
npx wrangler secret put PRIVATE_KEY --env staging
npx wrangler secret put OPENAI_API_KEY --env staging
WEBHOOK_SECRET์ ๋ถํ์
Production Worker๊ฐ GitHub ์๋ช
์ ๊ฒ์ฆํ ํ์ Staging์ผ๋ก ํฌ์๋ฉํ๋ฏ๋ก, Staging์์ ๋ค์ ๊ฒ์ฆํ ํ์๊ฐ ์๋ค. ์ฝ๋์์ env.WEBHOOK_SECRET ๋ฏธ์ค์ ์ ๊ฒ์ฆ์ ์๋ ์คํตํ๋ค:
GitHub โโโ X-Hub-Signature-256 โโโโบ Production Worker โโโ forward โโโโบ Staging Worker
โ
๊ฒ์ฆ ์๋ฃ ๊ฒ์ฆ ์คํต
(env.WEBHOOK_SECRET) (WEBHOOK_SECRET ๋ฏธ์ค์ )
Production Worker ํ๊ฒฝ๋ณ์ (1๊ฐ)
Staging Worker ๋ฐฐํฌ ํ URL์ ํ์ธํ์ฌ Production์ ์ค์ :
npx wrangler secret put STAGING_WORKER_URL
# ์
๋ ฅ: https://github-staging.daleseo.workers.dev
GitHub Actions Secret (1๊ฐ)
GitHub repo Settings > Secrets > Actions์์ ์ค์ :
CLOUDFLARE_API_TOKEN: Cloudflare API Token (Workers ๋ฐฐํฌ ๊ถํ)
5. ํ
์คํธ ์ํฌํ๋ก์ฐ
- ์ด ๋ ํฌ์์ ๊ธฐ๋ฅ ๋ธ๋์น ์์ฑ
- GitHub Actions์์ ํด๋น ๋ธ๋์น๋ฅผ ์ ํํ์ฌ ์คํ
์ด์ง ๋ฐฐํฌ ์คํ
- leetcode-study์์ ํ
์คํธ PR ์์ฑ,
staging ๋ผ๋ฒจ ๋ถ์ฐฉ
- Staging Worker๊ฐ ์ฒ๋ฆฌ โ ํ
์คํธ PR์์ ๋์ ํ์ธ
- ํ์ธ ์๋ฃ โ ๊ธฐ๋ฅ ๋ธ๋์น๋ฅผ main์ ๋ณํฉ โ ์ด์ ์๋ ๋ฐฐํฌ
- ํ
์คํธ PR์ close
6. ๊ณ ๋ ค์ฌํญ
projects_v2_item ์ด๋ฒคํธ๋ payload์ PR ๋ผ๋ฒจ ์ ๋ณด๊ฐ ์ง์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ํญ์ Production์์ ์ฒ๋ฆฌ๋จ
issue_comment, pull_request_review_comment ์ด๋ฒคํธ๋ payload.issue.labels ๋๋ payload.pull_request.labels๋ก ๋ผ๋ฒจ ํ์ธ ๊ฐ๋ฅ
- Staging Worker์ ๋๊ธ/๋ฆฌ๋ทฐ๊ฐ ํ
์คํธ PR์ ์ค์ ๋ก ๋ฌ๋ฆฌ๋ฏ๋ก, ์คํฐ๋ ์ฐธ์ฌ์์๊ฒ ํผ๋์ด ์๋๋ก staging ๋ผ๋ฒจ์ ์ฉ๋๋ฅผ ํ์ ๊ณต์
๊ธฐ๋ ํจ๊ณผ
- ์ด์ ํ๊ฒฝ ์ฅ์ ์๋ฐฉ (revert ํ์ ๊ฐ์)
- PR ๋ฆฌ๋ทฐ ์ ์ค์ webhook ๋์์ ์คํ
์ด์ง์์ ํ์ธ ๊ฐ๋ฅ
- ๊ฐ๋ฐ ์๋ ํฅ์ (๋น ๋ฅธ ํผ๋๋ฐฑ ๋ฃจํ)
๋ฐฐ๊ฒฝ
ํ์ฌ ๊ฐ๋ฐ ํ๋ก์ธ์ค์์ ์๋ก์ด ๊ธฐ๋ฅ์ด๋ ๋ณ๊ฒฝ์ฌํญ์ ์ด์ ๋ฐฐํฌ ์ ์ ๊ฒ์ฆํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
ํ์ฌ ํ๋ฆ:
์ด์ ํ๊ฒฝ์ ๋ฐฐํฌ๋ ํ์์ผ webhook ๋์์ ํ์ธํ ์ ์์ด์, ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ค์ ์คํฐ๋ ์ฐธ์ฌ์์๊ฒ ์ํฅ์ ๋ฏธ์นฉ๋๋ค. ์ต๊ทผ 3๊ฐ์ PR์ด ์ฐ์ ๋ฆฌ๋ฒํธ๋ ์ด๋ ฅ(#17, #18, #19)์ด ์ด๋ฅผ ์ ๋ณด์ฌ์ค๋๋ค.
์ํ๋ ํ๋ฆ:
์ ์ฝ ์กฐ๊ฑด
์ ํํ ์ ๊ทผ ๋ฐฉ์
๋ผ๋ฒจ ๊ธฐ๋ฐ ์คํ ์ด์ง ๋ผ์ฐํ
leetcode-study ๋ ํฌ์์ ํ ์คํธ์ฉ PR์ ์์ฑํ ๋
staging๋ผ๋ฒจ์ ๋ถ์ด๋ฉด, ํ๋ก๋์ ์์ปค๊ฐ ํด๋น ์ด๋ฒคํธ๋ฅผ ์คํ ์ด์ง ์์ปค๋ก ํฌ์๋ฉํ๋ค.์ด ๋ฐฉ์์ ์ ํํ ์ด์
๊ตฌํ ์คํ
1. Cloudflare Workers ํ๊ฒฝ ๋ถ๋ฆฌ
wrangler.jsonc์ staging ํ๊ฒฝ ์ถ๊ฐ:{ "name": "github", "main": "index.js", // ... "env": { "staging": { "name": "github-staging" } } }2. ์คํ ์ด์ง ๋ฐฐํฌ: GitHub Actions (workflow_dispatch)
์คํ ์ด์ง ๋ฐฐํฌ๋ ์๋์ด ์๋ ์๋ ํธ๋ฆฌ๊ฑฐ๋ก ์ํ๋ ๋ธ๋์น๋ฅผ ์ ํํด์ ๋ฐฐํฌํ๋ค.
์๋ ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ ํํ ์ด์ :
management.yaml์์workflow_dispatchํจํด์ ์ฐ๊ณ ์์ด์ ํ์ ์ต์3. Production Worker์ ๋ผ์ฐํ ๋ก์ง ์ถ๊ฐ
/webhooksํธ๋ค๋ฌ ์ต์๋จ์ staging ๋ผ๋ฒจ ๊ฐ์ง ๋ฐ ํฌ์๋ฉ:STAGING_WORKER_URL์ ํ๊ฒฝ๋ณ์๋ก ๊ด๋ฆฌ4. Secrets ์ค์
Staging Worker Secrets (3๊ฐ)
Cloudflare Workers secrets๋ write-only๋ก, ๊ธฐ์กด Production ๊ฐ์ ์กฐํ/๋ณต์ ํ ์ ์๋ค. Org owner ๋๋ Worker owner์๊ฒ ์๋ 3๊ฐ ๊ฐ์ ํ์ธํด์ผ ํ๋ค:
APP_IDPRIVATE_KEYOPENAI_API_KEYWEBHOOK_SECRET์ ๋ถํ์
Production Worker๊ฐ GitHub ์๋ช ์ ๊ฒ์ฆํ ํ์ Staging์ผ๋ก ํฌ์๋ฉํ๋ฏ๋ก, Staging์์ ๋ค์ ๊ฒ์ฆํ ํ์๊ฐ ์๋ค. ์ฝ๋์์
env.WEBHOOK_SECRET๋ฏธ์ค์ ์ ๊ฒ์ฆ์ ์๋ ์คํตํ๋ค:Production Worker ํ๊ฒฝ๋ณ์ (1๊ฐ)
Staging Worker ๋ฐฐํฌ ํ URL์ ํ์ธํ์ฌ Production์ ์ค์ :
npx wrangler secret put STAGING_WORKER_URL # ์ ๋ ฅ: https://github-staging.daleseo.workers.devGitHub Actions Secret (1๊ฐ)
GitHub repo Settings > Secrets > Actions์์ ์ค์ :
CLOUDFLARE_API_TOKEN: Cloudflare API Token (Workers ๋ฐฐํฌ ๊ถํ)5. ํ ์คํธ ์ํฌํ๋ก์ฐ
staging๋ผ๋ฒจ ๋ถ์ฐฉ6. ๊ณ ๋ ค์ฌํญ
projects_v2_item์ด๋ฒคํธ๋ payload์ PR ๋ผ๋ฒจ ์ ๋ณด๊ฐ ์ง์ ํฌํจ๋์ง ์์ผ๋ฏ๋ก ํญ์ Production์์ ์ฒ๋ฆฌ๋จissue_comment,pull_request_review_comment์ด๋ฒคํธ๋payload.issue.labels๋๋payload.pull_request.labels๋ก ๋ผ๋ฒจ ํ์ธ ๊ฐ๋ฅ๊ธฐ๋ ํจ๊ณผ