Skip to content

[chore] #7 - 슬랙 승인 & 머지 알람#11

Merged
aneykrap merged 6 commits into
developfrom
chore/#7-slack-approval-notify
Jul 3, 2026
Merged

[chore] #7 - 슬랙 승인 & 머지 알람#11
aneykrap merged 6 commits into
developfrom
chore/#7-slack-approval-notify

Conversation

@aneykrap

@aneykrap aneykrap commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

관련 이슈 🛠

작업 내용 요약 ✏️

PR 리뷰 승인 완료 및 머지 완료 시 Slack 알림을 전송하는 GitHub Actions 자동화를 추가했습니다.

주요 변경 사항 🛠️

  • github/workflows/pr-approval-notify.yml 추가
    • 리뷰어 2명의 최신 리뷰 상태가 모두 APPROVED이면 PR 작성자를 Slack에서 멘션 + PR 링크를 함께 전송
    • slack-approval-notified 라벨을 통해 동일 PR의 중복 알림 방지
    • 승인 조건이 깨지면 해당 PR의 라벨을 제거하여 재승인 시 다시 알림 전송
  • .github/workflows/pr-merged-notify.yml 추가
    • PR이 머지된 경우 Slack 알림 전송
    • <!channel> 멘션으로 PR 알림 채널의 전체 멤버에게 머지 완료 알림 전송 + PR 링크를 함께 전송
  • 이번에만 따로 pr 안파고 라벨링 파일 주석처리 했습니다

트러블 슈팅 ⚽️

  • 동일 PR에서 리뷰 이벤트가 여러 번 발생할 수 있어 승인 완료 알림 중복 방지를 위해 slack-approval-notified 라벨을 사용했습니다.
  • 여러 PR이 동시에 승인될 때 라벨 생성 요청이 충돌할 수 있어 해당 라벨은 저장소에 미리 생성하여 사용하도록 구현했습니다.

테스트 결과 📄

  • 아직 없습니당.. 실제 Slack 알림은 main 머지 후 테스트 PR에서 리뷰 승인 2개 및 머지 과정을 통해 확인 예정이에요

스크린샷 📷

  • 실제 Slack 알림 테스트 후 첨부 예정

리뷰 요구사항 📢

  • 승인 완료 알림 기준과 중복 알림 방지 방식이 티모버의 PR 리뷰 규칙에 적합한지 확인 부탁드립니당
  • 머지 완료 시 채널 전체 멘션이 의도한 알림 방식인지 확인 부탁드려요. 글고 별로면 말해줘요..
  • 원하는 기능이 있다면 언제든지 말해줘요~~

📎 참고 자료 (선택)

참고블로그

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • PR 리뷰 승인 조건을 만족하면 Slack으로 승인 완료 알림을 자동 전송합니다.
    • PR이 머지되면 Slack으로 “머지 완료” 메시지를 자동 전송합니다.
  • Bug Fixes
    • 승인 상태를 최신 리뷰 기준으로 집계하고, 마커 라벨을 활용해 중복 알림을 방지하며 조건 미달 시 마커를 제거합니다.
  • Chores
    • 기존 자동 라벨링 워크플로우가 비활성화되어 자동 라벨 부여/제거가 중단되었습니다.

@aneykrap aneykrap requested review from Jy000n and laura-jung June 29, 2026 07:52
@aneykrap aneykrap self-assigned this Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ebe2565c-d53d-48d7-a9d4-6228d8f10412

📥 Commits

Reviewing files that changed from the base of the PR and between 85dd029 and d934415.

📒 Files selected for processing (1)
  • .github/workflows/pr-approval-notify.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/pr-approval-notify.yml

📝 Walkthrough

Walkthrough

PR 승인 완료 Slack 알림과 PR 머지 완료 Slack 알림 워크플로우를 추가하고, 기존 자동 라벨 워크플로우를 주석 처리해 비활성화한다.

Changes

PR 알림 워크플로우

