How to push to protected branches in a GitHub Action

Hello,

we have successfully set up GitHub Actions to automatically bundle/compile our JavaScript files whenever we push to master. This worked well when we first tried it out in a non-master branch, or for one of our extensions (a different repo).

Now, we get failures about not being able to push to protected branches. We use the automatic GITHUB_TOKEN secret for pushing - as far as I can tell, there is no way to configure this pseudo-user to be able to push to protected branches.

Is there a simple way to proceed here; or do we need to create a new deploy token (which we had to do for our previous solution which was running on Travis CI)?

Any help is appreciated, thanks!

24 Likes

@andreagriffiths11 I got an email about your response, but apparently it has been deleted again.

Since you were asking… it’s still not working unfortunately, even though I reduced some of the protection rules for our master branch.

See https://github.com/flarum/core/runs/212450535

1 Like

The error we are currently seeing is this:

remote: error: GH006: Protected branch update failed for refs/heads/master.
remote: error: 6 of 6 required status checks are expected. At least 1 approving review is required by reviewers with write access.

That’s not something that should affect direct pushes from an Action, right?

I could only fix this by disabling all checks for this branch, but that now obviously means all MR restrictions are lifted as well. Not good.

3 Likes

In my case I am getting this error:

$ git push origin master
error: src refspec refs/heads/master matches more than one.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to 'https://Ash258:***@github.com/Ash258/GithubActionsBucketForTesting.git'
^^^ Error! See above ^^^ (last command: hub push origin master)

https://github.com/Ash258/GithubActionsBucketForTesting/runs/212145912#step:4:110

1 Like

The token will not be able to push to a protected branch as that would enable anyone with write access to your repo to push to that protected branch by simply updating the workflow in a branch. Having that ability would make protected branches useless.

2 Likes

That is a strange error.  

The checkout step already checks out the ref that triggered the run and then resets that ref to the specific SHA that configured the run.  

https://github.com/Ash258/GithubActionsBucketForTesting/runs/212145912#step:3:420

I am unsure why your additional checkout is setting up another tracking ref.

1 Like

@chrispat wrote:

The token will not be able to push to a protected branch as that would enable anyone with write access to your repo to push to that protected branch by simply updating the workflow in a branch. Having that ability would make protected branches useless.

 

@chrispat, thanks for pointing out this potential branch protection bypass.

However, this potential bypass can easily be plugged.

In our company, we have a policy to set Code owners for the .github/ directory to repository’s Administrators. That way, we would also prevent an arbitrary user with write access to bypass branch protection rules by altering GitHub Action workflows.

I also don’t think all rules need to be bypased for a GitHub Action. The one that is relevant is the Require pull request reviews before merging. We would need to be able to directly push commits created by an Action, whilst continuing to require pull request reviews for PRs created by humans.

8 Likes

Thanks for getting back!

