GitHub Actions
Continuous Integration
Pull Request
Workflow Automation
DevOps

Trigger Github Actions only when PR is merged

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

If you want a GitHub Actions workflow to run only after a pull request is actually merged, the trigger needs two parts. First, listen for the PR being closed. Second, check whether that closure happened because of a merge rather than a manual close.

Using the pull_request Closed Event

The right event is pull_request with types: [closed]. GitHub emits that event for both merged pull requests and pull requests that were simply closed without merging, so the workflow still needs a condition.

yaml
1name: Run only after merge
2
3on:
4  pull_request:
5    types: [closed]
6
7jobs:
8  deploy:
9    if: github.event.pull_request.merged == true
10    runs-on: ubuntu-latest
11    steps:
12      - uses: actions/checkout@v4
13      - run: echo "This PR was merged"

The if expression is the key line. Without it, the job would run for any closed pull request, including abandoned ones.

Restricting the Workflow to a Target Branch

Many repositories only want this workflow when a PR is merged into a specific branch such as main. Add a branch filter in the event configuration and keep the merged check at the job level.

yaml
1name: Post-merge checks
2
3on:
4  pull_request:
5    branches: [main]
6    types: [closed]
7
8jobs:
9  after-merge:
10    if: github.event.pull_request.merged == true
11    runs-on: ubuntu-latest
12    steps:
13      - uses: actions/checkout@v4
14      - run: echo "Merged into main"

This workflow runs only when the base branch of the pull request is main and the PR was merged.

Choosing Between pull_request and push

A common question is whether push to main is enough. Sometimes it is. If every change to main arrives through merged pull requests, a push workflow can effectively act as a post-merge workflow.

However, push has different semantics:

  • It also runs for direct pushes.
  • It does not expose pull request metadata in the same way.
  • It is harder to distinguish merge commits from other pushes cleanly.

If your logic depends on PR details such as labels, reviewers, or the merged flag itself, use pull_request with types: [closed].

Accessing Merge Metadata

Once the workflow is triggered from a merged PR, you can use fields from the event payload. For example, the merge commit SHA and PR title are often useful.

yaml
1jobs:
2  notify:
3    if: github.event.pull_request.merged == true
4    runs-on: ubuntu-latest
5    steps:
6      - run: echo "PR title: ${{ github.event.pull_request.title }}"
7      - run: echo "Merged by: ${{ github.event.pull_request.merged_by.login }}"
8      - run: echo "Merge commit: ${{ github.event.pull_request.merge_commit_sha }}"

This is helpful for release notes, deployment notifications, or branch-specific automation after code review has completed.

Common Pitfalls

The most common mistake is putting the merged check under on: instead of under a job or step if: condition. Event filters decide when the workflow starts, but merged is part of the event payload and must be evaluated after the event fires.

Another issue is forgetting that closed does not mean merged. A PR closed by hand still emits the same event type.

It is also easy to create duplicate automation by using both a pull_request merged workflow and a push workflow on the target branch without coordinating their responsibilities. If both run the same deployment, you will get double execution.

Summary

  • Trigger on pull_request with types: [closed] to capture merge completion.
  • Add if: github.event.pull_request.merged == true so the job runs only for merged PRs.
  • Use branch filters if the workflow should only apply to merges into a specific branch.
  • Prefer pull_request over push when you need PR metadata in the workflow.
  • Watch for duplicate runs if you also have push automation on the destination branch.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.