Merge Cheer

Zero-config GitHub Action that comments a G-rated celebration GIF when a pull request merges. This page is the live demo.

Watch the demo

What happens on merge

  1. A human pull request merges. Bots are skipped.
  2. The Action posts one comment. It does not check out the pull request.
  3. The comment is a thank-you plus a G-rated GIF the Action already ships. No Giphy key.

Zero-config comment

Merged — thank you @alice and @bob.

comic celebration GIF posted on the merged pull request

With an OpenAI key — live on #53

Cheers to YauhenBichel for keeping model cheers that are about the pull request!

celebration GIF from the model-written #53 comment

Live loops

Four of the shipped GIFs, looping here. Default topic: auto picks a random theme (seeded by the pull request number, so the same PR stays stable). Pin a group when you want one mood every time.

comic pop GIF
comic
sunny GIF
sunny
game GIF
game
sticker GIF
sticker

IT-section themes, same Action. Pin topic: python or topic: devops when the repo has a home.

devops GIF
devops
python GIF
python
frontend GIF
frontend
golang GIF
golang

Also on the Action: ship, fix, docs, tests, cleanup, celebration, welcome, party, space, magic, coffee, robot, yeah, sre, qa, design, architecture, engineering, backend, java, cpp. topic: title reads the PR title and body (typo / style / lint / format / chore: map to cleanup; build: maps to tests). A no-cheer or skip-cheer label skips the comment. A second run of the same moment does not post another GIF. A changes-requested cheer does not block the merge cheer. locale picks a built-in thank-you (es, de, fr, pt, uk, it, be, ja); a pinned message wins. Unset model keeps the stdlib path.

Install

Default is topic: auto — a random shipped theme, then one GIF in that group. Pin @v1.8.0 (current release).

GitHub

  1. Add the workflow below on the default branch.
  2. Keep pull_request_target and pull-requests: write so a fork merge can get a comment.
  3. Merge a human pull request. github-actions comments one GIF. Bots are skipped.
name: Celebrate merge
on:
  pull_request_target:
    types: [closed]
permissions:
  pull-requests: write
jobs:
  celebrate:
    if: github.event.pull_request.merged && github.event.pull_request.user.type != 'Bot'
    runs-on: ubuntu-latest
    steps:
      - uses: YauhenBichel/merge-cheer@v1.8.0

Pin a theme when you want the same mood on every merge:

- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    topic: comic   # or python, devops, sunny, game, …

@v1 is the older first release, not a floating major. An unknown topic falls back to celebration.

GitLab

  1. The Catalog row is not live. Copy examples/gitlab-ci.yml onto the default branch.
  2. Add a project access token GITLAB_TOKEN with api scope. CI_JOB_TOKEN cannot post notes.
  3. Merge into the default branch. The job finds that merge request and comments the GIF. A job that can see a closed or change-requested MR uses those moments instead.
celebrate:
  image: python:3.13-alpine
  variables:
    TOPIC: auto
    ACTION_REF: v1.8.0
    ACTION_REPO: YauhenBichel/merge-cheer
  script:
    - apk add --no-cache curl
    - curl -fsSL "https://raw.githubusercontent.com/YauhenBichel/merge-cheer/${ACTION_REF}/src/celebrate.py" -o /tmp/celebrate.py
    - python3 /tmp/celebrate.py

How to publish a CI/CD Catalog row later: MARKETPLACES.md.

Bitbucket

  1. The Docker Hub pipe is not public. Copy examples/bitbucket-pipelines.yml onto main.
  2. Add a secured repository variable BITBUCKET_ACCESS_TOKEN with pullrequest write.
  3. Merge a pull request. The step comments the GIF. A job that can see a declined or change-requested PR uses those moments instead.
script:
  - export ACTION_REF=v1.8.0
  - export ACTION_REPO=YauhenBichel/merge-cheer
  - export TOPIC="${TOPIC:-auto}"
  - curl -fsSL "https://raw.githubusercontent.com/YauhenBichel/merge-cheer/${ACTION_REF}/src/celebrate.py" -o celebrate.py
  - python3 celebrate.py

The Docker Hub pipe is not public. How to publish a Hub image and Pipes row later: MARKETPLACES.md.

Watch the AI demo

This is the model path. Zero-config is still Merged — thank you @author.

