GitHub Actions: How to Create Pull Requests Automatically

Friday, October 11, 2019

Introducing one of the first GitHub Actions I wrote and published to the GitHub Marketplace. A generic action to automatically create a pull request for changes to your repository in the Actions workspace.

create-pull-request

Changes to a repository in the Actions workspace persist between steps in a workflow. The create-pull-request action is designed to be used in conjunction with other steps that modify or add files to your repository. The local changes will be automatically committed to a new branch and a pull request created.

Create Pull Request action will:

  1. Check for repository changes in the Actions workspace. This includes untracked (new) files as well as modified files.
  2. Commit all changes to a new branch, or update an existing pull request branch.
  3. Create a pull request to merge the new branch into the currently active branch executing the workflow.

There are many interesting use-cases for this type of action, such as…

  • Process management bots
  • Synchronization with external data sources
  • Updating contract definitions (API, Swagger docs, etc.)
  • Code linting/formatting
  • Static analysis/fixes
  • Scheduled process management

Basic example workflow

Here is simple example that adds a dated report to a repository and raises a pull request.

on:
  schedule:
    - cron: '0 10 * * *'
name: create-pull-request workflow
jobs:
  createPullRequest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Create report file
        run: date +%s > report.txt
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v1.7.2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: Add report file
          title: '[Example] Add report file'
          body: >
            This PR is auto-generated by 
            [create-pull-request](https://github.com/peter-evans/create-pull-request).
          labels: report, automated pr

This is an example of what pull requests created with the action look like on GitHub.

Pull Request Example

Example workflow to automate periodic dependency updates

This example workflow executes once a week and will create a pull request for any dependency updates. This pattern will work well for updating any kind of static content from an external source.

name: Update Dependencies
on:
  schedule:
    - cron:  '0 10 * * 1'
jobs:
  update-deps:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - uses: actions/setup-node@v1
        with:
          node-version: '10.x'
      - name: Update dependencies
        id: vars
        run: |
          npm install -g npm-check-updates
          ncu -u
          npm install
      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v1.7.2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: update dependencies
          author-email: peter-evans@users.noreply.github.com
          author-name: Peter Evans
          title: Automated Dependency Updates
          body: This is an auto-generated PR with dependency updates.
          labels: dep-updates, automated pr
          reviewers: peter-evans
          branch: dep-updates
          branch-suffix: none

Example usage with “on: pull_request” workflows

The following is an example workflow for a use-case where autopep8 action runs as both a check on pull requests and raises a further pull request to apply code fixes. This is a pattern that would work well for any automated code linting and fixing.

How it works:

  1. When a pull request is raised the workflow executes as a check.
  2. If autopep8 makes any fixes a pull request will be raised for those fixes to be merged into the current pull request branch. The workflow then deliberately causes the check to fail.
  3. When the pull request containing the fixes is merged the workflow runs again. This time autopep8 makes no changes and the check passes.
  4. The original pull request can now be merged.

Note that due to limitations on forked repositories this workflow does not work for pull requests raised from forks.

name: autopep8
on: pull_request
jobs:
  autopep8:
    # Check if the PR is not raised by this workflow and is not from a fork
    if: startsWith(github.head_ref, 'autopep8-patches') == false && github.event.pull_request.head.repo.full_name == github.repository
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: autopep8
        id: autopep8
        uses: peter-evans/autopep8@v1.1.0
        with:
          args: --exit-code --recursive --in-place --aggressive --aggressive .
      - name: Set autopep8 branch name
        id: vars
        run: echo ::set-output name=branch-name::"autopep8-patches/$GITHUB_HEAD_REF"
      - name: Create Pull Request
        if: steps.autopep8.outputs.exit-code == 2
        uses: peter-evans/create-pull-request@v1.7.2
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: autopep8 action fixes
          author-email: peter-evans@users.noreply.github.com
          author-name: Peter Evans
          title: Fixes by autopep8 action
          body: This is an auto-generated PR with fixes by autopep8.
          labels: autopep8, automated pr
          reviewers: peter-evans
          branch: ${{ steps.vars.outputs.branch-name }}
          branch-suffix: none
      - name: Fail if autopep8 made changes
        if: steps.autopep8.outputs.exit-code == 2
        run: exit 1

See the create-pull-request repository for the latest version and full usage details.