π GitHub Action for creating Pull Requests
GitHub Action that will create a pull request from the currently selected branch.
π¦ Available on
- Docker Hub: devopsinfra/action-pull-request:latest
- GitHub Packages: ghcr.io/devops-infra/action-pull-request:latest
β¨ Features
- Creates pull request if triggered from a current branch or any specified by
source_branchto atarget_branch - Title and body of a pull request can be specified with
titleandbody - Can assign
assignee,reviewer, one or morelabel, amilestoneor mark it as adraft - Can replace any
old_stringinside a pull request template with anew_string. Or put commits' subjects in place ofold_string - When
get_diffistruewill add list of commits in place of<!-- Diff commits -->and list of modified files in place of<!-- Diff files -->in a pull request template - When
allow_no_diffis set to true will continue execution and create pull request even if both branches have no differences, e.g. having only a merge commit - Supports both
amd64andarm64architectures
π Related Actions
Useful in combination with my other action devops-infra/action-commit-push.
Both actions are compatible when you use actions/checkout with a custom path:
- set
repository_pathindevops-infra/action-commit-push - set the same
repository_pathindevops-infra/action-pull-request
This action isolates global Git config in a temporary file (via GIT_CONFIG_GLOBAL) to avoid modifying runner/user-level Git config.
π Badges
π·οΈ Version Tags: vX, vX.Y, vX.Y.Z
This action supports three tag levels for flexible versioning:
vX: latest patch of the major version (e.g.,v1).vX.Y: latest patch of the minor version (e.g.,v1.2).vX.Y.Z: fixed to a specific release (e.g.,v1.2.3).
π API Reference
- name: Run the Action
uses: devops-infra/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
repository: devops-infra/action-pull-request
repository_path: .
source_branch: development
target_branch: master
title: My pull request
template: .github/PULL_REQUEST_TEMPLATE.md
body: "**Automated pull request**"
reviewer: octocat
assignee: octocat
label: enhancement
milestone: My milestone
project: Engineering Roadmap
draft: true
old_string: "<!-- Add your description here -->"
new_string: "** Automatic pull request**"
get_diff: true
ignore_users: "dependabot"
allow_no_diff: false
max_body_bytes: 65000
max_diff_lines: 0
π§ Input Parameters
| Input Variable | Required | Default | Description |
|---|---|---|---|
github_token |
Yes | "" |
GitHub token ${{ secrets.GITHUB_TOKEN }} |
repository |
No | ${{ github.repository }} |
Target repository in owner/name format used for API calls and git remote auth |
repository_path |
No | . |
Relative path under GITHUB_WORKSPACE to the checked-out repository |
source_branch |
No | current branch | Name of the source branch |
target_branch |
No | master |
Name of the target branch. Change it if you use main |
title |
No | subject of the first commit | Pull request title |
template |
No | "" |
Template file location |
body |
No | list of commits | Pull request body |
reviewer |
No | "" |
Reviewer's username |
assignee |
No | "" |
Assignee's usernames |
label |
No | "" |
Labels to apply, comma separated |
milestone |
No | "" |
Milestone |
project |
No | "" |
GitHub Project title to add the pull request to |
draft |
No | false |
Whether to mark it as a draft |
old_string |
No | "" |
Old string for the replacement in the template |
new_string |
No | "" |
New string for the replacement in the template. If not specified, but old_string was, it will gather commits subjects |
get_diff |
No | false |
Whether to replace predefined comments with differences between branches - see details below |
ignore_users |
No | "dependabot" |
List of users to ignore, comma separated |
allow_no_diff |
No | false |
Allows to continue on merge commits with no diffs |
max_body_bytes |
No | 65000 |
Maximum PR body size in bytes before overflow is posted as managed PR comments |
max_diff_lines |
No | 0 |
Maximum lines per generated diff section (0 means unlimited) |
π Required Workflow Permissions
Set explicit job/workflow token permissions when using this action:
permissions:
contents: read
pull-requests: write
issues: write
contents: readis required to read repository state.pull-requests: writeis required to create and update pull requests.issues: writeis required when managed overflow comments are created, updated, or deleted (including cleanup on later runs).- Project assignment via
projectrequires a token/auth context thatghcan use with project access.
π€ Output Parameters
| Output | Description |
|---|---|
url |
Pull request URL |
pr_number |
Number of GitHub pull request |
βΏ How get_diff works
In previous versions occurrences of following strings in a template result with replacing them with list of commits and list of modified files (<!-- Diff commits --> and <!-- Diff files -->).
Now this action will expect to have three types of comment blocks. Meaning anything between START and END comment will get replaced. This is especially important when updating pull request with new commits.
<!-- Diff summary - START -->and<!-- Diff summary - END -->- show first lines of each commit in the pull request<!-- Diff commits - START -->and<!-- Diff commits - END -->- show graph of commits in the pull request, with authors' info and time<!-- Diff files - START -->and<!-- Diff files - END -->- show list of modified files
When the generated PR body exceeds max_body_bytes, the action keeps the main body within the configured size and publishes remaining content in managed PR comments.
Managed comments are updated/deleted on subsequent runs.
Set max_diff_lines to cap each generated diff section before insertion.
If your template uses old comment strings it will try to adjust them in the pull request body to a new standard when pull request is created. It will not modify the template.
CAUTION: Remember to not use default fetch-depth for actions/checkout action. Rather set it to 0 - see example below.
π» Usage Examples
Red areas show fields that can be dynamically expanded based on commits to the current branch. Blue areas show fields that can be set in action configuration.

