Skip to content

ci: announce raised + merged pull requests to Discord#25

Merged
swstegall merged 1 commit into
developfrom
feat/discord-pr-announcements
May 31, 2026
Merged

ci: announce raised + merged pull requests to Discord#25
swstegall merged 1 commit into
developfrom
feat/discord-pr-announcements

Conversation

@swstegall

Copy link
Copy Markdown
Owner

Adds .github/workflows/announce-pull-request.yml — a port of the Garlemald-Server PR announcer — which posts to the PR-announcements Discord channel when a PR is raised (opened/reopened) and when a PR is merged.

Message format

@<maintainer role>, Pull Request raised for Garlemald Client.
Title: <pr title>
Source Branch: <user>:<branch>
Destination Branch: <user>:<branch>
<pr url>

…and the same with merged on a merged close. (Closed-without-merge PRs are not announced.)

Design / hardening

  • Trigger pull_request_target (not pull_request): contributors work from forks, and pull_request fork runs have no secrets and need first-time-contributor approval, so the announcement would silently never fire. pull_request_target runs in the base-repo context (has the secret, no approval gate). Safety: never checks out or runs PR code — only reads event metadata and POSTs to Discord.
  • Webhook via the DISCORD_PR_WEBHOOK_URL repo secret (already set), never hardcoded — a public webhook URL gets auto-revoked by Discord's scanner.
  • No raw JSON interpolation (payload built with jq -n --arg) and no literal ${{ }} inside the run: block — the two bugs that previously broke add_issues_to_project.yml. All dynamic values arrive via env:.
  • allowed_mentions: {parse: [], roles: [<maintainer>]} so an attacker-controlled PR title (e.g. containing @everyone) can only ever ping the one maintainer role.
  • permissions: {} (the GITHUB_TOKEN is unused); a Discord failure is non-fatal.

Validation

  • diff against the Garlemald-Server workflow: the only difference is the project name ("Server" → "Client").
  • yaml.safe_load parses; ${{ appears only in concurrency:/env: positions (zero in the run: block); hostile-title payload → valid JSON with inert mentions; actionlint clean.

Maintainer role id 1510751664347283556 (same as the Garlemald-Server PR announcer), defined once as a workflow-level env. Because pull_request_target keys off the base branch's copy, this takes effect for PRs targeting develop once merged (and main after the next developmain); it won't fire on this PR itself.

🤖 Generated with Claude Code

Add .github/workflows/announce-pull-request.yml: posts to the PR-
announcements Discord channel when a PR is raised (opened/reopened) and
when a PR is merged, pinging the maintainer role with the title, source/
destination branch labels, and the PR link. Port of the garlemald-server
workflow; only the project name differs ("Garlemald Client").

Design notes:
- pull_request_target (not pull_request) so the webhook secret is
  available for fork PRs and no first-time-contributor approval gate
  blocks the announcement. The workflow never checks out or runs PR code
  — it only reads event metadata and POSTs to Discord — so the usual
  pull_request_target code-execution risk does not apply.
- Webhook from the DISCORD_PR_WEBHOOK_URL repo secret (never hardcoded:
  a public webhook URL gets auto-revoked by Discord's scanner).
- Payload built with jq --arg (no raw interpolation -> no invalid-JSON on
  quoted titles), and no literal ${{ }} appears inside the run block.
- allowed_mentions {parse: [], roles: [<maintainer>]} so an attacker-
  controlled PR title can only ever ping the one maintainer role.
- permissions: {} (GITHUB_TOKEN unused); Discord failure is non-fatal.

Validated: yaml parse, no ${{ in run block, hostile-title payload is
valid JSON with inert mentions, and actionlint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@swstegall
swstegall merged commit 26c27a7 into develop May 31, 2026
5 checks passed
@swstegall
swstegall deleted the feat/discord-pr-announcements branch May 31, 2026 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant