배포·승격 알림 Slack에서 Discord 웹훅으로 이관 - #659
Conversation
|
Slack 스레드 연동용 메타데이터입니다. slack-pr-bot 워크플로가 자동 생성하며, 수정·삭제하면 PR 과 Slack 알림 연동이 끊깁니다. |
|
Warning Review limit reached
Next review available in: 15 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
Walkthroughdeploy.yml과 promote.yml의 Slack 알림( ChangesSlack → Discord 알림 전환
Estimated code review effort: 2 (Simple) | ~10 minutes Assessment against linked issues
CI 워크플로만 손보는 깔끔한 작업이네요, YAML 인덴트 지옥 속에서도 길을 잃지 않으셨군요. 👏 다만 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/deploy.yml (1)
619-654: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winDiscord 알림 3곳 모두
run:스크립트에 GitHub 컨텍스트 값을 직접 템플릿 보간 — 스크립트 인젝션 경고 (zizmor)
github.actor(628, 665, 768번 줄,error등급)와needs.resolve.outputs.branch/domain/ref(634, 636, 650, 671, 673, 712, 772번 줄,info등급) 값이${{ }}문법으로run:셸 스크립트 안에 직접 삽입되고 있습니다. GitHub Actions는 이 값을 셸 실행 전에 문자열로 치환하기 때문에, 값에 백틱·따옴표·세미콜론 등이 포함되면 임의 명령 실행으로 이어질 수 있습니다.브랜치명(
needs.resolve.outputs.branch는workflow_run.head_branch기반)이나 GitHub 로그인명은 일반적으로 제약이 있지만, GitHub Actions 공식 보안 하드닝 가이드에서도 이런 값은env:로 전달 후 셸 변수로 참조하도록 권장합니다. 이미DISCORD_WEBHOOK_URL/DISCORD_USER_MAP은env:로 안전하게 넘기고 있으니, 나머지 값도 동일하게 처리하면 됩니다.🛡️ 성공 알림 step 기준 예시 (실패/릴리즈 알림도 동일 패턴 적용)
- name: Notify Discord on success if: success() continue-on-error: true shell: bash env: DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} DISCORD_USER_MAP: ${{ secrets.DISCORD_USER_MAP }} + GH_ACTOR: ${{ github.actor }} + DEPLOY_REF: ${{ needs.resolve.outputs.ref }} + DEPLOY_BRANCH: ${{ needs.resolve.outputs.branch }} + DEPLOY_DOMAIN: ${{ needs.resolve.outputs.domain }} run: | [ -z "$DISCORD_WEBHOOK_URL" ] && { echo "DISCORD_WEBHOOK_URL 미설정 — 알림 생략"; exit 0; } - ACTOR="${{ github.actor }}" + ACTOR="$GH_ACTOR" DISCORD_ID=$(echo "${DISCORD_USER_MAP:-{}}" | jq -r --arg login "$ACTOR" '.[$login] // empty') ACTOR_MENTION="${DISCORD_ID:+<@$DISCORD_ID>}" ACTOR_MENTION="${ACTOR_MENTION:-$ACTOR}" - SHORT_SHA="${{ needs.resolve.outputs.ref }}" + SHORT_SHA="$DEPLOY_REF" SHORT_SHA="${SHORT_SHA:0:7}" - COMMIT_URL="https://github.com/${{ github.repository }}/commit/${{ needs.resolve.outputs.ref }}" + COMMIT_URL="https://github.com/${{ github.repository }}/commit/$DEPLOY_REF" ... TEXT=$(printf '✅ `%s` 배포 성공!\n• 경로: `%s` 브랜치 → %s (%s)\n• 배포자: %s\n• 커밋: [%s](%s) %s\n• [워크플로우 로그](%s)' \ - "$TARGET" "${{ needs.resolve.outputs.branch }}" "$TARGET" "${{ needs.resolve.outputs.domain }}" "$ACTOR_MENTION" "$SHORT_SHA" "$COMMIT_URL" "$COMMIT_MSG" "$RUN_URL") + "$TARGET" "$DEPLOY_BRANCH" "$TARGET" "$DEPLOY_DOMAIN" "$ACTOR_MENTION" "$SHORT_SHA" "$COMMIT_URL" "$COMMIT_MSG" "$RUN_URL")
${{ github.repository }}는 리포지토리 슬러그 형식이 고정돼 있어 상대적으로 안전하지만, 일관성을 위해 필요 시GITHUB_REPOSITORY기본 환경변수를 활용해도 됩니다.zizmor가error/info등급으로 총 12곳을 짚었으니, 이번 기회에 세 알림 step 모두 같은 방식으로 정리하는 걸 추천드려요. 관련 개념은 GitHub 공식 문서의 "Security hardening for GitHub Actions – Understanding the risk of script injections"를 참고하시면 좋습니다.Also applies to: 656-717, 756-775
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/deploy.yml around lines 619 - 654, The Discord notification steps are vulnerable because GitHub context values are being interpolated directly into the shell script in the Notify Discord steps. Move all dynamic values used in the success/failure/release notifications, especially github.actor and needs.resolve.outputs.branch/domain/ref, into env: variables and reference only shell variables inside the run script. Apply the same pattern consistently in the Discord notify blocks so the send logic in the bash snippets stays safe and uses the existing jq/curl flow without direct ${{ }} templating.Source: Linters/SAST tools
🧹 Nitpick comments (2)
.github/workflows/deploy.yml (1)
652-654: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low valueDiscord webhook 응답 코드 미확인 — 전송 실패가 조용히 묻힐 수 있어요
curl -s만 사용하고-f/--fail나 HTTP 상태 코드 체크가 없어서, Discord가 4xx/5xx를 반환해도 step은 그대로 성공 처리됩니다.continue-on-error: true와 맞물려 배포 자체엔 영향 없지만, 알림이 실제로 안 갔는지 로그로 확인할 방법이 없어요.♻️ 개선 예시
- curl -s -X POST "$DISCORD_WEBHOOK_URL" \ - -H "Content-Type: application/json; charset=utf-8" \ - --data "$(jq -n --arg content "$TEXT" '{content:$content, allowed_mentions:{parse:["users"]}}')" + HTTP_CODE=$(curl -s -o /tmp/discord_resp.json -w '%{http_code}' -X POST "$DISCORD_WEBHOOK_URL" \ + -H "Content-Type: application/json; charset=utf-8" \ + --data "$(jq -n --arg content "$TEXT" '{content:$content, allowed_mentions:{parse:["users"]}}')") + [ "$HTTP_CODE" -lt 300 ] || echo "::warning::Discord 알림 전송 실패 (HTTP $HTTP_CODE) $(cat /tmp/discord_resp.json)"급한 이슈는 아니라서 여유 될 때 반영해도 좋습니다.
Also applies to: 714-716, 773-775
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/deploy.yml around lines 652 - 654, The Discord webhook notification step currently ignores HTTP failures, so a 4xx/5xx response can look successful. Update the curl invocation used for the Discord POST in the workflow to fail on non-2xx responses or explicitly check the HTTP status code, and keep the logging clear when the request is rejected. Apply the same fix to each duplicated webhook block in the workflow so all notification steps behave consistently..github/workflows/promote.yml (1)
197-199: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winDiscord 웹훅 curl 호출에 타임아웃 미설정
외부 API(Discord) 응답이 지연되면 이 스텝이 예상보다 오래 걸릴 수 있습니다.
continue-on-error: true로 job 실패는 막아주지만, hang 상태로 러너 시간을 소모하는 건 막지 못합니다.--max-time(또는--connect-timeout) 옵션을 추가하면 좋겠습니다.⏱️ 제안 수정
- curl -s -X POST "$DISCORD_WEBHOOK_URL" \ + curl -s --max-time 10 -X POST "$DISCORD_WEBHOOK_URL" \ -H "Content-Type: application/json; charset=utf-8" \ --data "$(jq -n --arg content "$TEXT" '{content:$content, allowed_mentions:{parse:["users"]}}')"deploy.yml에도 같은 패턴이 있어 함께 적용하면 좋겠습니다.
Also applies to: 220-222
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/promote.yml around lines 197 - 199, The Discord webhook curl call in the promotion workflow can hang indefinitely because it has no timeout. Update the curl invocation in the webhook notification step to include a timeout option such as --max-time (and optionally --connect-timeout) so the job fails fast on slow Discord responses; apply the same change to the matching webhook call in the deploy workflow if it uses the same curl pattern.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/promote.yml:
- Line 181: The workflow step is directly interpolating github.actor inside the
shell script, which should be moved to an env mapping instead. Update the
relevant job step to pass ACTOR via env from github.actor, and remove the inline
ACTOR assignment in the run block so the shell only reads the environment
variable. Use the existing promotion/notification step around the ACTOR usage as
the place to make this change.
---
Outside diff comments:
In @.github/workflows/deploy.yml:
- Around line 619-654: The Discord notification steps are vulnerable because
GitHub context values are being interpolated directly into the shell script in
the Notify Discord steps. Move all dynamic values used in the
success/failure/release notifications, especially github.actor and
needs.resolve.outputs.branch/domain/ref, into env: variables and reference only
shell variables inside the run script. Apply the same pattern consistently in
the Discord notify blocks so the send logic in the bash snippets stays safe and
uses the existing jq/curl flow without direct ${{ }} templating.
---
Nitpick comments:
In @.github/workflows/deploy.yml:
- Around line 652-654: The Discord webhook notification step currently ignores
HTTP failures, so a 4xx/5xx response can look successful. Update the curl
invocation used for the Discord POST in the workflow to fail on non-2xx
responses or explicitly check the HTTP status code, and keep the logging clear
when the request is rejected. Apply the same fix to each duplicated webhook
block in the workflow so all notification steps behave consistently.
In @.github/workflows/promote.yml:
- Around line 197-199: The Discord webhook curl call in the promotion workflow
can hang indefinitely because it has no timeout. Update the curl invocation in
the webhook notification step to include a timeout option such as --max-time
(and optionally --connect-timeout) so the job fails fast on slow Discord
responses; apply the same change to the matching webhook call in the deploy
workflow if it uses the same curl pattern.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: e4769801-6a27-4d90-bc66-708c07b5efc0
📒 Files selected for processing (2)
.github/workflows/deploy.yml.github/workflows/promote.yml
- deploy.yml(배포 성공/실패/릴리즈)·promote.yml(승격 성공/실패)의 Slack chat.postMessage 를 Discord 웹훅 POST(DISCORD_WEBHOOK_URL)로 교체 - 배포자 멘션 맵을 SLACK_USER_MAP(하드코딩)에서 DISCORD_USER_MAP(secret)으로. 매핑 없으면 GitHub 로그인 이름으로 폴백(핑은 안 감). 멘션 대상은 현재 활성 멤버 m-a-king·sevineleven 만 - 메시지 포맷을 Discord 마크다운으로: 링크 <url|text> 를 [text](url) 로, 멘션 <@id> 유지, allowed_mentions 로 유저 핑 명시 - DISCORD_WEBHOOK_URL 비면 skip 하는 가드 추가 — secret 미설정 상태로 머지돼도 배포가 안 깨진다 - admin IP 게이트용 SLACK_ADMIN_SIGNING_SECRET 은 알림과 무관한 별개 마이그레이션(#654)이라 그대로 둠
- 리뷰 요청이 노이즈가 될 수 있어 auto-reviewer 워크플로의 팀 풀에서 1o18z 를 뺀다 — 필요하면 직접 리뷰 요청한다. 이제 m-a-king·sevineleven 사이에서만 자동 지정된다
299dc43 to
679b10f
Compare
- CodeRabbit(zizmor template-injection) 지적 반영: run 블록에 ${{ github.actor }} 를 직접 보간하던 것을 env: ACTOR 로 옮기고 셸은 $ACTOR 만 읽게 함
- deploy.yml 3개(성공·실패·릴리즈)·promote.yml 2개(성공·실패) 알림 스텝 전부 동일 패턴으로 통일
- 값 자체는 GitHub 로그인명이라 위험이 크진 않으나, 표현식과 셸을 분리하는 Actions script injection 권장 패턴에 맞춤
- CodeRabbit review body 반영 (deploy.yml·promote.yml 알림 스텝) - env 분리 확장: needs.resolve.outputs.ref/branch/domain 도 run 직접 보간에서 env 로 옮김 (브랜치명은 백틱·$ 등 셸 메타문자를 허용해 인젝션 벡터 - zizmor Major) - curl 타임아웃: --max-time 10 추가로 Discord 지연 시 러너 hang 방지 - 전송 실패 감지: HTTP 응답코드 확인해 2xx 아니면 ::warning:: 로그 (continue-on-error 라 배포엔 무영향, 알림 유실을 로그로 드러냄) - promote.yml 은 동적값이 이미 env 라 A 해당 없음, B/C(curl)만 적용
|
@coderabbitai review body 지적 3건을 A. 스크립트 인젝션 (🟠 Major) — B. curl 타임아웃 (🔵 nitpick) — 5개 알림 curl 에 C. HTTP 응답코드 확인 (🔵 nitpick) — 응답이 2xx 가 아니면 |
🧩 Analysis chain🏁 Script executed: #!/bin/bash
git fetch origin 890362e --depth=1 2>&1 | tail -5
git show 890362e --stat 2>&1 | head -20
echo "---deploy.yml---"
git show 890362e -- .github/workflows/deploy.yml 2>&1 | head -300
echo "---promote.yml---"
git show 890362e -- .github/workflows/promote.yml 2>&1 | head -300Length of output: 11338 🏁 Script executed: #!/bin/bash
git show 890362e:.github/workflows/deploy.yml | grep -n 'needs.resolve.outputs\|github.repository\|github.run_id\|TAG\b\|CAUSE\b' | head -60
echo "---promote full context for TARGET_INPUT SRC DST---"
git show 890362e:.github/workflows/promote.yml | sed -n '150,230p'Length of output: 9996
A. 인젝션 수정 — B. curl 타임아웃 — 5곳 모두 C. HTTP 응답코드 확인 — 수고하셨습니다. 인젝션 벡터를 브랜치명까지 확장해서 짚어낸 판단이 좋았습니다 — GitHub Actions 워크플로에서 (๑•̀ㅂ•́)و✧ ✅ Action performedReview finished.
|
- ${DISCORD_USER_MAP:-{}} 는 secret 이 설정돼 있으면 bash 가 뒤에 } 를 덧붙여(...}}) jq 가 파싱 실패(exit 5) → set -eo pipefail 로 curl 전에 step 이 죽어 알림이 전송되지 않음
- 역설적으로 secret 미설정일 때만 우연히 동작(빈 {})해, #659 머지 후 매 배포·승격 알림이 조용히 실패
- guard 로 분리: DISCORD_MAP 에 담고 비었으면 {} 로 채운 뒤 jq 에 넘김
- deploy.yml 3블록(성공·실패·릴리즈) + promote.yml 2블록(성공·실패) 전부 적용
- PR #659 검증이 로컬에 jq 없어 python 으로 렌더링만 확인하느라 이 라인을 실제로 안 돌린 사각
Situation
Task
Action
chat.postMessage(bot token + channel) 를 Discord 웹훅 POST(DISCORD_WEBHOOK_URL)로 교체했다. 배포·승격·릴리즈 알림은 모두 같은 알림 채널로 간다.SLACK_USER_MAP(워크플로에 하드코딩)에서DISCORD_USER_MAP(secret)으로 옮겼다. 매핑이 없으면 GitHub 로그인 이름으로 폴백한다(핑은 안 감). 멘션 대상은 현재 활성 멤버 m-a-king·sevineleven 만 둔다.<url|text>를[text](url)로, 멘션<@id>는 유지,allowed_mentions로 유저 핑을 명시.DISCORD_WEBHOOK_URL이 비어 있으면 알림 step 을 조용히 건너뛴다. secret 없이 머지돼도 배포 잡이 안 깨진다.SLACK_ADMIN_SIGNING_SECRET은 알림과 무관한 별개 마이그레이션(Admin 슬래시커맨드 Discord 이관 (Ed25519 서명검증) #654)이라 건드리지 않았다.웹훅 vs 봇 (선택)
Result
SLACK_*알림 secret 정리는 그 이관들이 끝난 뒤 문서 이슈(문서·템플릿 Discord 정리 #655)에서 함께 처리한다.연관 이슈
Updates
리뷰어 자동 지정 정리
679b10f)