stefanzweifel / git-auto-commit-action

Automatically commit and push changed files back to GitHub with this GitHub Action for the 80% use case.
MIT License
2.03k stars 229 forks source link

Not working on a protected branch #87

Closed brianjmurrell closed 4 years ago

brianjmurrell commented 4 years ago

Version of the Action v4.4.0

Describe the bug Not working with a protected branch despite the project enabling force-pushes.

Screenshots image

Used Workflow https://github.com/daos-stack/pipeline-lib/blob/master/.github/workflows/update_pipeline_lib_branch.yml

The failed action: https://github.com/daos-stack/pipeline-lib/runs/900246701?check_suite_focus=true

I was able to push from the CLI:

$ git push origin HEAD:master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 380 bytes | 380.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
To github.com:daos-stack/pipeline-lib.git
   a1bf9ea..fb2658d  HEAD -> master
stefanzweifel commented 4 years ago

Another user recently mentioned this problem in an already closed issue (https://github.com/stefanzweifel/git-auto-commit-action/issues/71#issuecomment-660470689).

I didn't have the time yet to test it myself, but could you try creating a Personal Access Token (PAT) and use that token instead of the normal secrets.GITHUB_TOKEN?

https://github.com/stefanzweifel/git-auto-commit-action#commits-of-this-action-do-not-trigger-new-workflow-runs

Will update the README accordingly when we've found the solution that works for everybody.

localheinz commented 4 years ago

@brianjmurrell @stefanzweifel

Works fine with a personal access token!

👌

stefanzweifel commented 4 years ago

@localheinz Thanks for the update! Will rewrite the section about protected branches in the README soon.

brianjmurrell commented 4 years ago

How does a Personal Access Token work for teams/organisations where dozens of people work on the same repo?

stefanzweifel commented 4 years ago

@brianjmurrell I guess your question is: "How can I create a Personal Access Token for an org?"

That's currently not possible. I think this SO answer sums it up pretty good:

That's not possible currently, you can only create tokens for user accounts since user accounts have permissions associated with them (organizations don't). So, you'd need to create a token with an account which has access to the repository in question and give that to Travis. You can also create a machine account for that purpose.

https://stackoverflow.com/a/31160721/3863449

If you're in an org and don't want to create a PAT from your own personal accounts, the recommended way is to create a machine/bot account, and create a PAT from that machine account.

localheinz commented 4 years ago

@brianjmurrell

As @stefanzweifel said: I have created @ergebnis-bot and use its personal access token in repositories I control.

Similarly, in other organizations we have also created bot accounts. Secrets can be easily shared using organization secrets.

stefanzweifel commented 4 years ago

Just a quick update: I've updated the README with a note on protected branches. In addition to the --force-option which has to be passed to the Action, I've also added a note on the need of a PAT.

https://github.com/stefanzweifel/git-auto-commit-action#push-to-protected-branches

I'm closing this issue for now. If you think your issue is not resolved or have any other question, feel free to reopen or create a new issue.

brianjmurrell commented 4 years ago

It seems like opening quite a wide gate to allow force pushes to protected branches. We have that disabled specifically to prevent accidental pushes to master where a user meant to push to their own PR/branch. Is there no finer grained control over this than all-or-none?

stefanzweifel commented 4 years ago

@brianjmurrell It's definitely not the most beautiful solution for this problem, however, this Action just uses the git-binary to do all the action. As far as I know, there are no API endpoints which would accomplish the same which would make this whole "push to protected branch"-thing safer.

And I totally understand that your org has enabled protected branches and disabled the force-push option. (The feature exists for that reason 😄 )

However, if Actions would be excluded from these rules and Actions could push to protected branches, they could create the same havoc as a user would be able to 🤷

dimitarspassov commented 4 years ago

I have an issue, which I feel belongs to this discussion.

There is a "Commits of this Action do not trigger new Workflow runs" in the README, which states: The resulting commit will not trigger another GitHub Actions Workflow run.. And according to the GitHub limitations, using a personal access token (PAT) changes this behaviour.

My goal is to create a workflow in an organization repository, which has a step that commits and pushes changes through this action. The branch is protected so I have do force push and to use a bot with PAT. But using PAT causes recursive workflow runs. Is there a way to fix this?

I guess my workflow could need rethinking, but if this is a common scenario (as it seems to me), then using this action with PAT will always cause recursive workflow runs.

stefanzweifel commented 4 years ago

