main-chore(refactor): refactor has been put in place at "2026-01-08T1… #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CODEOWNERS Approved - Slack Notification | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| skip-draft: | ||
| description: "Skip notification for draft PRs" | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| require-full-approval: | ||
| description: "If true, only notify when reviewDecision is APPROVED. If false, notify on first approval." | ||
| required: false | ||
| type: boolean | ||
| default: true | ||
| slack-message-prefix: | ||
| description: "Custom prefix for Slack message (emoji + text)" | ||
| required: false | ||
| type: string | ||
| default: ":white_check_mark: CODEOWNERS gate satisfied" | ||
| secrets: | ||
| SLACK_RELEASE_CHANGELOG_WEBHOOK: | ||
| description: "Slack incoming webhook URL" | ||
| required: true | ||
| GH_TOKEN: | ||
| description: "GitHub token with PR read access (uses GITHUB_TOKEN if not provided)" | ||
| required: false | ||
| jobs: | ||
| notify: | ||
| name: Notify Slack on CODEOWNERS Approval | ||
| # Only run when the submitted review is an approval | ||
| if: github.event.review.state == 'approved' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Fetch PR decision and check for duplicate notification | ||
| id: pr | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| github-token: ${{ secrets.GH_TOKEN || github.token }} | ||
| script: | | ||
| const { owner, repo } = context.repo; | ||
| const prNumber = context.payload.pull_request.number; | ||
| const query = `query($owner:String!, $repo:String!, $number:Int!) { | ||
| repository(owner:$owner, name:$repo) { | ||
| pullRequest(number:$number) { | ||
| number | ||
| title | ||
| url | ||
| isDraft | ||
| headRefOid | ||
| baseRefName | ||
| reviewDecision | ||
| } | ||
| } | ||
| }`; | ||
| const data = await github.graphql(query, { owner, repo, number: prNumber }); | ||
| const pr = data.repository.pullRequest; | ||
| core.setOutput("number", String(pr.number)); | ||
| core.setOutput("title", pr.title); | ||
| core.setOutput("url", pr.url); | ||
| core.setOutput("is_draft", pr.isDraft ? "true" : "false"); | ||
| core.setOutput("head_sha", pr.headRefOid); | ||
| core.setOutput("base", pr.baseRefName); | ||
| core.setOutput("review_decision", pr.reviewDecision ?? ""); | ||
| // Dedupe marker per head SHA (so new commits can re-trigger notification) | ||
| const marker = `<!-- codeowners-approved:${pr.headRefOid} -->`; | ||
| core.setOutput("marker", marker); | ||
| // Check if we've already notified for this SHA | ||
| const comments = await github.paginate(github.rest.issues.listComments, { | ||
| owner, | ||
| repo, | ||
| issue_number: prNumber, | ||
| per_page: 100, | ||
| }); | ||
| const alreadyNotified = comments.some(c => (c.body || "").includes(marker)); | ||
| core.setOutput("already_notified", alreadyNotified ? "true" : "false"); | ||
| // Log for debugging | ||
| console.log(`PR #${pr.number}: draft=${pr.isDraft}, decision=${pr.reviewDecision}, notified=${alreadyNotified}`); | ||
| - name: Skip notification (conditions not met) | ||
| if: | | ||
| (inputs.skip-draft && steps.pr.outputs.is_draft == 'true') || | ||
| (inputs.require-full-approval && steps.pr.outputs.review_decision != 'APPROVED') || | ||
| steps.pr.outputs.already_notified == 'true' | ||
| run: | | ||
| echo "### Notification Skipped" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Condition | Value |" >> $GITHUB_STEP_SUMMARY | ||
| echo "|-----------|-------|" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Is Draft | ${{ steps.pr.outputs.is_draft }} |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Review Decision | ${{ steps.pr.outputs.review_decision }} |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Already Notified | ${{ steps.pr.outputs.already_notified }} |" >> $GITHUB_STEP_SUMMARY | ||
| - name: Post to Slack | ||
| if: | | ||
| (inputs.skip-draft == false || steps.pr.outputs.is_draft != 'true') && | ||
| (inputs.require-full-approval == false || steps.pr.outputs.review_decision == 'APPROVED') && | ||
| steps.pr.outputs.already_notified != 'true' | ||
| uses: slackapi/slack-github-action@v2 | ||
| with: | ||
| webhook-type: incoming-webhook | ||
| webhook: ${{ secrets.SLACK_RELEASE_CHANGELOG_WEBHOOK }} | ||
| payload: | | ||
| { | ||
| "text": ${{ toJSON(format('{0} | ||
| <{1}|PR #{2} — {3}> | ||
| Base: `{4}` Head: `{5}` | ||
| Approved by: `{6}`', inputs.slack-message-prefix, steps.pr.outputs.url, steps.pr.outputs.number, steps.pr.outputs.title, steps.pr.outputs.base, steps.pr.outputs.head_sha, github.event.review.user.login)) }} | ||
| } | ||
| - name: Summary (notification sent) | ||
| if: | | ||
| (inputs.skip-draft == false || steps.pr.outputs.is_draft != 'true') && | ||
| (inputs.require-full-approval == false || steps.pr.outputs.review_decision == 'APPROVED') && | ||
| steps.pr.outputs.already_notified != 'true' | ||
| run: | | ||
| echo "### Slack Notification Sent" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY | ||
| echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY | ||
| echo "| PR | [#${{ steps.pr.outputs.number }}](${{ steps.pr.outputs.url }}) |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Title | ${{ steps.pr.outputs.title }} |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Base | \`${{ steps.pr.outputs.base }}\` |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Head SHA | \`${{ steps.pr.outputs.head_sha }}\` |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Approved By | @${{ github.event.review.user.login }} |" >> $GITHUB_STEP_SUMMARY | ||