Back to blog
GitHub automation11 min readPublished June 13, 2026

How to post GitHub releases to Discord

A correct, real recipe for posting GitHub releases to Discord with a webhook - GitHub Actions YAML and a curl example - plus bot vs webhook, mention etiquette, and the S2P approval path.

What this solves

Someone wants their GitHub releases to show up in a Discord channel and needs a correct recipe plus guidance on webhook versus bot.

How S2P helps

Ship a working webhook recipe that posts each GitHub release to Discord, and know when a bot or a release-native tool is the better fit.

Key takeaways

  • A Discord webhook is the easiest path: a single POST to a URL, no OAuth.
  • Use a bot only when you need richer interaction, slash commands, or controlled mentions.
  • Mention etiquette matters: avoid pinging everyone for routine releases.
  • A release-native tool adds approval and multi-channel routing on top of the webhook.

Section 1

Good news: the DIY webhook path is genuinely easy

Unlike LinkedIn, Discord makes this simple. There is no OAuth dance, no token refresh, just a URL you POST to. This is the rare case where DIY is the right first move.

Discord channels can generate an incoming webhook, which is a unique URL that accepts a JSON payload and turns it into a message in that channel. There is no app to register, no OAuth flow, and no token to refresh. You create the webhook in the channel settings, copy the URL, store it as a secret, and POST to it. That is the entire auth story, which is why for Discord the honest recommendation is to start with the webhook rather than reach for a tool.

To create one, open your Discord server, go to the target channel's settings, choose Integrations, then Webhooks, and create a new webhook. You can name it and give it an avatar so messages look intentional, then copy its URL. Treat that URL like a password - anyone who has it can post to your channel - so store it as a repository secret, never in committed code. With the URL in hand, the rest is a single HTTP POST.

From there you have two equally valid ways to fire the POST when a release publishes: a GitHub Actions workflow that runs on the release event, or any script or service that calls the webhook with curl. The next two sections give you a correct, copy-ready version of each. Both are real and both work; pick based on whether you want it living in your CI or in your own backend.

  • A Discord webhook is a URL that accepts JSON and posts a message.
  • No OAuth, no app registration, no token refresh.
  • Create it in channel settings under Integrations, then Webhooks.
  • Treat the URL like a password and store it as a secret.

Section 2

Recipe 1: GitHub Actions on the release event

If you want this to live next to your code, a GitHub Action triggered on release is the clean way to do it.

This workflow triggers when a release is published, then sends a Discord message containing the release name, its notes, and a link back to the release on GitHub. It reads the values straight from the release event payload, so you do not have to hardcode anything per release. Store your webhook URL as a repository secret named DISCORD_WEBHOOK_URL and the workflow does the rest.

The payload uses Discord's embed format, which renders as a tidy card with a title, a description, and a clickable link rather than a wall of plain text. Embeds are the difference between a release post that looks deliberate and one that looks like log spam. The content field is left empty here on purpose, which matters for mention etiquette - we cover why in a moment - but the embed carries the actual announcement. The jq step safely turns the release body into a valid JSON string so newlines and quotes do not break the payload.

This recipe is correct and minimal. It has no approval step and no multi-channel routing, which is fine for a community or internal channel where an automatic, dependable release feed is exactly what people want. If you later need a human to review the post or want the same release to also reach LinkedIn or X with channel-appropriate copy, that is the point where a release-native tool starts to earn its place over the raw webhook.

.github/workflows/discord-on-release.yml

name: Post release to Discord

on:
  release:
    types: [published]

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
      - name: Send Discord message
        env:
          WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL }}
          NAME: ${{ github.event.release.name }}
          NOTES: ${{ github.event.release.body }}
          URL: ${{ github.event.release.html_url }}
        run: |
          DESCRIPTION=$(jq -Rs . <<< "$NOTES")
          curl -sS -X POST "$WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{
              \"content\": \"\",
              \"embeds\": [{
                \"title\": \"Released: $NAME\",
                \"description\": $DESCRIPTION,
                \"url\": \"$URL\",
                \"color\": 5793266
              }]
            }"

