create-pull-request

repository·main·Indexed 25 days ago

https://github.com/peter-evans/create-pull-request

A GitHub Action that automates the creation and updating of pull requests based on file changes made during a workflow execution in the Actions workspace. It detects changes, commits them to a new or existing branch, and creates or updates a pull request to merge those changes into a base branch.

Tokens
16.4K
Snippets
36
Records
60
Agent score
78%

What's inside create-pull-request

  1. Overview of Create Pull Request

    main

    The create-pull-request GitHub Action automates the process of creating a pull request for changes made within a GitHub Actions workspace. It is intended to be used after other workflow steps have modified or added files to the repository.

    When executed, the action:

    1. Detects changes in the workspace, including untracked (new) files, modified tracked files, and unpushed commits made during the workflow.
    2. Commits these changes to a new branch (or updates an existing pull request branch).
    3. Creates or updates a pull request to merge that branch into the base branch (the branch checked out in the workflow).
  2. Understand Action Behaviour

    main

    The action's default behavior is to maintain a single pull request that is updated as new changes are made.

    • If changes exist: A new branch is pushed and a pull request is created.
    • If no changes exist: The action exits silently.
    • If a PR already exists: The action updates the existing pull request if new changes are detected.
    • If a PR becomes unnecessary: If the base branch is updated such that there is no longer a diff between the PR branch and the base, the action automatically closes the pull request. If delete-branch is set to true, the branch will also be deleted.
  3. Configure Workflow Permissions

    main

    For this action to work, you must explicitly allow GitHub Actions to create pull requests.

    Navigate to your repository's settings under Actions > General > Workflow permissions to enable this. For organization-owned repositories, admins can manage this in the organization settings.

  4. Push using SSH (deploy keys)

    main

    You can use SSH deploy keys as an alternative to a Personal Access Token (PAT) to allow the action to push changes. This is useful for triggering on: push workflows.

    Limitations:

    • Cannot be used alone to create pull requests in a remote repository (a PAT is still required for the PR creation).
    • Cannot be used with sign-commits: true.

    Setup Steps:

    1. Create an SSH key pair (no passphrase).
    2. Add the public key as a deploy key in the target repository with "Allow write access" enabled.
    3. Add the private key as a repository secret.
    4. Configure actions/checkout to use the ssh-key.
        steps:
          - uses: actions/checkout@v6
            with:
              ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
    
          # Make changes to pull request here
    
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v8
  5. Upgrade to v4

    main

    When upgrading to v4, note the following requirements and changes:

    Breaking Changes

    • add-paths Input: The value -A is no longer supported. To commit all new and modified files, omit the add-paths input entirely.

    Requirements

    • Runtime: Updated to Node.js 16. Requires Actions runner v2.285.0 or later.
    • GHES: If using GitHub Enterprise Server, version GHES 3.4 or later is required.
  6. GPG commit signature verification

    main

    For organizations requiring specific commit signing, you can use GPG to sign commits with a user-generated GPG key.

    Requirements:

    • The committer email address MUST match the email address used to create your GPG key.
    • You must use a PAT (not a bot token) for the token input.

    Setup Steps:

    1. Generate a GPG key and add the public key to your GitHub account.
    2. Export the private key (e.g., gpg --armor --export-secret-key email@example.com).
    3. Store the private key and its passphrase in repository secrets.
    4. Use crazy-max/ghaction-import-gpg to import the key into the workflow.

    Example Workflow:

        steps:
          - uses: actions/checkout@v6
    
          - uses: crazy-max/ghaction-import-gpg@v5
            with:
              gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
              passphrase: ${{ secrets.GPG_PASSPHRASE }}
              git_user_signingkey: true
              git_commit_gpgsign: true
    
          # Make changes to pull request here
    
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v8
            with:
              token: ${{ secrets.PAT }}
              committer: example <email@example.com>
  7. Install and use Create Pull Request

    main

    To use this action, include it in your GitHub Actions workflow after checking out your repository. You can pin to a specific release version using the @v8.x.x format.

          - uses: actions/checkout@v6
    
          # Make changes to pull request here
    
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v8
  8. Automate code fixes with a pull request (autopep8 example)

    main

    You can use create-pull-request to automatically apply code fixes (like linting) by raising a new pull request against the original one.

    Workflow Pattern:

    1. Run a linting tool (e.g., autopep8) on a pull request.
    2. If changes are made, use create-pull-request to create a new branch (e.g., autopep8-patches/...) and a PR containing those fixes.
    3. Deliberately fail the original check to signal that fixes are pending.
    4. Once the fix PR is merged, the original workflow runs again, finds no changes, and passes.

    Important Limitations:

    • This pattern does not work for pull requests raised from forks due to GitHub token restrictions on public repositories. It works for private repositories if configured to enable workflows 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@v6
            with:
              ref: ${{ github.head_ref }}
          - name: autopep8
            id: autopep8
            uses: peter-evans/autopep8@v1
            with:
              args: --exit-code --recursive --in-place --aggressive --aggressive .
          - name: Set autopep8 branch name
            id: vars
            run: |
              branch-name="autopep8-patches/${{ github.head_ref }}"
              echo "branch-name=$branch-name" >> $GITHUB_OUTPUT
          - name: Create Pull Request
            if: steps.autopep8.outputs.exit-code == 2
            uses: peter-evans/create-pull-request@v8
            with:
              commit-message: autopep8 action fixes
              title: Fixes by autopep8 action
              body: This is an auto-generated PR with fixes by autopep8.
              labels: autopep8, automated pr
              branch: ${{ steps.vars.outputs.branch-name }}
          - name: Fail if autopep8 made changes
            if: steps.autopep8.outputs.exit-code == 2
            run: exit 1
  9. Handle Detached HEAD states with the `base` input

    main

    Some GitHub events (like release or pull_request) check out a specific commit rather than a branch, resulting in a "detached HEAD" state. In these cases, you must provide the base input so the action can correctly rebase your changes.

    • For pull_request events: Use ${{ github.head_ref }} to base the new PR on the current pull request's branch.
    • For release events: Specify the branch name of the tagged commit (e.g., main).
          # For pull_request events
          - uses: peter-evans/create-pull-request@v8
            with:
              base: ${{ github.head_ref }}
    
          # For release events
          - uses: peter-evans/create-pull-request@v8
            with:
              base: main
  10. Push pull request branches to a fork

    main

    To follow the principle of least privilege, you can push pull request branches to a fork instead of the main repository. This is typically done using a dedicated machine account.

    Requirements:

    • The machine account needs read access to the parent repository.
    • The machine account needs write access to its own fork.
    • If the machine account lacks write access to the parent, you cannot use labels, assignees, reviewers, team-reviewers, or milestone.

    Configuration: Set the push-to-fork input to the full repository name of the fork (e.g., machine-user/fork-of-repository).

          - uses: actions/checkout@v6
    
          # Make changes to pull request here
    
          - uses: peter-evans/create-pull-request@v8
            with:
              token: ${{ secrets.MACHINE_USER_PAT }}
              push-to-fork: machine-user/fork-of-repository
  11. Authenticate with GitHub App generated tokens

    main

    GitHub App tokens allow for fine-grained permissions scoped to specific repositories.

    App Configuration Requirements:

    • Contents: Read & write
    • Pull requests: Read & write
    • Workflows: Read & write (only if PRs contain workflow changes)
    • Members (Organization): Read-only (only if adding teams as reviewers)

    Usage Pattern: Use actions/create-github-app-token to generate a token and pass it to the token input of create-pull-request.

        steps:
          - uses: actions/create-github-app-token@v2
            id: generate-token
            with:
              app-id: ${{ secrets.APP_ID }}
              private-key: ${{ secrets.APP_PRIVATE_KEY }}
    
          - uses: actions/checkout@v6
    
          # Make changes to pull request here
    
          - name: Create Pull Request
            uses: peter-evans/create-pull-request@v8
            with:
              token: ${{ steps.generate-token.outputs.token }}