@dimitarspassov Using this Action with a PAT shouldn't cause recursive workflows runs automatically. It all depends on what your workflow is changing.

For example, if your workflow is storing the current time and date in a text file (date > current-date.txt), and you commit and push the file to the remote repository with a PAT, it will definitely cause endless recursive workflow runs.

If your workflow does something similar and everytime it runs would commit something, I think you should be able to prevent the endless workflows runs by using if conditions on the job. (Docs about if conditions)

The above example could look like this: The workflow clones the repo, writes the current time in a txt-file and commits the changes pack to the repo by using a PAT. Howerver, the job itself is protected by a if-clause and will only run, if the user who started the workflow run is not org-bot.

name: My Workflow

on: push

jobs:
  my-workflow:

    # ↓ This condition is important
    if: github.actor != 'org-bot' 

    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
      with:
        token: ${{ secrets.PAT }}
        ref: ${{ github.head_ref }}

    # ...

    run: date > current-date.txt

    - uses: stefanzweifel/git-auto-commit-action@v4
      with:
        commit_message: My Commit Message
        branch: ${{ github.head_ref }}
        commit_user_name: org-bot

But please note: I'm not 100% sure this actually works. I'm not sure if commit_user_name and github.actor are the same values or if you would have to use the actual GitHub username of your bot account here.

dimitarspassov commented 4 years ago

Thank you @stefanzweifel for the quick answer.

I've just finished testing and it seems that the if-conditions are the way to go here.

Unfortunately, I have a workflow job, that is required as part of the branch protection. Even with force pushes allowed and using the bot's PAT, I get an error:

remote: error: GH006: Protected branch update failed for refs/heads/master.        
remote: error: Required status check "build-and-test" is expected.   

I suppose what I'm trying to achieve may not be possible, but is there still a way to work this out?

stefanzweifel commented 4 years ago

@dimitarspassov By the name of the check ("build-and-test") I assume that a push could only happen if your project is successfully built and tested.

The Action would therefore have to be triggered when build-and-test finishes. Maybe this can be achieved with the workflow_dispatch-event.

However, this makes things just way too complicated.

dimitarspassov commented 4 years ago

@stefanzweifel Yep, I agree with your conclusion. I will have to reconsider the general approach. Thanks for the quick answer again!

antonmos commented 3 years ago

@brianjmurrell It's definitely not the most beautiful solution for this problem, however, this Action just uses the git-binary to do all the action. As far as I know, there are no API endpoints which would accomplish the same which would make this whole "push to protected branch"-thing safer.

And I totally understand that your org has enabled protected branches and disabled the force-push option. (The feature exists for that reason 😄 )

However, if Actions would be excluded from these rules and Actions could push to protected branches, they could create the same havoc as a user would be able to 🤷

We are using develop-on-master workflow, so force pushing to master could clobber some actual commits.

@stefanzweifel could you please help me understand why force-pushes are necessary at all?

cc @opp-svega

stefanzweifel commented 3 years ago

@antonmos

could you please help me understand why force-pushes are necessary at all?

I assume that your master branch is protected, right?

By default, nobody can push to a protected branch: Not you from your command line or any other actor (like git-auto-commit in a GitHub Actions Workflow run).

To circumvent this and push through the branch protection, you can use git force pushes. In your terminal you would use git push --force, in git-auto-commit you would use the push_options: '--force' option. (Note that you need to allow force pushes to protected branches in your repo).

As mentioned before, git-auto-commit is just a wrapper around the git binary. So there is no other way to change a file in a workflow and push it to a protected without using force-pushes.

If you don't want to use force-pushes, and master is your only protected branch, you would have to rewrite your workflow that uses git-auto-commit so that it never runs on master. For example it would only listen to the pull_request-event and push your changes in a PR.

More on force pushes on protected branches:

antonmos commented 3 years ago

By default, nobody can push to a protected branch: Not you from your command line or any other actor (like git-auto-commit in a GitHub Actions Workflow run)