Section 3

Recipe 2: a plain curl POST

If you prefer your own backend or just want to test the webhook in ten seconds, a single curl call is all it takes.

You do not need GitHub Actions to use a webhook. Any environment that can make an HTTP request can post to Discord, which makes this trivial to test from your terminal or wire into an existing service that already hears about your releases. The minimal version is a single POST with a content field; the nicer version uses an embed exactly like the Action above.

Here is the smallest possible working example. Replace the URL with your real webhook and run it - a message appears in the channel immediately. This is also the fastest way to confirm your webhook URL is valid before you build anything around it. If this works, the GitHub Actions recipe above will work too, because it is the same POST with the values filled in from the release event.

Once you have confirmed the basic POST, upgrade to an embed for anything user-facing. A bare content string is fine for a quick internal ping, but a titled, linked embed reads as an intentional announcement and gives readers a one-click path to the full release notes. Keep the content field empty unless you actually intend to ping people, for the etiquette reasons in the next section.

Minimal Discord webhook test (curl)

curl -sS -X POST "https://discord.com/api/webhooks/ID/TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "",
    "embeds": [{
      "title": "Released: v2.4.0",
      "description": "Approval rules now route releases to the right reviewer.",
      "url": "https://github.com/your-org/your-repo/releases/tag/v2.4.0",
      "color": 5793266
    }]
  }'

Section 4

Bot vs webhook: which do you actually need?

Most people reaching for a bot here do not need one. The webhook covers the common case; the bot is for when you need interaction.

A webhook is a one-way pipe: it posts messages and nothing more. That is perfect for a release feed, because posting a release into a channel is inherently one-way. It is simple, has no auth lifecycle, and cannot do anything beyond send messages, which is also a security benefit - a leaked webhook URL can spam one channel, not control your server. For the overwhelming majority of release announcements, a webhook is the correct tool and a bot is overkill.

A bot is a full Discord application with a token, permissions, and the ability to read messages, respond to commands, manage roles, and interact with users. You want a bot when the release post needs to do more than appear: reacting to user commands, posting into threads programmatically, gating announcements behind roles, or integrating releases into a richer community workflow. That power comes with real cost - registering an application, managing a bot token, hosting the bot process, and handling the gateway connection - so only take it on when the interaction justifies it.

The simple rule: if you only need releases to show up in a channel, use a webhook. If you need the release post to participate in conversations or respond to users, use a bot. Do not build and host a bot just to send a message a webhook could send. Choosing the heavier tool when the lighter one fits is a common way to create maintenance you did not need.

  • Webhook: one-way, no auth lifecycle, perfect for a release feed.
  • Bot: a full app with a token, for interaction, commands, and roles.
  • Use a webhook unless the post needs to respond to or manage users.
  • A leaked webhook can spam one channel; a bot token is far more sensitive.

Section 5

Mention etiquette: do not ping everyone

The fastest way to get muted by your own community is to ping everyone on a routine release. Restraint is part of the recipe.

Discord mentions are powerful and easy to abuse. An everyone or here notification interrupts every member, and using it for every routine release trains your community to mute the channel - which defeats the purpose of posting there at all. The recipes above deliberately leave the content field empty and put the announcement in an embed precisely so the message lands without pinging anyone. A release showing up in a dedicated releases channel is enough; people who care will see it.

Reserve mentions for genuinely mention-worthy moments. A major release, a security fix that requires action, or a breaking change that affects everyone can justify a ping - and even then, a role mention like a self-assigned releases role is far better than an everyone ping, because only people who opted in get interrupted. The etiquette is the same as the broader cadence principle: protect attention as a finite budget, because if every post pings, people stop reading the one that matters.