Layer / File(s) Summary
승인 알림 트리거·권한·동시성 설정
.github/workflows/pr-approval-notify.yml
pull_request_reviewpull_request 이벤트 트리거, 실행 권한, 환경변수, PR 번호 기반 동시성 그룹, open·non-draft 조건이 정의된다.
리뷰 집계·Slack 멘션·라벨 관리
.github/workflows/pr-approval-notify.yml
리뷰 최신 상태를 집계해 승인 수를 판정하고, 부족하면 마커 라벨을 제거하며, 충족하면 Slack 사용자 맵으로 작성자 ID를 찾은 뒤 웹훅 전송과 라벨 추가를 수행한다.
PR 머지 완료 Slack 알림
.github/workflows/pr-merged-notify.yml
pull_request closed 이벤트에서 merged인 경우에만 실행되며, 웹훅 시크릿 존재와 응답 성공을 확인한 뒤 PR 링크가 포함된 메시지를 전송한다.
자동 라벨 워크플로우 비활성화
.github/workflows/auto-label.yml
기존 자동 라벨 워크플로우 전체가 주석 처리되어 GitHub Actions 실행 대상에서 제외된다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubEvent
  participant GitHubAPI
  participant SlackWebhook
  GitHubEvent->>GitHubAPI: PR 리뷰와 라벨 조회
  GitHubAPI-->>GitHubEvent: 리뷰 목록
  GitHubEvent->>SlackWebhook: 승인 완료 메시지 전송
  SlackWebhook-->>GitHubEvent: ok 응답
Loading
sequenceDiagram
  participant PullRequestEvent
  participant GitHubScript
  participant SlackWebhook
  PullRequestEvent->>GitHubScript: closed 이벤트 전달
  GitHubScript->>SlackWebhook: PR 링크 포함 메시지 POST
  SlackWebhook-->>GitHubScript: ok 응답
Loading

Possibly related PRs

  • Team-Timo/Timo-Server#4: 동일한 .github/workflows/auto-label.yml 파일의 라벨 자동화 로직과 직접 겹치는 변경이다.

Poem

🐰 PR이 톡톡, 승인도 반짝
슬랙 알림이 폴짝, 머지 소식도 쏙
라벨은 조용히 잠들고
토끼는 워크플로우를 살짝 눌러요 ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 머지 알림 워크플로우와 auto-label 비활성화는 #7의 승인 알림 범위를 벗어납니다. 머지 알림과 자동 라벨 비활성화 변경을 별도 PR로 분리하거나, #7 범위에 맞게 승인 알림만 남기세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 슬랙 승인 및 머지 알림이라는 핵심 변경을 간결하게 요약합니다.
Linked Issues check ✅ Passed 필요한 2개 승인 시 Slack 알림과 재승인 시 재알림이 구현되어 #7 요구사항을 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 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/pr-approval-notify.yml:
- Around line 5-6: The workflow trigger in pull_request currently only listens
for synchronize, so approval notifications can be missed when a draft PR becomes
ready_for_review. Update the event types in the pr-approval-notify workflow to
include ready_for_review alongside synchronize, and keep the existing draft
check in the notification step so the workflow still skips drafts while firing
when the PR transitions to ready state.
- Around line 137-154: The Slack send and marker label update in the workflow
step are not in the same idempotency boundary, so a failure after Slack succeeds
can leave the notification state inconsistent and allow duplicate sends on
reruns. Update the logic around the Slack POST and the subsequent
github.rest.issues.addLabels call so the marker state is recorded atomically
with the notification flow: either add the label before sending and remove it on
Slack failure, or move the dedupe state into a separate reliable store that both
Slack and label writes consult. Keep the fix localized to the webhook send block
and the markerLabel/NOTIFIED_LABEL handling.
- Around line 59-78: Update the review aggregation logic in the
pr-approval-notify workflow so approval is counted only for reviews tied to the
current head commit. In the reviewer loop that builds latestOpinionByReviewer
and approvers, filter approvals by review.commit_id === pr.head.sha, and ensure
any CHANGES_REQUESTED state from the latest relevant review prevents completion
even if REQUIRED_APPROVALS is met. Use the existing review.state,
review.commit_id, pr.head.sha, and latestOpinionByReviewer symbols to adjust the
approval check.

