How to push to protected main branches in a GitHub Action?

Viewed 1602

This is my github action workflow.

name: Release

on:
  push:
    branches:
      - main

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          persist-credentials: false
      - name: Setup java
        uses: actions/setup-java@v1
        with:
          java-version: 11
      - name: Setup node
        uses: actions/setup-node@v1
        with:
          node-version: "14.x"
          cache: npm
      - name: Install dependencies
        run: npm ci
      - name: Build package
        run: npm run build --if-present
      - name: Semantic release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          HUSKY: 0
        run: chmod +x script/prepare-release.sh && npx semantic-release

However, my workflow fails with the following error log.

[semantic-release] › ✖  An error occurred while running semantic-release: Error: Command failed with exit code 1: git push --tags https://x-access-token:[secure]@github.com/didrlgus/convention-template.git HEAD:main
remote: error: GH006: Protected branch update failed for refs/heads/main.        
remote: error: At least 1 approving review is required by reviewers with write access.      

Maybe it's because my main branch is a protected branch.
How can I push with a protected branch on github action?

2 Answers

There is a workaround. Steps as follows:

  1. Create new Github user eg. my-org-bot

  2. Generate Personal Access Token for this user on https://github.com/settings/tokens and save it somewhere (select repo scope for the token)

  3. Go to your repo and add my-org-bot to contributors

  4. Open your branch protection rules and add my-org-bot to the rule below: enter image description here

  5. Go to repository secrets and add new secret for Actions with key =BOT_ACCESS_TOKEN and the value = Personal Access Token generated previously

  6. Modify your GH Workflow Checkout step with below: enter image description here

Now your workflow should be able to push directly to your protected branch on behalf of my-org-bot user.

The solution that works for us is as follows:

name: Version and Package Repo
on:
  push:
    branches: [ master, main ]
jobs:
  build:
    if: github.event.commits[0].author.name != 'GitHubActions'
    runs-on: ubuntu-18.04
    steps:
    - name: Checkout repo
      uses: actions/checkout@v2
      with:
        fetch-depth: 0
        token: ${{ secrets.PAT }}
    - name: Configure git
      run: |
        git config user.name "GitHubActions"
        git config user.email "<>"
    - name: Install NPM Packages
      run: npm install
      env:
        NODE_AUTH_TOKEN: $\{{ secrets.PAT }}
    - name: Version and Package
      run: npm version patch --force
      env:
        NODE_AUTH_TOKEN: $\{{ secrets.PAT }}
    - name: Update git
      run: |
        git push
        git push --tags

This runs on all pushes to master and main branches (we use the same script on multiple repos) and it:

  • checks the repo out
  • configures git
  • installs and then versions some NPM packages (not relevant to this issue, aside from the job making some kind of change to the repo) - this creates a new commit
  • pushes the changes back to the same branch

secrets.PAT is a personal access token of a user with admin rights and the repo has branch protection on, but excludes admins.

It is worth considering that if you run git push from an action with the on push trigger and you're using a PAT rather than GITHUB_TOKEN, then the action will run in a loop. If you are using GITHUB_TOKEN then GitHub Actions prevents the action running again automatically. We use the conditional if line at the top of the job to prevent the job running if the author name of the last commit is GitHubActions. This is the author name set in the Configure git stage, so the commits that happen within this job (as a result of npm version patch) are from an author with this name.

If the author variable doesn't work for you, there are plenty of others you can use:

https://docs.github.com/en/actions/learn-github-actions/contexts#github-context https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push

The downside of this approach is that you always get a second run appear in your list of actions which is immediately skipped.

Related