From 80a63ba5281b4e93ab5431e0e2837bfd227933a3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 21:26:41 +0000 Subject: [PATCH 1/3] Add org bot workflow for issue and PR notifications Agent-Logs-Url: https://github.com/th30d4y/.github/sessions/408104c2-72ed-479a-991f-56f817c13e51 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- .github/workflows/org-bot.yml | 144 ++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 .github/workflows/org-bot.yml diff --git a/.github/workflows/org-bot.yml b/.github/workflows/org-bot.yml new file mode 100644 index 0000000..db59d64 --- /dev/null +++ b/.github/workflows/org-bot.yml @@ -0,0 +1,144 @@ +name: Organization Issue/PR Bot + +on: + issues: + types: [opened] + pull_request: + types: [opened] + +permissions: + contents: read + issues: write + pull-requests: write + members: read + +jobs: + welcome-and-notify: + runs-on: ubuntu-latest + steps: + - name: Build event metadata + id: metadata + shell: bash + run: | + set -euo pipefail + + if [[ "${{ github.event_name }}" == "issues" ]]; then + echo "type=Issue" >> "$GITHUB_OUTPUT" + echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT" + echo "title=${{ github.event.issue.title }}" >> "$GITHUB_OUTPUT" + echo "url=${{ github.event.issue.html_url }}" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "pull_request" ]]; then + echo "type=Pull Request" >> "$GITHUB_OUTPUT" + echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" + echo "title=${{ github.event.pull_request.title }}" >> "$GITHUB_OUTPUT" + echo "url=${{ github.event.pull_request.html_url }}" >> "$GITHUB_OUTPUT" + else + echo "Unsupported event: ${{ github.event_name }}" >&2 + exit 1 + fi + + - name: Post welcome comment + uses: actions/github-script@v7 + env: + BOT_MESSAGE: | + 👋 Hello! Thanks for your contribution. We will review this and get back to you as soon as possible. — th30d4y + with: + script: | + const message = process.env.BOT_MESSAGE.trim(); + const issueNumber = context.issue.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + try { + const comments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number: issueNumber, + per_page: 100 + }); + + const alreadyCommented = comments.some((comment) => { + if (!comment?.body) return false; + if (!comment.user?.type?.toLowerCase().includes('bot')) return false; + return comment.body.includes("👋 Hello! Thanks for your contribution.") && + comment.body.includes("th30d4y"); + }); + + if (alreadyCommented) { + core.info(`Skipping comment: matching bot comment already exists on #${issueNumber}`); + return; + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issueNumber, + body: message + }); + } catch (error) { + core.setFailed(`Failed to post welcome comment: ${error.message}`); + } + + - name: Resolve organization owner recipients + id: recipients + uses: actions/github-script@v7 + with: + result-encoding: string + script: | + const org = context.repo.owner; + + try { + const admins = await github.paginate(github.rest.orgs.listMembers, { + org, + role: "admin", + per_page: 100 + }); + + if (!admins.length) { + core.setFailed(`No organization owners/admins found for org "${org}".`); + return ""; + } + + const recipientSet = new Set(); + for (const admin of admins) { + const user = await github.rest.users.getByUsername({ username: admin.login }); + const publicEmail = user?.data?.email; + const fallbackNoreply = `${admin.id}+${admin.login}@users.noreply.github.com`; + recipientSet.add(publicEmail || fallbackNoreply); + } + + const recipients = [...recipientSet].join(","); + core.info(`Resolved ${recipientSet.size} organization owner recipient(s).`); + return recipients; + } catch (error) { + core.setFailed(`Failed to resolve organization owners: ${error.message}`); + return ""; + } + + - name: Send owner notification email + if: ${{ steps.recipients.outputs.result != '' }} + uses: dawidd6/action-send-mail@v3 + with: + server_address: smtp.gmail.com + server_port: 465 + secure: true + username: ${{ secrets.EMAIL_USER }} + password: ${{ secrets.EMAIL_PASS }} + subject: "[${{ github.repository }}] New ${{ steps.metadata.outputs.type }} Opened: ${{ steps.metadata.outputs.title }}" + to: ${{ steps.recipients.outputs.result }} + from: th30d4y Bot <${{ secrets.EMAIL_USER }}> + html_body: | +
Repository: ${{ github.repository }}
Type: ${{ steps.metadata.outputs.type }}
+Title: ${{ steps.metadata.outputs.title }}
+URL: ${{ steps.metadata.outputs.url }}
+Automated notification by th30d4y.
+ + - name: Fail when email was not sent + if: ${{ steps.recipients.outputs.result == '' }} + shell: bash + run: | + echo "No recipients resolved, email notification was not sent." >&2 + exit 1 From b3524b377157a11ff99fee81d3c5e6f73a67439a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 21:27:28 +0000 Subject: [PATCH 2/3] Harden workflow metadata and recipient resolution Agent-Logs-Url: https://github.com/th30d4y/.github/sessions/408104c2-72ed-479a-991f-56f817c13e51 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- .github/workflows/org-bot.yml | 53 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/.github/workflows/org-bot.yml b/.github/workflows/org-bot.yml index db59d64..8aa3e77 100644 --- a/.github/workflows/org-bot.yml +++ b/.github/workflows/org-bot.yml @@ -18,24 +18,31 @@ jobs: steps: - name: Build event metadata id: metadata - shell: bash - run: | - set -euo pipefail - - if [[ "${{ github.event_name }}" == "issues" ]]; then - echo "type=Issue" >> "$GITHUB_OUTPUT" - echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT" - echo "title=${{ github.event.issue.title }}" >> "$GITHUB_OUTPUT" - echo "url=${{ github.event.issue.html_url }}" >> "$GITHUB_OUTPUT" - elif [[ "${{ github.event_name }}" == "pull_request" ]]; then - echo "type=Pull Request" >> "$GITHUB_OUTPUT" - echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" - echo "title=${{ github.event.pull_request.title }}" >> "$GITHUB_OUTPUT" - echo "url=${{ github.event.pull_request.html_url }}" >> "$GITHUB_OUTPUT" - else - echo "Unsupported event: ${{ github.event_name }}" >&2 - exit 1 - fi + uses: actions/github-script@v7 + with: + script: | + try { + const payload = context.payload; + if (context.eventName === "issues" && payload.issue) { + core.setOutput("type", "Issue"); + core.setOutput("number", String(payload.issue.number)); + core.setOutput("title", payload.issue.title || "(no title)"); + core.setOutput("url", payload.issue.html_url); + return; + } + + if (context.eventName === "pull_request" && payload.pull_request) { + core.setOutput("type", "Pull Request"); + core.setOutput("number", String(payload.pull_request.number)); + core.setOutput("title", payload.pull_request.title || "(no title)"); + core.setOutput("url", payload.pull_request.html_url); + return; + } + + core.setFailed(`Unsupported event payload for "${context.eventName}".`); + } catch (error) { + core.setFailed(`Failed to build event metadata: ${error.message}`); + } - name: Post welcome comment uses: actions/github-script@v7 @@ -99,13 +106,9 @@ jobs: return ""; } - const recipientSet = new Set(); - for (const admin of admins) { - const user = await github.rest.users.getByUsername({ username: admin.login }); - const publicEmail = user?.data?.email; - const fallbackNoreply = `${admin.id}+${admin.login}@users.noreply.github.com`; - recipientSet.add(publicEmail || fallbackNoreply); - } + const recipientSet = new Set( + admins.map((admin) => `${admin.id}+${admin.login}@users.noreply.github.com`) + ); const recipients = [...recipientSet].join(","); core.info(`Resolved ${recipientSet.size} organization owner recipient(s).`); From db034cc08f3f1725a67513715c722549a9e3fb6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Apr 2026 21:28:09 +0000 Subject: [PATCH 3/3] Refine dedupe matching and recipient warning flow Agent-Logs-Url: https://github.com/th30d4y/.github/sessions/408104c2-72ed-479a-991f-56f817c13e51 Co-authored-by: Stalin-143 <161853795+Stalin-143@users.noreply.github.com> --- .github/workflows/org-bot.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/org-bot.yml b/.github/workflows/org-bot.yml index 8aa3e77..15abf34 100644 --- a/.github/workflows/org-bot.yml +++ b/.github/workflows/org-bot.yml @@ -64,11 +64,12 @@ jobs: per_page: 100 }); + const normalize = (text) => (text || "").replace(/\r\n/g, "\n").trim(); + const expected = normalize(message); const alreadyCommented = comments.some((comment) => { if (!comment?.body) return false; if (!comment.user?.type?.toLowerCase().includes('bot')) return false; - return comment.body.includes("👋 Hello! Thanks for your contribution.") && - comment.body.includes("th30d4y"); + return normalize(comment.body) === expected; }); if (alreadyCommented) { @@ -102,7 +103,7 @@ jobs: }); if (!admins.length) { - core.setFailed(`No organization owners/admins found for org "${org}".`); + core.warning(`No organization owners/admins found for org "${org}".`); return ""; }