In @.github/workflows/pr-merged-notify.yml:
- Around line 31-37: Add a timeout to the Slack webhook request in the
github-script block that calls fetch(webhookUrl, ...), since the workflow runs
on Node 24 and can hang on network stalls. Update the fetch call to use
AbortSignal.timeout(10_000) (or equivalent request timeout wiring) so the
request fails fast, and keep the change localized to the webhook POST logic used
for the Slack notification.
- Around line 3-16: The PR merge notification workflow currently runs on
pull_request, which prevents secrets like SLACK_PR_WEBHOOK_URL from being
available for forked PRs. Update the pr-merged-notify workflow trigger to
pull_request_target so the job can access the secret when
github.event.pull_request.merged is true, and keep the notify job limited to
sending the Slack message without checking out or executing PR code. Use the
existing notify job and actions/github-script step as the anchor when making the
change.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a95b77d-d3fc-4878-98a0-b89e70492147

📥 Commits

Reviewing files that changed from the base of the PR and between a3b014a and 043f0cc.

📒 Files selected for processing (2)
  • .github/workflows/pr-approval-notify.yml
  • .github/workflows/pr-merged-notify.yml

Comment thread .github/workflows/pr-approval-notify.yml Outdated
Comment on lines +59 to +78
const latestOpinionByReviewer = new Map();

for (const review of reviews) {
const reviewerLogin = review.user?.login;

if (!reviewerLogin || reviewerLogin === pr.user.login) {
continue;
}

if (
["APPROVED", "CHANGES_REQUESTED", "DISMISSED"]
.includes(review.state)
) {
latestOpinionByReviewer.set(reviewerLogin, review.state);
}
}

const approvers = [...latestOpinionByReviewer.entries()]
.filter(([, state]) => state === "APPROVED")
.map(([login]) => login);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
git ls-files .github/workflows/pr-approval-notify.yml
echo '---'
wc -l .github/workflows/pr-approval-notify.yml
echo '---'
sed -n '1,180p' .github/workflows/pr-approval-notify.yml | cat -n

Repository: Team-Timo/Timo-Server

Length of output: 6266


🌐 Web query:

GitHub REST API list reviews review.state commit_id chronological order approvals stale after push synchronize CHANGES_REQUESTED pull requests reviews

💡 Result:

To list pull request reviews using the GitHub REST API, use the endpoint: GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews [1]. Key details regarding the API behavior and pull request reviews: Chronological Order: The API returns the list of reviews in chronological order [1][2]. Review State and Commit ID: Each review object in the response includes a state field (e.g., APPROVED, CHANGES_REQUESTED, COMMENTED) and a commit_id, which represents the specific commit the review was submitted against [3]. Stale Approvals: When the option "Dismiss stale pull request approvals when new commits are pushed" is enabled in branch protection rules, new commits pushed to the pull request will invalidate existing approvals [4][5]. When this happens, the review state is effectively treated as no longer providing the required approval for merging [5]. Synchronization/Dismissal: If stale approvals are configured to be dismissed, any push to the source branch triggers the dismissal of existing approvals [4][5]. This action is often logged in the pull request timeline as an automatic system event indicating that the previous approval has been marked as stale [5]. Note that the review itself remains in the API response history, but its status regarding branch protection requirements is updated based on the push [4]. For most programmatic purposes, you can iterate through the chronologically sorted list returned by the API to identify the most recent review state for each reviewer on the pull request [1][3].

Citations:


🌐 Web query:

GitHub REST API pull request reviews listReviews commit_id state order latest review stale approvals synchronize branch protection dismissed CHANGES_REQUESTED documentation

💡 Result:

