ad-m / github-push-action

GitHub actions to push back to repository eg. updated code
MIT License
1.18k stars 226 forks source link

remote rejected: cannot lock ref #61

Open kenorb opened 4 years ago

kenorb commented 4 years ago

The following error can happen at random especially for jobs in parallel (matrix). This could be related to race condition.

Run ad-m/github-push-action@master
  with:
    branch: refs/heads/optimize-strategy-ac
    github_token: ***
    directory: .
Started: bash /home/runner/work/_actions/ad-m/github-push-action/master/start.sh
Push to branch refs/heads/optimize-strategy-ac
To https://github.com/EA31337/EA31337-Lite-optimization-tests.git
 ! [remote rejected] HEAD -> optimize-strategy-ac (cannot lock ref 'refs/heads/optimize-strategy-ac': is at 98bf7e54a615d7e23cbcf8688d22c4099a1d2240 but expected 00da1b358846ae9a8ffa71b34eb1e330e3a37e3d)
error: failed to push some refs to 'https://github.com/EA31337/EA31337-Lite-optimization-tests.git'
Error: Invalid status code: 1
    at ChildProcess.<anonymous> (/home/runner/work/_actions/ad-m/github-push-action/master/start.js:9:19)
    at ChildProcess.emit (events.js:210:5)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5) {
  code: 1
}
Error: Invalid status code: 1
    at ChildProcess.<anonymous> (/home/runner/work/_actions/ad-m/github-push-action/master/start.js:9:19)
    at ChildProcess.emit (events.js:210:5)
    at maybeClose (internal/child_process.js:1021:16)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:283:5)

My config:

    steps:
      - uses: actions/checkout@v2
        with:
          persist-credentials: false
          # Otherwise, you will failed to push refs to dest repo.
          fetch-depth: 0
      - run: docker-compose run $DCA ${{ matrix.test }}
      - name: Commit files
        run: |
          git config --local core.autocrlf false
          git config --local user.email "${{ github.actor }}@users.noreply.github.com"
          git config --local user.name "${{ github.actor }}"
          git pull origin ${{ github.ref }} --autostash --rebase -Xours
          git add --renormalize .
          git status
          git commit -am "${{ github.workflow }}"
      - name: Git Diff
        run: NO_PAGER=1 git --no-pager diff HEAD^
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          branch: ${{ github.ref }}
          github_token: ${{ secrets.GITHUB_TOKEN }}

I don't want to force push (because obviously something changed upstream right after the pull), so maybe integrating pull feature as well right before push could be useful and do some customizable number of retries?

One workaround is to move push action outside of matrix jobs by uploading changed from from matrix job, then downloading artifacts (e.g. patches) and push the changes at the final stage.

kenorb commented 4 years ago

Workaround

As for the workaround, I've re-pulled and pushed again after the job failure.

      - name: Commit files
        run: |
          git config --local core.autocrlf false
          git config --local user.email "${{ github.actor }}@users.noreply.github.com"
          git config --local user.name "${{ github.actor }}"
          git add . && git add --renormalize .
          git pull origin ${{ github.ref }} --autostash --rebase -X ours
          git commit --allow-empty -am "${{ github.workflow }}"
          NO_PAGER=1 git --no-pager diff HEAD^
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          branch: ${{ github.ref }}
          github_token: ${{ secrets.GITHUB_TOKEN }}
      - name: Re-pull on failure
        if: ${{ failure() }}
        run: git pull origin ${{ github.ref }} --autostash --rebase -X ours
      - name: Re-push on failure
        if: ${{ failure() }}
        uses: ad-m/github-push-action@master
        with:
          branch: ${{ github.ref }}
          force: true
          github_token: ${{ secrets.GITHUB_TOKEN }}

But would be great to add some pull feature and re-try system to this action to try again, in case the remote HEAD changed.

lucharo commented 3 years ago

Hey @kenorb this really helped, thank you!

gergokee commented 4 months ago

i have the same issue, is there any planned fix for this ?

ZPascal commented 4 months ago

@gergokee I think, the issue is already solved by using the --atomic option by default.

gergokee commented 2 months ago

@ZPascal i read about atomic but that is not going to solve this issue. Atomic push is a possiblity to push to different branches as the same time, however this does not directly solve the issue of concurrent asynchronous pushes to the same reference (e.g., the same branch) where one push occurs slightly after the other. The atomic push ensures that either all or none of the specified references are updated in a single operation, maintaining consistency across multiple branches or tags being pushed simultaneously. However, it does not manage or resolve conflicts arising from concurrent pushes to the same reference. (We've solved it with some "ugly" workarounds upon catching push error...)