Guide · checked 24 October 2026

How to post to social media from GitHub Actions Announce every release on X, LinkedIn and Bluesky

Trigger a workflow on release: published and add one step: the Upload-Post action posts the release name, notes and link to X, LinkedIn, Bluesky, Threads and more, with a shorter version for X. One API key in a repository secret replaces a set of credentials per network.

.github/workflows/announce-release.yml
name: Announce release
on:
  release:
    types: [published]

jobs:
  announce:
    if: ${{ !github.event.release.prerelease }}
    runs-on: ubuntu-latest
    steps:
      - uses: Upload-Post/upload-post-action@v1
        with:
          api-key: ${{ secrets.UPLOAD_POST_API_KEY }}
          profile: my-project
          platforms: x, linkedin, bluesky, threads
          text: |
            ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} is out.
            ${{ github.event.release.name }}
            ${{ github.event.release.html_url }}
          extra: |
            {"x_title": "${{ github.event.repository.name }} ${{ github.event.release.tag_name }} is out"}

Set it up in four steps

About 10 minutes, on any repository.

  1. 1

    Connect your accounts to Upload-Post

    Create a free account at app.upload-post.com, create a profile (for example “my-project”) and connect X, LinkedIn, Bluesky, Threads or any other network with its own login. No X developer account needed.

  2. 2

    Add the API key as a secret

    Create a key at app.upload-post.com/api-keys, then in the repository open Settings, Secrets and variables, Actions, and add it as UPLOAD_POST_API_KEY. Or run gh secret set UPLOAD_POST_API_KEY.

  3. 3

    Add the workflow

    Save the YAML above as .github/workflows/announce-release.yml. It runs when a release is published and skips pre-releases.

  4. 4

    Publish a release

    The step posts to every listed network and returns the post URLs in its outputs. Check them in the job log.

Every input and output, plus examples for videos and scheduled posts: GitHub Action guide.

Pick the right release trigger

From GitHub’s workflow events reference, read 24 October 2026.

TypeFires whenUse it for
publishedA release, pre-release or draft is publishedThe usual choice; add the prerelease check to skip betas
releasedA release is published, or a pre-release becomes a releaseStable releases only
prereleasedA pre-release is published (not from a draft)Announce betas separately
createdA release is published without first being saved as a draftMisses releases you publish from a draft

The trap that catches most projects: if release-please, semantic-release or another workflow creates the release with the default GITHUB_TOKEN, no new workflow run starts. Create the release with a personal access token or a GitHub App token, or post from the same workflow. Source: GitHub docs.

Write a post people read

Build the text from release.name, tag_name and html_url, not the raw changelog. Keep LinkedIn and Bluesky for the longer version with the link, and send X a short one through extra with x_title.

Expressions are pasted in as plain text, so a quote in a release name breaks the JSON in extra. Wrap free text with toJSON():

extra: |
  {"x_title": ${{ toJSON(github.event.release.name) }}}

A screenshot or a short demo video gets more attention than text: set type to photos or video and point media at a file in the repository.

X: costs and links

X’s API is pay per use: $0.015 per post and $0.200 for a post with a link. With Upload-Post you post through your connected X account, without an X developer app. The example keeps the link in the LinkedIn, Bluesky and Threads text; to add links to X posts too, turn on the X Links add-on ($19 a month, 50 link posts).

Sources: X API pricing, X Links add-on. More: X API pricing explained.

One step or one action per network

Popular posting actions on GitHub Marketplace, read 24 October 2026.

ActionNetworksCredentials you manageLatest release
Upload-Post Social Publisher Our product X, LinkedIn (profile and pages), Bluesky, Threads, Facebook, Instagram, TikTok, YouTube, Pinterest, Discord, Telegram, Google Business One API key v1.0.0 (2026)
ethomson/send-tweet-action X 4 X API secrets and your own X developer app v1.0.0 (2019)
nearform-actions/github-action-notify-twitter X X API secrets v1.3.0 (2026)
cbrgm/mastodon-github-action Mastodon Mastodon access token v2.2.5 (2026)
myConsciousness/bluesky-post Bluesky Bluesky app password v6 (2026)

There is no widely used action for LinkedIn. Building one means your own LinkedIn app and a token in a secret, and LinkedIn access tokens last 60 days, with refresh tokens limited to approved partners (LinkedIn docs). With Upload-Post the token stays in your connected account, not in the repository.

When the announcement does not go out

The problems people hit first, and the fix for each.

The workflow did not run

Releases created by another workflow with the default GITHUB_TOKEN, such as release-please or semantic-release, do not start new workflow runs. Create the release with a personal access token or a GitHub App token, or post from the same workflow.

Nothing happened for a draft

Drafts do not fire release events until they are published. Publish the draft and the published event fires.

The post failed with 401

The secret is missing or misnamed. The step reads api-key from secrets.UPLOAD_POST_API_KEY; check the name under Settings, Secrets and variables.

The release notes became a thread on X

Text over 280 characters is split into a thread on X, at line breaks first. For a single post, send a short x_title in extra. On X Premium, set x_long_text_as_post to true to publish the long text as one post.

A re-run posted twice

Re-running a job runs the step again and posts again. With wait: true, a failed step names the platforms that already published, so you only post to the rest.

GitHub Actions and social media: frequently asked questions

How do I trigger a workflow when a release is published?

Use on: release: types: [published]. It fires for releases and pre-releases when they are published, including drafts at the moment you publish them. Add if: !github.event.release.prerelease to skip pre-releases.

Why didn’t it run when release-please created the release?

Events created with the default GITHUB_TOKEN do not start new workflow runs. Give the release step a personal access token or a GitHub App token, or add the posting step to the workflow that creates the release.

Do I need an X developer account?

Not with Upload-Post: you connect your X account to Upload-Post once and the action posts through it. The single-network X actions need your own X developer app and four secrets.

What does posting to X from GitHub Actions cost?

X’s API is pay per use: $0.015 per post and $0.200 for a post with a link, on X’s price list. With Upload-Post, X posting is part of your plan, and the X Links add-on adds links to X posts.

Can I post to a LinkedIn company page from a workflow?

Yes. When you connect LinkedIn in Upload-Post, pick the company page (you need the Super admin or Content admin role on it), or send target_linkedin_page_id in extra. There is no token to renew in the repository.

Can I post to Bluesky and Threads in the same step?

Yes. List them in platforms (x, linkedin, bluesky, threads) and one step posts to all of them, with the post URLs returned in the outputs.

Can I attach a screenshot or a demo video?

Yes. Set type to photos or video and media to a path in the repository or a public URL. With wait: true the step waits for the post URLs.

Can I schedule the announcement instead of posting at once?

Yes. Set scheduled-date and timezone, or add-to-queue to use your posting queue’s next slot.

Announce your next release everywhere

Free plan, no card. One secret for X, LinkedIn, Bluesky, Threads and more.