A practical setup is a dedicated channel for your automated release feed with no pings, plus a sparing role mention for the rare release that truly needs immediate attention. This keeps the automatic firehose useful without making it annoying, and it respects the difference between here is what we shipped and you need to act on this now.

  • Leave the content field empty and announce via an embed.
  • Never ping everyone for routine releases; you will get the channel muted.
  • Reserve pings for major, security, or breaking releases.
  • Prefer an opt-in role mention over an everyone or here ping.

Section 6

When the webhook is not enough: the S2P path

The webhook is great for one channel with no review. The moment you want approval or multiple channels, the trade-off shifts.

The DIY webhook is the right answer for an automatic, no-review release feed into a single Discord channel, and this guide recommends it for exactly that. Its limits show up when your needs grow past that one job. There is no approval step, so whatever the workflow builds posts instantly - fine for a community releases channel, riskier if the same content represents your brand. And a webhook only knows about Discord, so if you also want the release on LinkedIn, X, or Bluesky with copy that fits each, you are back to maintaining a separate path per channel.

This is where a release-native tool complements rather than replaces the webhook idea. S2P detects your GitHub release once and can draft channel-native posts for Discord and your other destinations together, then route them through approval before anything publishes. You get the same instant-from-release behavior, but with a human able to glance at the post first and with one release fanning out to every channel in the right voice, instead of a webhook per platform and no review anywhere.

The honest split mirrors the rest of our how-to guides. If you want a dependable release feed in one Discord channel and nothing more, the webhook recipe above is genuinely the best tool and you should use it. If you want approval, multiple channels from one release, and a record of what went where, that is the job a release-native tool is built for. Many teams do both: a raw webhook for an internal channel, and S2P for the public, multi-channel announcements that need review.

  • The webhook is ideal for one channel with no review needed.
  • S2P adds an approval step before a brand post goes live.
  • One detected release fans out to Discord plus other channels in fitting copy.
  • Common pattern: raw webhook internally, S2P for public multi-channel posts.

FAQ

Questions this article answers

How do I post a GitHub release to Discord?

Create an incoming webhook in your Discord channel settings under Integrations, copy the URL, and store it as a secret. Then POST a JSON message to that URL whenever a release publishes, either from a GitHub Actions workflow triggered on the release event or from any script using curl. No OAuth is required.

Do I need a Discord bot to post releases?

Usually no. A webhook posts messages one way and is perfect for a release feed with no auth lifecycle to maintain. Use a bot only when the post needs to do more than appear, such as responding to commands, posting in threads programmatically, or managing roles. For a plain release announcement, a webhook is the right tool.

Is it safe to put a Discord webhook URL in GitHub?

Store it as a repository secret, never in committed code. Anyone with the webhook URL can post to that channel, so treat it like a password. A leaked webhook can be abused to spam the one channel it targets, which is much less severe than a leaked bot token, but it should still be kept secret and can be regenerated if exposed.

Should release posts mention everyone in Discord?

No, not for routine releases. Pinging everyone or here on every release trains members to mute the channel. Leave the content field empty and announce via an embed so the message lands without pinging. Reserve mentions, ideally an opt-in role mention, for major, security, or breaking releases that genuinely require attention.

What does S2P add over a Discord webhook?

A webhook posts to one channel with no review. S2P detects the GitHub release once, drafts channel-native posts for Discord and your other destinations, and routes them for approval before publishing. You get the same instant-from-release behavior plus a human review step and one release fanning out to multiple channels in the right voice.

Can I use both a webhook and S2P?

Yes, and many teams do. A raw webhook is a great no-review feed for an internal or community releases channel, while S2P handles the public, multi-channel announcements that need approval and channel-specific copy. They are complementary: use the webhook where you want zero friction and the tool where you want control.

Related guides and pages

Where to go next

Hand-picked pages that go deeper on the workflow, channels, and tooling covered above.

Ship 2 Post

Stop writing release posts.

Your engineers already commit. Now those commits become content - in your voice, on every channel.