Why does `merge_commit_sha` change during action run?

What could cause the merge_commit_sha on a PR to change during an action run?

I am seeing it change sometimes during a run even when the base branch and head of the base branch isn’t changing. The head of the PR branch isn’t changing either. I’m only expecting it to change if GitHub needs to make a new test merge commit, and I thought it would only need to do that if the base branch changed or the head commit on the PR branch changed?

Is this a bug?

E.g. on this action run the merge_commit_sha in the action context was cd2db2bd06d39c54f78109d138abb8d68ad175d4, but later the one that comes back from the API was c59639de0faffb38973b54cab24520567b5bcff5. Both commits actually exist and look identical. The PR should be up to date with the base branch because the ‘update branch’ button is not showing.

Rerunning the job when it fails like this usually fixes it.

Thanks

Hi @tjenkinson,

Glad to see you in Github Community Forum!

It’s not a bug.

When you can create a pull request, github will execute workflow based on a fake merge branch: refs/pull/:prNumber/merge, the merge_commit_sha doesn’t exist on base or head branch, but points to that surrogate merge commit, and there is a mergeable key to show the status of the test commit.

The value of the mergeable attribute can be true , false , or null . If the value is null , then GitHub has started a background job to compute the mergeability. After giving the job time to complete, resubmit the request. When the job finishes, you will see a non- null value for the mergeable attribute in the response. If mergeable is true , then merge_commit_sha will be the SHA of the test merge commit(github.sha).

In the workflow github context, you will see the the mergeable value is null:
image

However in rest api result, it’s true.
image

Actually ‘github.sha’ stands for the actual merge commit.

Retrigger the workflow(eg: new commit), the merge_commit_sha in github context will get the value from last run.

Please refer to the links for more detials:

Thanks

Hi @weide-zhou. Thanks for the quick response!

I’m confused how it works most of the time and fails the rest.

When it worked could this be that the background job finished before the action was triggered?

So merge_commit_sha first points to a surrogate commit (mergeable === null), and then it points to the test commit shortly after when (mergeable === true)?

I read the docs before but they don’t mention the surrogate commit when mergeable === null. It just says

Before merging a pull request, the merge_commit_sha attribute holds the SHA of the test merge commit

so I was expecting a change to that value to mean that the PR had been updated since the action started. Might be good to add the info about the surrogate commit to the docs :slight_smile:

Thanks

How can I detect if the base branch has changed?

I can pass the head commit sha on the merge call to ensure the head commit hasn’t changed since the action started, but I’m not sure how I could detect if the base branch has changed before merging?

Thanks

Hi @tjenkinson,

Thanks for your reply!

If your operation will affect ‘refs/pull/prnumber/merge’(eg: a new commit on head branch), the ‘mergeable’ key will be null in the workflow context.
If your operation will not affect the fake merge branch(eg: add label, edit the pr to trigger workflow), the ‘mergeable’ key could be true and the ‘merge_commit_sha’ is same with api result.
You can confirm ‘mergeable’ key before you get the value of ‘merge_commit_sha’.

After the pull request is created, you cannot get the base branch change from the context.
You can checkout the base branch, and get the head commit of base branch:

      - name: checkout
        uses: actions/checkout@v2
        with:
          ref: ${{ github.base_ref }}
      - run: |
          git rev-parse HEAD

compare the value with ${{github.event.pull_request.base.sha}} from workflow context. If they are same, the base branch is not changed.

Thanks

Thanks. So it sounds like it’s not possible with the api to guarantee you are merging the same thing you validated in the action?

I think the merge api call would need to take the base branch head commit in addition to the pr branch head commit id. Could this feature be added?

E.g. there’s nothing right now that would protect against the base branch in the pr changing after the merge api call is made and the merge occurs?

Hi @tjenkinson,

If the workflow is triggered, it will get the base branch latest, if your action will auto merge the PR, it will complete the merge.

If base branch is changed, it will cause conflict for pull request and you cannot complete merge, you need to reslove it maunally.

Thanks

Hi @weide-zhou

I think the merge would work though if the base branch changed and it could be merged without conflicts (and ‘require branch to be up to date before merging’ turned off)?

Hi @tjenkinson,

Yes, it is.

If you enabled 'require branch to be up to date before merging’ in branch protection rule, change the base branch, it will report base branch is out-of-date, cannot merge pr (except for admin).

If you turn it off, and only update base branch, no conflict created in PR, you can still merge the PR.

Thanks

If you turn it off, and only update base branch, no conflict created in PR, you can still merge the PR.

Exactly and this is the problem.

Here’s the scenario:

  1. 'require branch to be up to date before merging’ is turned off
  2. PR created with base branch-a and pr branch-b
  3. action runs and checks that the result of merging branch-b into branch-a is ok
  4. action sends api request to merge PR
  5. base branch changed from branch-a to branch-c (whilst merge request in flight)
  6. Merge completes and branch-b is merged into branch-c

The action checked everything was ok for branch-b going into branch-a, but this is not what happened.

The merge api lets us set the head commit on the PR to ensure the merge fails if a new commit is pushed. It doesn’t appear there is any way to handle this case though?

Maybe I should create a new post for this as it’s gone a bit off topic from the original question.

Hi @tjenkinson,

This is mostly like how github deal with pull request but not related to github aciton, it’s recommended to raise a new ticket in this topic for confirmation.

Thanks