Yes, we're now running our only Summer Sale. All Courses are 30% off until 20th July, 2026:
Create Pull Request With GitHub Actions
Last updated: June 17, 2025
1. Overview
GitHub Actions is a powerful automation platform for continuous integration and continuous delivery (CI/CD) workflows. One common requirement when working with GitHub repositories is to programmatically create a Pull Request (PR) as part of an automated update, whether it’s refreshing a timestamp, syncing generated files, or applying a bulk change across branches.
In this tutorial, we’ll explore multiple ways to create a Pull Request using GitHub Actions, including the GitHub CLI, REST API, and the peter-evans/create-pull-request action.
2. Setup
Before we can create pull requests from a GitHub Actions workflow, we must ensure Git is configured correctly and authenticated using a token.
Let’s start by creating a composite action that handles this setup:
$ cat .github/actions/setup-repo/action.yml
name: 'Setup Git Repository'
description: 'Configure Git user and authentication for commits'
inputs:
token:
description: 'GitHub token'
required: true
runs:
using: 'composite'
steps:
- name: Configure Git user
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
shell: bash
- name: Authenticate using token
run: |
git remote set-url origin https://x-access-token:${{ inputs.token }}@github.com/${{ github.repository }}
shell: bash
We’ll reuse this action to ensure that Git operations, such as committing and pushing, work correctly.
Next, we’ll define another composite action that updates a file and optionally pushes the changes to a new branch:
$ cat .github/actions/update-and-push/action.yml
name: 'Update File and Push Branch'
description: 'Creates a new branch, modifies a file, commits, and pushes'
inputs:
update_only:
required: false
default: false
outputs:
branch:
description: 'Branch name'
value: ${{ steps.push.outputs.branch }}
runs:
using: 'composite'
steps:
- name: Update file
run: echo "Updated at $(date -u --rfc-3339=ns)" > gh-update.txt
shell: bash
- name: Commit and push
id: push
run: |
branch="gh/update-$(date +%s)"
if [ "${{ inputs.update_only }}" = "false" ]; then
git checkout -b "$branch"
git add gh-update.txt
git commit -m "chore: update file"
echo "Pushing branch: $branch"
git push origin "$branch"
else
echo "Skipping push as update_only is true"
fi
echo "branch=$branch" >> "$GITHUB_OUTPUT"
shell: bash
We’ll use this action to handle file updates and create a uniquely named branch to hold the changes. Further, we’ve added the update_only flag to the composite action to skip committing to the branch.
Finally, we must create a personal access token with the “repo” scope and add it as a repository secret named GH_TOKEN.
3. Using the GitHub CLI (gh)
The GitHub CLI provides a convenient way to interact with repositories from the command line. We can use it in a workflow to open a pull request after pushing changes to a branch.
First, let’s write the workflow in the create-pr-gh-cli.yml file under the .github/workflows directory:
$ cat .github/workflows/create-pr-gh-cli.yml
name: "Create Pull Request via GitHub CLI"
on:
workflow_dispatch:
jobs:
create-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: ./.github/actions/setup-repo
with:
token: ${{ secrets.GH_TOKEN }}
- uses: ./.github/actions/update-and-push
- name: Open pull request using gh CLI
run: |
gh pr create \
--title "chore: update via gh cli" \
--body "This PR was created using the GitHub CLI." \
--base main \
--head $(git rev-parse --abbrev-ref HEAD)
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
We used the gh pr create command to open a pull request from the newly pushed branch. Further, we explicitly passed the GITHUB_TOKEN to allow the CLI to authenticate.
Next, let’s verify our workflow by running it manually:
The workflow executed successfully.
Lastly, we should see a new pull request in the list of open PRs:
Excellent! It looks like we nailed it.
4. Using the GitHub REST API
If we prefer not to rely on external tools like the GitHub CLI, we can use the GitHub REST API directly to create a pull request from within a workflow.
Let’s start by writing the workflow in the .github/workflows/create-pr-rest.yml file:
$ cat .github/workflows/create-pr-rest.yml
name: "Create Pull Request via REST API"
on:
workflow_dispatch:
jobs:
create-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: ./.github/actions/setup-repo
with:
token: ${{ secrets.GH_TOKEN }}
- uses: ./.github/actions/update-and-push
- name: Open pull request via REST API
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.GH_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d "$(jq -n \
--arg title 'chore: daily timestamp update' \
--arg head "$(git rev-parse --abbrev-ref HEAD)" \
--arg base 'main' \
--arg body 'This PR updates the timestamp file automatically via GitHub Actions.' \
'{title: $title, head: $head, base: $base, body: $body}')"
We used the jq command to construct a POST request to the /pulls endpoint with the necessary metadata to open a pull request from the new branch.
Now, we can trigger a workflow run and verify that a pull request is generated with the related changes:
Perfect! It worked as expected.
5. Using peter-evans/create-pull-request Action
If we want a ready-to-use and well-maintained solution for creating pull requests, we can use the peter-evans/create-pull-request action. It handles the entire process, from committing changes to opening the pull request, without requiring custom logic.
Let’s define the workflow in the .github/workflows/create-pr-peter-evans.yml file:
$ cat .github/workflows/create-pr-peter-evans.yml
name: "Create Pull Request via peter-evans Action"
on:
workflow_dispatch:
jobs:
create-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: ./.github/actions/setup-repo
with:
token: ${{ secrets.GH_TOKEN }}
- uses: ./.github/actions/update-and-push
id: update
with:
update_only: true
- name: Open pull request using peter-evans action
uses: peter-evans/create-pull-request@v5
with:
branch: ${{ steps.update.outputs.branch }}
base: main
commit-message: "chore: update via create-pull-request action"
title: "chore: update via create-pull-request action"
body: "This PR was created using the peter-evans/create-pull-request action."
token: ${{ secrets.GH_TOKEN }}
We used the peter-evans/create-pull-request action to automate the entire pull request creation process in a single step. Furthermore, we set the update_only flag to true for the update-and-push action because the create-pull-request action expects uncommitted changes in the branch.
Now, let’s run the workflow:
Fantastic! We got it working.
6. Conclusion
In this tutorial, we explored different ways to create a pull request using GitHub Actions, including the GitHub CLI, the REST API, and the peter-evans/create-pull-request action.
Each method serves a different use case, and we can choose the one that best fits our workflow.