The GitHub REST API provides comprehensive support for managing pull request (PR) reviews, which are central to ensuring code quality and branch protection. List Reviews for a Pull Request To list all reviews for a specific pull request, use the following endpoint: GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews [1][2] The API returns these reviews in chronological order [1][2]. Note that this endpoint retrieves the entire review history of the PR, including comments, approvals, and any previously dismissed reviews [3]. The REST API does not provide a built-in filter to retrieve only "APPROVED" reviews; to achieve this, you must fetch the list and filter the results programmatically, or use the GitHub GraphQL API, which allows filtering by state (e.g., reviews(states: APPROVED)) [3]. Review States and Branch Protection - Review States: Reviews can have various states, such as CHANGES_REQUESTED (indicating the reviewer requires modifications) or APPROVED [3]. - Stale Reviews: When branch protection is enabled, you can configure the "Dismiss stale pull request approvals" setting [4]. When enabled, this feature automatically dismisses any existing "APPROVED" reviews whenever a new, "reviewable" commit is pushed to the pull request branch [5][4]. - Reviewable Commits: A "reviewable commit" generally refers to any manual change pushed to the branch [5]. Merges or rebases performed using built-in GitHub tools to sync with the target/base branch typically do not count as reviewable changes that trigger dismissal, whereas manual updates or pushes generally will [5]. Dismissing Reviews Beyond automatic dismissal through stale review settings, authorized users (repository administrators or those with write access) can manually dismiss a review [6]. This action changes the status of a review to a "dismissed" state (effectively moving it to a comment), and it requires the person performing the dismissal to provide a comment explaining why [6]. You can manage these settings via the API using endpoints that update pull request review protection (e.g., enabling or disabling dismiss_stale_reviews) [4][7]. Summary of Parameters - pull_number: The integer ID identifying the PR [1][8]. - per_page/page: Used for pagination (default 30, max 100) [1][2]. - dismiss_stale_reviews: A boolean setting in branch protection configuration [4][7]. Top Results: [1], [3], [5], [4], [6]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Show surrounding workflow logic for completion condition and any mention of stale approvals
sed -n '1,180p' .github/workflows/pr-approval-notify.yml | cat -n
echo '---'
rg -n "dismiss stale|stale|CHANGES_REQUESTED|APPROVED|review" .github/workflows/pr-approval-notify.yml

Repository: Team-Timo/Timo-Server

Length of output: 6703


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
text = Path('.github/workflows/pr-approval-notify.yml').read_text()
# lightweight probe of the exact logic
print("uses commit_id:", "commit_id" in text)
print("filters commit:", "pr.head.sha" in text)
print("tracks CHANGES_REQUESTED:", '"CHANGES_REQUESTED"' in text)
print("latestOpinionByReviewer stores state only:", 'latestOpinionByReviewer.set(reviewerLogin, review.state)' in text)
PY

Repository: Team-Timo/Timo-Server

Length of output: 282


승인 완료 판정을 최신 head SHA 기준으로 좁히세요.
지금은 리뷰어별 최신 상태만 보고 APPROVED 개수만 세기 때문에, 이전 커밋의 승인이나 최신 상태가 CHANGES_REQUESTED인 리뷰어가 있어도 REQUIRED_APPROVALS를 만족하면 알림이 나갑니다. commit_id === pr.head.sha인 승인만 집계하고, 변경 요청 상태가 하나라도 있으면 완료로 처리하지 마세요.

🤖 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/pr-approval-notify.yml around lines 59 - 78, Update the
review aggregation logic in the pr-approval-notify workflow so approval is
counted only for reviews tied to the current head commit. In the reviewer loop
that builds latestOpinionByReviewer and approvers, filter approvals by
review.commit_id === pr.head.sha, and ensure any CHANGES_REQUESTED state from
the latest relevant review prevents completion even if REQUIRED_APPROVALS is
met. Use the existing review.state, review.commit_id, pr.head.sha, and
latestOpinionByReviewer symbols to adjust the approval check.

Comment on lines +137 to +154
const slackResponse = await fetch(webhookUrl, {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
},
body: JSON.stringify({ text })
});

if (!slackResponse.ok) {
throw new Error("Slack 알림 전송에 실패했습니다.");
}

await github.rest.issues.addLabels({
owner,
repo,
issue_number: pr.number,
labels: [markerLabel]
}); No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workflow lines ==\n'
sed -n '1,240p' .github/workflows/pr-approval-notify.yml | nl -ba | sed -n '120,180p'

printf '\n== symbol search ==\n'
rg -n "alreadyNotified|markerLabel|addLabels|removeLabel|Slack 알림 전송|pr-approval-notify" .github/workflows . -g '!**/node_modules/**' -g '!**/dist/**' -g '!**/build/**'

Repository: Team-Timo/Timo-Server

Length of output: 221


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workflow lines 120-180 ==\n'
awk 'NR>=120 && NR<=180 { printf "%4d  %s\n", NR, $0 }' .github/workflows/pr-approval-notify.yml

printf '\n== symbol search ==\n'
rg -n "alreadyNotified|markerLabel|addLabels|removeLabel|Slack 알림 전송|pr-approval-notify" .github/workflows .

Repository: Team-Timo/Timo-Server

Length of output: 3005


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== workflow lines 80-115 ==\n'
awk 'NR>=80 && NR<=115 { printf "%4d  %s\n", NR, $0 }' .github/workflows/pr-approval-notify.yml

Repository: Team-Timo/Timo-Server

Length of output: 1472


Slack 전송과 마커 라벨 기록을 같은 idempotency 경계로 묶어야 합니다. 지금은 Slack 성공 후 issues.addLabels가 실패하면 NOTIFIED_LABEL이 남지 않아 다음 실행에서 alreadyNotified가 다시 false가 되고, 동일 알림이 반복됩니다. 라벨을 먼저 기록하고 Slack 실패 시 롤백하거나, 별도 상태 저장소로 중복 방지를 분리하세요.

🤖 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/pr-approval-notify.yml around lines 137 - 154, The Slack
send and marker label update in the workflow step are not in the same
idempotency boundary, so a failure after Slack succeeds can leave the
notification state inconsistent and allow duplicate sends on reruns. Update the
logic around the Slack POST and the subsequent github.rest.issues.addLabels call
so the marker state is recorded atomically with the notification flow: either
add the label before sending and remove it on Slack failure, or move the dedupe
state into a separate reliable store that both Slack and label writes consult.
Keep the fix localized to the webhook send block and the
markerLabel/NOTIFIED_LABEL handling.

Comment thread .github/workflows/pr-merged-notify.yml Outdated
Comment on lines +3 to +16
on:
pull_request:
types: [closed]

jobs:
notify:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest

steps:
- name: Slack 머지 완료 알림 전송
uses: actions/github-script@v8
env:
SLACK_PR_WEBHOOK_URL: ${{ secrets.SLACK_PR_WEBHOOK_URL }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

git ls-files .github/workflows/pr-merged-notify.yml && \
wc -l .github/workflows/pr-merged-notify.yml && \
cat -n .github/workflows/pr-merged-notify.yml

Repository: Team-Timo/Timo-Server

Length of output: 1755


🌐 Web query:

GitHub Actions pull_request fork repository secrets available documentation pull_request_target secrets workflow checkout trusted trigger fetch timeout github-script v8 Node fetch no timeout

💡 Result:

GitHub Actions workflows have specific security constraints regarding repository secrets and pull requests [1][2]. 1. Secrets and Fork Pull Requests: Workflows triggered by the pull_request event for pull requests originating from forks do not have access to repository secrets [3][1]. This restriction is in place to prevent untrusted code in a PR from accessing secrets [4]. 2. The pull_request_target Trigger: The pull_request_target event can be used to run workflows in the context of the base repository, which provides access to secrets [5][4]. However, this event carries significant security risks ("pwn requests") because the workflow runs with elevated trust [6][7]. It executes using the base repository's GITHUB_TOKEN and has access to repository secrets and the default-branch cache [6][4][7]. To use it safely, workflows must ensure that they do not check out or execute untrusted code from the pull request head [5][6][7]. As of recent changes (e.g., actions/checkout v7+), actions/checkout by default refuses to fetch fork pull request code in pull_request_target workflows to mitigate "pwn request" vulnerabilities [7]. If you must check out fork code, you can use the allow-unsafe-pr-checkout: true input, though this should be treated as a major security decision [5][7]. 3. github-script v8 and Node Fetch: github-script v8 uses Node 24 [8][9]. If you encounter UND_ERR_CONNECT_TIMEOUT or similar fetch errors in GitHub Actions, it is often related to network or DNS resolution issues (such as IPv6 support on the runner) rather than a lack of an explicit timeout parameter in github-script itself [10]. Node's fetch implementation, which powers these requests, follows standard Node.js behavior. If you need to enforce timeouts, you must typically wrap the fetch call in an AbortController signal within your script. Top Results: [5][1][7][8][10]

Citations:


🏁 Script executed:

python3 - <<'PY'
print("Need docs lookup results for GitHub Actions secret availability and fetch timeout behavior.")
PY

Repository: Team-Timo/Timo-Server

Length of output: 251


포크 PR 머지 알림은 pull_request에서 실패합니다.
포크에서 온 PR이 머지되면 secrets.SLACK_PR_WEBHOOK_URL이 주입되지 않아 이 잡이 끝납니다. 포크 PR도 지원하려면 pull_request_target로 전환하고, PR 코드는 checkout/실행하지 마세요.

제안된 수정
-  on:
-    pull_request:
+  on:
+    pull_request_target:
       types: [closed]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
types: [closed]
jobs:
notify:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Slack 머지 완료 알림 전송
uses: actions/github-script@v8
env:
SLACK_PR_WEBHOOK_URL: ${{ secrets.SLACK_PR_WEBHOOK_URL }}
on:
pull_request_target:
types: [closed]
jobs:
notify:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Slack 머지 완료 알림 전송
uses: actions/github-script@v8
env:
SLACK_PR_WEBHOOK_URL: ${{ secrets.SLACK_PR_WEBHOOK_URL }}
🤖 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/pr-merged-notify.yml around lines 3 - 16, The PR merge
notification workflow currently runs on pull_request, which prevents secrets
like SLACK_PR_WEBHOOK_URL from being available for forked PRs. Update the
pr-merged-notify workflow trigger to pull_request_target so the job can access
the secret when github.event.pull_request.merged is true, and keep the notify
job limited to sending the Slack message without checking out or executing PR
code. Use the existing notify job and actions/github-script step as the anchor
when making the change.

Comment thread .github/workflows/pr-merged-notify.yml Outdated
@aneykrap aneykrap changed the title Chore/#7 slack approval notify [chore] 슬랙 승인 & 머지 알람 Jun 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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/auto-label.yml:
- Around line 1-118: The auto-label workflow is fully commented out, leaving an
empty workflow definition in the Actions scan path. Remove the workflow file
entirely if it is meant to be disabled, or move/rename it so it is no longer
picked up by GitHub Actions; use the auto-label workflow entry under
.github/workflows/ and its job/script block as the target for cleanup.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a122c4a3-5ecb-410a-890f-02f5002c5723

📥 Commits

Reviewing files that changed from the base of the PR and between 043f0cc and 079184d.

📒 Files selected for processing (3)
  • .github/workflows/auto-label.yml
  • .github/workflows/pr-approval-notify.yml
  • .github/workflows/pr-merged-notify.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/pr-merged-notify.yml
  • .github/workflows/pr-approval-notify.yml

Comment on lines +1 to +118
#name: Auto Label
#
#on:
# issues:
# types: [opened, edited]
# pull_request_target:
# types: [opened, edited, reopened, synchronize]
#
#permissions:
# issues: write
#
#jobs:
# label:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b
# with:
# script: |
# const isIssue = context.eventName === 'issues';
# const item = isIssue
# ? context.payload.issue
# : context.payload.pull_request;
#
# const title = item.title.toLowerCase();
# const body = (item.body || '').toLowerCase();
# const author = item.user.login;
#
# const labels = new Set();
#
# const titleRules = [
# {
# label: '✨ feat',
# patterns: [/\[feat\]/, /(?:^|[^a-z0-9])feat:/]
# },
# {
# label: '🛠️ fix',
# patterns: [/\[fix\]/, /(?:^|[^a-z0-9])fix:/]
# },
# {
# label: '🚨 hotfix',
# patterns: [/\[hotfix\]/, /(?:^|[^a-z0-9])hotfix:/]
# },
# {
# label: '📃 docs',
# patterns: [/\[docs\]/, /(?:^|[^a-z0-9])docs:/]
# },
# {
# label: '🔁 refactor',
# patterns: [/\[refactor\]/, /(?:^|[^a-z0-9])refactor:/]
# },
# {
# label: '📝 chore',
# patterns: [/\[chore\]/, /(?:^|[^a-z0-9])chore:/]
# },
# {
# label: '🧪 test',
# patterns: [/\[test\]/, /(?:^|[^a-z0-9])test:/]
# },
# {
# label: '✏️ style',
# patterns: [/\[style\]/, /(?:^|[^a-z0-9])style:/]
# },
# {
# label: '✒️ comment',
# patterns: [/\[comment\]/, /(?:^|[^a-z0-9])comment:/]
# },
# {
# label: '📄 rename',
# patterns: [/\[rename\]/, /(?:^|[^a-z0-9])rename:/]
# },
# {
# label: '♻️ remove',
# patterns: [/\[remove\]/, /(?:^|[^a-z0-9])remove:/]
# }
# ];
#
# for (const rule of titleRules) {
# if (rule.patterns.some(pattern => pattern.test(title))) {
# labels.add(rule.label);
# }
# }
#
# const authorLabels = {
# 'Jy000n': '🌸 자윤',
# 'aneykrap': '🌵 예나',
# 'laura-jung': '🍀️ 윤아'
# };
#
# const managedLabels = new Set([
# ...titleRules.map(rule => rule.label),
# ...Object.values(authorLabels)
# ]);
#
# if (authorLabels[author]) {
# labels.add(authorLabels[author]);
# }
#
# const currentLabels = (item.labels || []).map(label => label.name || label);
# const labelsToRemove = currentLabels.filter(label => managedLabels.has(label));
#
# await Promise.all(labelsToRemove.map(label => github.rest.issues.removeLabel({
# owner: context.repo.owner,
# repo: context.repo.repo,
# issue_number: item.number,
# name: label
# }).catch(error => {
# if (error.status !== 404) {
# throw error;
# }
# })));
#
# if (labels.size > 0) {
# await github.rest.issues.addLabels({
# owner: context.repo.owner,
# repo: context.repo.repo,
# issue_number: item.number,
# labels: [...labels]
# }); No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

주석 처리로 비활성화하지 말고 워크플로우 파일 자체를 제거하세요.

지금 상태는 “비활성화된 워크플로우”가 아니라 .github/workflows/ 아래에 남아 있는 빈 워크플로우라서 actionlint가 이미 workflow is empty로 실패하고 있습니다. 비활성화가 목적이면 이 파일을 삭제하거나, 보관이 필요하면 .github/workflows/ 밖으로 옮기거나 확장자를 바꿔서 Actions가 스캔하지 않게 해야 합니다.

🧰 Tools
🪛 actionlint (1.7.12)

[error] 1-1: workflow is empty

(syntax-check)

🤖 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/auto-label.yml around lines 1 - 118, The auto-label
workflow is fully commented out, leaving an empty workflow definition in the
Actions scan path. Remove the workflow file entirely if it is meant to be
disabled, or move/rename it so it is no longer picked up by GitHub Actions; use
the auto-label workflow entry under .github/workflows/ and its job/script block
as the target for cleanup.

Source: Linters/SAST tools

@aneykrap aneykrap changed the title [chore] 슬랙 승인 & 머지 알람 [chore] #7 - 슬랙 승인 & 머지 알람 Jun 29, 2026
Jy000n
Jy000n previously approved these changes Jun 29, 2026

@Jy000n Jy000n left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다-!! 👍
전체적으로 승인 기준 및 Slack 알림 흐름이 잘 구성되어 있어서 이해하기 쉬웠습니다.

저는

  • 승인 완료 알림은 최신 리뷰 상태 기준으로 APPROVED 2개 이상일 때 발생
  • 중복 알림 방지는 label(slack-approval-notified)을 통해 관리
  • PR이 수정되면 기존 승인 상태가 변할 수 있으므로, 다시 승인 2개를 받아야 재알림이 발생하는 구조
    로 이해했는데 저희 규칙과 잘 맞는 것 같습니다..!!

repo,
issue_number: pr.number,
labels: [markerLabel]
}); No newline at end of file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P5) 전에 윤아님 코드에서도 언급했었는데, 이렇게 마지막 줄에 경고가 뜨는게 git에 파일을 올릴 때는 코드 동작에는 문제가 없지만 파일 끝에 암묵적으로 개행 문자를 넣어야 하는 규약이 있다고 해요!! 그래서 파일 마지막에는 엔터를 한 번 넣어주셔도 좋을 것 같아요!!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 저번에 리뷰 써주신것도 봤는데 개행문자를 안썼네용 요 내용은 다음부터 엔터 넣도록 하겠습니다. 감사합니다!

}