I dont believe this is accurate. Protected branches have a setting for "Restrict who can push to matching branches" and "Include administrators" which are off by default. If they are off, then Administrators can push to a protected branch without meeting configured restrictions (e.g. PR reviews) (i just tested this). Note that this is different from force pushing, which is disable for all protected branches unless Allow force pushes is enabled (it's disabled by default).

My goal is to prevent force-pushing to master because it can break history/auditing/drop commits, but it is up to the individual to determine if PRs is need for a give change, i.e. there is no need to PR if you are fixing formatting in a README or if you are doing work in a pair. That said, all the actions should run regardless of whether the work is coming via PR or not.

So, if i am not mistaken, there is no need to force push if you are just trying to get an additive commit to a protected branch.

What is not clear to me is why we needed to specify push_options: '--force' if git-auto-commit-action is only adding new commits, while i am able to push to protected master branch directly without using --force

stefanzweifel commented 3 years ago

@antonmos Agree. "Nobody" wasn't accurate. (I honestly haven't used protected branchens in a long while and wasn't aware that there was an "Include Administrators" option).

And I totally get what you want to achieve here. force-pushing is always a risky move.

What is not clear to me is why we needed to specify push_options: '--force' if git-auto-commit-action is only adding new commits, while i am able to push to protected master branch directly without using --force

When your Workflow is run, and the git-auto-commit Action is executed, the git push call is not run in the name of the GitHub user antonmos but rather as a "GitHub Actions system user". (See the docs about Authentication in a Workflow)

Let's imagine that your repository has protected branches setup like this:

Screenshot 2021-04-20 at 08 32 05

Now you make a commit from you terminal and push it to master. Because you are an administrator, it goes through. Now a Workflow is triggered which will update/format README.md. git-auto-commit detects the change, creates a commit and tries to push it to GitHub. It will fail with the following error message.

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.        
To https://github.com/stefanzweifel/repo
  ! [remote rejected] master -> master (protected branch hook declined)
error: failed to push some refs to 'https://github.com/stefanzweifel/repo'
Error: Invalid status code: 1

As the Workflow is run as the "GitHub Actions user" it's not detected as an administrator of the repo and the protected branches rules apply.

To circumvent this, you have to create a Personal Access Token. With this token, the git push command will be executed in your name (as an administrator). the protected branches rules shouldn't apply then.

Does this clarify your questions? (Also feel free to submit a PR to the README/docs, if you think the part about protected branches can be made clearer)


The line about needing push_options: --force might be out of date. I will do some testing over the next few days and update the README accordingly.

antonmos commented 3 years ago

Thank you for your reply! We set it up with a PAT and made that user Admin in this repo and it worked without push_options: --force

zmilonas commented 2 years ago

Thank you @stefanzweifel.

Could you please clarify which scopes are needed for the Personal Access Token to work? The full list with descriptions is here: https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps

I'm guessing something like repo:status but maybe full repo is needed?

Additionally GitHub just released a "new version" of Personal Access Tokens - https://github.blog/2022-10-18-introducing-fine-grained-personal-access-tokens-for-github/ - do you think it's possible to use those instead? Will it work without any code change in the action?

Thanks in advance :)

edit: if you will be able to assist me understanding these i'd be happy to contribute - either to README to clarify or to code if some code change would be needed.

stefanzweifel commented 2 years ago

@zmilonas

Could you please clarify which scopes are needed for the Personal Access Token to work? The full list with descriptions is here: https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps I'm guessing something like repo:status but maybe full repo is needed?

Last time I checked, the token needs repo and workflow access. We've documented this in the README here:

If you create a personal access token, apply the repo and workflow scopes.

Additionally GitHub just released a "new version" of Personal Access Tokens - https://github.blog/2022-10-18-introducing-fine-grained-personal-access-tokens-for-github/ - do you think it's possible to use those instead? Will it work without any code change in the action?

I think that should work. From the announcement post I could see that the GraphQL API is not yet supported. git-auto-commit doesn't use any API directly. It just does a git push. Authentication happens through actions/checkout.

Regarding the scopes from the new fine grained PATs, I think you would need "Read and Wrtie" for "Actions" and "Contents". But I haven't tested this yet.

Feel free to give this all a try. If you think the docs in the README needs to be updated, feel free to create a pull request.

bakayolo commented 1 year ago

FYI, in order for this to work I had to do

if: github.event.head_commit.author.username != 'tag-bot'

github.actor is always ... me :)

air3ijai commented 8 months ago

We may use GitHub Apps - Consistently allow GitHub Apps as exceptions to branch protection rules.

Authenticating as a GitHub App in a GitHub Actions workflow.

- name: Create Token
  id: create_token
  uses: tibdex/github-app-token@v2
  with:
    app_id: ${{ secrets.APP_ID }}
    private_key: ${{ secrets.APP_PRIVATE_KEY }}

- uses: actions/checkout@v4
  with:
    token: ${{ steps.create_token.outputs.token }}