Could that restriction be lifted so that the token can not push to any protected branch *except* for the one that triggered the action (if that is even protected)? That way, workflow changes in non-protected branches could still not affect the protected branch, but my scenario would start working. (Because only pushes to master would trigger workflows that could themselves push to master. Any changes to these workflows would have to be committed / approved / merged by somebody with access to those protected branches anyway.

7 Likes

Could there not be an exception process for things like GitHub Apps? We have a CI utility that performs routine, scripted post-merge activities (version bumps, updating the changelog, etc). It would be incredibly useful to be able to specify “tokens from GitHub App X can bypass the protected branch” 

13 Likes

I created a personal access token.
I am admin in the repo, and admins have write access without restriction to protected branches.

Then added this token to the Secrets page (…/settings/secrets) as GITHUB\_TOKEN\_PHIL.

In the workflow file I override the pseudo token GITHUB_TOKEN:

-name:'Bump Version'  
uses:'phips28/gh-action-bump-version@master'  
env:
GITHUB\_TOKEN: ${{ secrets.GITHUB_TOKEN_PHIL }}

Now the action can push to the protected branch.

BUT this results in an endless workflow, the push triggers another action and so on…
This behavior doesnt appear if I use the default pseudo token and remove the protected state. In this case the action triggers once, and no trigger after the action pushed to branch. (Thats how it should be)
@chrispat is that inconsistency a bug? A push from an action should not trigger a action again IMO.

2 Likes

@phips28 A push from an Action does not trigger a new run, a git push with your own PAT will trigger.   In Actions we just get webhook events and all we can see is the actor.  When the actor is the actions app we do not trigger, however, if you happen to use your own PAT to do the push the actor will be you.  To Actions this does not appear any differnt than if you pushed from your own desktop.

1 Like

What scopes did you use for personal token?

1 Like

So currently the only solution is to create an admin/org owner account, generate a PAT from that account, then store that somewhere and use it to authenticate when writing back to the branch?

Another vote for allowing actions to write to protected branches.

11 Likes

In our team, we’re trying to automate as much as we can and we’ve been struggling for months due to this issue. We were left considering two options:

  1. Always disable Include administrators

  2. Don’t automate releases

We then noticed the Github API allows you to play with the include administrators or enforce_admins flag. We wrote this tool https://github.com/benjefferies/branch-protection-bot which, if put in a pipeline before a release step and ran again after it will temporarily enable, then disable Include administrators minimising the risk of accidental commits.

3 Likes

We’re facing the same problems. Was a bit dissapointed when I found out that GitHub Actions didn’t have push permission when it ran in the CI/CD-environment on protected branches.

We use lerna to handle our monorepo and plan to use the built-in publishing and versioning that comes with lerna based on conventional-commits. Right now that is not possible because we’re forced to disable all of our branch policies if we want the publishing and versioning process to be automated.

If we want to have branch policies active we now have to resolve to manually bumping versions locally, which pretty much means that anyone with push permission on our protected branches can bump to a version that does not follow conventional-commits. It’s also a bit of a chore as for prereleases we want to bump version and publish on a dist-tag when someone completes a pull request merge.

So it’s like picking between two negatives here in my eyes. Either we disable branch policies and hope that everyone follows the protocol and doesn’t make mistakes. What we gain is a streamlined publishing workflow using lerna. Or we enable branch policies to gain control over them and have to manually bump versions for branches.

If anyone have been in the same situation using lerna and got any tips or workarounds to handle this let me know, because I’ve been scratching my head around this for the couple of days on the best way to go forth with this.

8 Likes

@phips28 if it helps, we ended up doing this. We ignore the push to master if the only files touched were package.json and CHANGELOG.md. Feels a bit kludgy but it did work and prevented infinite jobs. It would depend on the scope of the changes your plugin is causing, you’d want it to cover every file the commit could change. We assume if a human is updating package.json they will have a new package.lock from an npm i.

name: Bump version
on:  
push:  
branches:  
 - master
paths-ignore:  
 - 'package.json'  
- 'CHANGELOG.md'  
jobs:  
build:  
runs-on: ubuntu-latest

steps:  
 - uses: actions/checkout@v1
with:  
token: ${{ secrets.GITHUB_TOKEN_ACTION }}
- name: Bump version and push tag
uses: team/conventional-changelog-action@master
with:  
github-token: ${{ secrets.GITHUB_TOKEN_ACTION }}
git-message: 'chore(release): {version}'  
preset: 'angular'  
tag-prefix: ''  
output-file: 'CHANGELOG.md'  
2 Likes

One way to avoid putting package.json on the paths-ignore list:

use “!contains(github.event.head_commit.author.name, ‘GITHUBACTION’)”

e.g.

on:
  push:
    branches:
      - master
jobs:
  publish-gpr:
    if: "!contains(github.event.head_commit.author.name, 'GITHUBACTION')"
    runs-on: ubuntu-latest
    steps:
      ....
      - name: Set up git for commits
        run: |
          git config user.name "GITHUBACTION"
        timeout-minutes: 1
      - name: Push
        run: git push --follow-tags --no-verify origin HEAD:master
        timeout-minutes: 1
  empty-job:
    # if no jobs run, github action considers it a test failure -- which seems like a bug
    # this makes it so the top-level if statement for the job does not give status failure.
    runs-on: ubuntu-latest
    if: success()
    steps:
      - name: Meep
        run: |
          echo "This job will always succeed. If no jobs run, we still want the workflow to give status success."
2 Likes

is it possible to whitelist the github actions app in the **“Restrict who can push to matching branches”** section?

> Specify people, teams or apps allowed to push to matching branches. Required status checks will still prevent these people, teams and apps from merging if the checks fail.

If the actions app showed up in this list, this would help.

5 Likes

Did you try with --amend argument?

1 Like

I tried this and I still got the errors:

remote: error: GH006: Protected branch update failed for refs/heads/master.

remote: error: At least 1 approving review is required by reviewers with write access.

2 Likes