const text = [
"<!channel> PR이 머지되었어요!",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P5) 저의 경우에는 머지 완료 알림은 즉시 pull하지 않더라도 크게 신경 쓰이지는 않을 것 같고, 빠르게 최신 상태를 반영해야 하는 경우에는 유용할 것 같아서 좋은 것 같습니다 :)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자윤님 의견 감사해요! 그러면 일단 도입해보고 너무 불필요하다 싶으면 제외하는 방향으로 가요!!

Copy link
Copy Markdown
Collaborator Author

@예나

laura-jung
laura-jung previously approved these changes Jul 1, 2026

@laura-jung laura-jung left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코멘트 남겨두었으니 확인 부탁드립니다.
slack 역시 workflows에서 진행되는군요! 새롭게 알아갑니다.
어푸가 되고, 머지가 되는 과정이 생각보다 경우의 수가 많은데 그 케이스들에 맞게 잘 구성하신 것 같습니다!

어푸를 남기고 보니 check에 에러가 뜨는 부분이 있네요 pull_request_review부분인 것 같은데 GITHUB_TOKEN 권한 문제인 것 같습니다 확인 한번 부탁드립니다.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

p4) 현재의 경우에서는 2명의 approval을 받고나면 marked label 처리가 되어 이후 다시 커밋이 진행되면 메세지가 오지 않을 위험이 있는 것 같습니다. 물론 어푸 이후에 커밋을 변경하는 경우가 거의 없어서 지금의 경우로도 충분히 괜찮을 것 같은데요! 추후에는 label 처리방식이 아닌 커밋 SHA를 기준으로 처리하는 방식으로 리팩토링 해보면 어떨까하는 생각입니다.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넹 요거 고민했던 부분인데 approval 이후 커밋이 변경되는 경우가 많지 않아서 일단 지금처럼 해놨습니당 추후에는 커밋SHA를 기준으로 리팩토링해보겠습니다. 좋은 의견 감사해용!

@aneykrap aneykrap dismissed stale reviews from laura-jung and Jy000n via d934415 July 2, 2026 09:58
@aneykrap aneykrap requested review from Jy000n and laura-jung July 2, 2026 09:59

@Jy000n Jy000n left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니당

@github-actions github-actions Bot added the slack-approval-notified Slack 승인 완료 알림 중복 방지용 라벨 label Jul 3, 2026
@aneykrap aneykrap merged commit a45803c into develop Jul 3, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌵 예나 📝 chore slack-approval-notified Slack 승인 완료 알림 중복 방지용 라벨

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[chore] PR 승인 완료 시 Slack 멘션 알림 자동화

3 participants