π Basic Example
Create pull request for non-master branches:
name: Run the Action
on:
push:
branches-ignore: master
permissions:
contents: read
pull-requests: write
issues: write
jobs:
action-pull-request:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Create pull request
uses: devops-infra/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
title: Automatic pull request
π Advanced Example
Use first commit as a title and part of body, add a label based on a branch name, add git differences in the template:
name: Run the Action
on:
push:
branches-ignore: master
permissions:
contents: read
pull-requests: write
issues: write
jobs:
action-pull-request:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
path: repo
- name: Run the Action
if: startsWith(github.ref, 'refs/heads/feature')
uses: devops-infra/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.repository }}
repository_path: repo
title: ${{ github.event.commits[0].message }}
assignee: ${{ github.actor }}
label: automatic,feature
project: Engineering Roadmap
template: .github/PULL_REQUEST_TEMPLATE/FEATURE.md
old_string: "**Write your description here**"
new_string: ${{ github.event.commits[0].message }}
get_diff: true
π― Use specific version
Pick the tag level based on your stability needs:
vX.Y.Z: exact immutable release (most predictable)vX.Y: latest patch within one minor linevX: latest patch within one major line
name: Run the Action
on:
push:
branches-ignore: master
permissions:
contents: read
pull-requests: write
issues: write
jobs:
action-pull-request:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: devops-infra/[email protected]
id: Pin patch version
- uses: devops-infra/[email protected]
id: Pin minor version
- uses: devops-infra/action-pull-request@v1
id: Pin major version
π€ Contributing
Contributions are welcome! See CONTRIBUTING. This project is licensed under the MIT License - see the LICENSE file for details.
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π¬ Support
If you have any questions or need help, please:
- π Create an issue
- π Star this repository if you find it useful!
π§ͺ End-to-End Validation
Use the manual workflow .github/workflows/manual-e2e-validate.yml to validate this action against the centralized E2E repository.
mode=refvalidates ref-oriented E2E paths against stable pinned action refs.mode=imageis wired but currently placeholder-only in the central E2E workflow for this action.
CI/CD automation also runs these E2E checks automatically:
- Pull requests: E2E validation runs through reusable org workflows.
- Release branch prepare: E2E validation runs against release candidate refs.
- Release create: E2E validation runs against production release refs.
Example trigger inputs:
mode=ref
mode=image
image_tag=v1.2.3-test
Forking
To publish images from a fork, set these variables so Task uses your registry identities:
DOCKER_USERNAME, DOCKER_ORG_NAME, GITHUB_USERNAME, GITHUB_ORG_NAME.
Two supported options (environment variables take precedence over .env):
# .env (local only, not committed)
DOCKER_USERNAME=your-dockerhub-user
DOCKER_ORG_NAME=your-dockerhub-org
GITHUB_USERNAME=your-github-user
GITHUB_ORG_NAME=your-github-org
# Shell override
DOCKER_USERNAME=your-dockerhub-user \
DOCKER_ORG_NAME=your-dockerhub-org \
GITHUB_USERNAME=your-github-user \
GITHUB_ORG_NAME=your-github-org \
task docker:build
Recommended setup:
- Local development: use a
.envfile. - GitHub Actions: set repo variables for the four values above, and secrets for
DOCKER_TOKENandGITHUB_TOKEN.
Publish images without a release:
- Run the
(Manual) Release Createworkflow withbuild_only: trueto build and push images without tagging a release.