ci: announce raised + merged pull requests to Discord#25
Merged
Conversation
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>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
…and the same with merged on a merged close. (Closed-without-merge PRs are not announced.)
Design / hardening
pull_request_target(notpull_request): contributors work from forks, andpull_requestfork runs have no secrets and need first-time-contributor approval, so the announcement would silently never fire.pull_request_targetruns 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.DISCORD_PR_WEBHOOK_URLrepo secret (already set), never hardcoded — a public webhook URL gets auto-revoked by Discord's scanner.jq -n --arg) and no literal${{ }}inside therun:block — the two bugs that previously brokeadd_issues_to_project.yml. All dynamic values arrive viaenv:.allowed_mentions: {parse: [], roles: [<maintainer>]}so an attacker-controlled PR title (e.g. containing@everyone) can only ever ping the one maintainer role.permissions: {}(theGITHUB_TOKENis unused); a Discord failure is non-fatal.Validation
diffagainst the Garlemald-Server workflow: the only difference is the project name ("Server" → "Client").yaml.safe_loadparses;${{appears only inconcurrency:/env:positions (zero in therun:block); hostile-title payload → valid JSON with inert mentions;actionlintclean.🤖 Generated with Claude Code