A human pull request merges. The model writes one short line about what landed. The GIF group still comes from topic. Default auto is a random theme. Set topic: title to use the title map. “Thanks” is empty. A line that names the work is the cheer people actually read.

github-actions comment on merge-cheer pull request 53
Live on #53. Cheers to YauhenBichel for keeping model cheers that are about the pull request!

Use a model on your repo

Zero-config stays a GIF plus Merged — thank you @author. Add one repository secret and the Action writes a line about what merged. Generic thanks are dropped. A 429 or a bad reply falls back to the stdlib line. The job still does not check out the pull request head.

  1. Settings → Secrets and variables → Actions → New repository secret named OPENAI_API_KEY.
  2. Copy examples/celebrate-openai.yml onto the default branch.
  3. Merge a human pull request. Read the comment, then the job log for model: message=….
- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    model: gpt-4o-mini
    model-api-key: ${{ secrets.OPENAI_API_KEY }}

@v1.7.0 drops generic thanks. A 429 or a junk reply falls back to the stdlib line. Any OpenAI-compatible host works via model-base-url.

Use Hugging Face Inference

Add repository secret HF_TOKEN with Inference Providers permission and copy examples/celebrate-huggingface.yml onto the default branch. No OpenAI key is needed.

- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    model: meta-llama/Llama-3.1-8B-Instruct:cheapest
    model-base-url: https://router.huggingface.co/v1
    model-api-key: ${{ secrets.HF_TOKEN }}

The 8B chat model uses the router's :cheapest provider policy. See Hugging Face Inference Providers for routing and billing; availability and prices can change. Errors, rate limits, and unsafe or generic replies still fall back to the default thank-you. No pull request head checkout.

Use Google Gemini

Add repository secret GEMINI_API_KEY from Google AI Studio and copy examples/celebrate-gemini.yml onto the default branch. If the key is already stored as GOOGLE_API_KEY, use ${{ secrets.GOOGLE_API_KEY }} for model-api-key.

- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    model: gemini-2.5-flash-lite
    model-base-url: https://generativelanguage.googleapis.com/v1beta/openai
    model-api-key: ${{ secrets.GEMINI_API_KEY }}

This uses Google's OpenAI-compatible endpoint, not an OpenAI key. The example uses 2.5 Flash-Lite because Gemini 2.0 Flash has been retired. Errors, rate limits, and unsafe or generic replies fall back to the default thank-you. No pull request head checkout; tests need no live API key.

Use Groq

Add repository secret GROQ_API_KEY from your Groq account and copy examples/celebrate-groq.yml onto the default branch. No OpenAI key is needed.

- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    model: openai/gpt-oss-20b
    model-base-url: https://api.groq.com/openai/v1
    model-api-key: ${{ secrets.GROQ_API_KEY }}

This uses Groq's low-cost GPT OSS 20B chat model. See the model page for current pricing and limits. Errors, rate limits, and unsafe or generic replies fall back to the default thank-you. No pull request head checkout or live API key is needed for the tests.

Use Anthropic Claude

Add repository secret ANTHROPIC_API_KEY using a key scoped to a single Anthropic workspace, then copy examples/celebrate-anthropic.yml onto the default branch. No OpenAI key is needed.

- uses: YauhenBichel/merge-cheer@v1.8.0
  with:
    model: claude-haiku-4-5-20251001
    model-base-url: https://api.anthropic.com/v1
    model-api-key: ${{ secrets.ANTHROPIC_API_KEY }}

This uses Anthropic's OpenAI compatibility layer, intended for evaluation rather than most production use cases. Multi-workspace keys require an anthropic-workspace-id header this Action does not expose; use a single-workspace key. The example pins Haiku 4.5. Errors, rate limits, and unsafe or malformed replies fall back to the default thank-you. No pull request head checkout or live key is needed for the tests.

Keep credits low

The model writes only the thank-you line. The GIF group stays from topic (auto is random, title is the map). One call per merge, then skip if that pull request already has a cheer. Use gpt-4o-mini. A 429 is not retried — the stdlib line posts instead. Pin message when you do not want a model call.

Cases

The Action already handles these. The videos above are two of them.

Used by

8 public repositories in MoleCare and this account already run Merge Cheer on the default branch.

MoleCare

Also

To be listed, merge a celebrate workflow that uses: YauhenBichel/merge-cheer@v1.8.0 on the default branch.