Checkout: Checking out wrong commit?

Created on 11 Jul 2020  路  23Comments  路  Source: actions/checkout

I just introduced a failing test into the main branch of a project; the failing tests (introduced in the commit triggering the build) appeared not to have run in the PR build.

When I look at the actions/checkout output, I am surprised by what I see.

Specifically, the build is running on commit 2dca06e -- however, actions/checkout appears to be merging the prior commit -- c0121d5 -- (without the tests) into the project's main branch.

Is this expected?

Screen Shot 2020-07-10 at 9 55 09 PM

The project's checkout configuration is completely vanilla: https://github.com/golangci/golangci-lint/blob/master/.github/workflows/pr.yml#L46

Most helpful comment

This looks quite serious (allows to sneak not validated code as valid)

@ericsciple is there any specific timeline for this?

All 23 comments

This is similar to #237

@andymckay fyi

This looks quite serious (allows to sneak not validated code as valid)

@ericsciple is there any specific timeline for this?

I was able to use the following work-around:

[... trimmed ...]
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          # Check out pull request's HEAD commit instead of the merge commit to
          # work-around an issue where wrong a commit is being checked out.
          # For more details, see:
          # https://github.com/actions/checkout/issues/299.
          ref: ${{ github.event.pull_request.head.sha }}
[... trimmed ...]

This affects us, we found this documentation: https://developer.github.com/v3/pulls/#response-1. I searched code in this repository for mergeable and merge_commit_sha, but couldn't find anything. Feels like it's related.

I'm having the same problem in this pull request run: https://github.com/ssantichaivekin/empress/runs/900765234

Screen Shot 2020-07-24 at 11 34 46 AM

It seems that this can be fixed by making a commit that is up to date with the current origin/master. See https://github.com/ssantichaivekin/empress/issues/184

We just ran into what I think is another instance of this issue in https://github.com/DFHack/scripts/runs/910104637?check_suite_focus=true#step:4:375
This check ran on https://github.com/DFHack/scripts/commit/5177a127b32631fbcedc4b0e93e0c5c05a124388, but ended up running on a merge between master and the previous commit on that branch (https://github.com/DFHack/scripts/commit/1ec3d9b1a14c6b39b1bf0b907108a3e313eed955, as seen in the actions/checkout output), which produced a lot of irrelevant errors that the newer commit was intended to address. This issue repeated itself when we re-ran the check, so it appears to be reproducible in this case, but I'm not seeing an obvious reason why - the newer commit in that PR was pushed well after the checks run on the older commit failed, and we haven't seen this in other PRs. Update: we've seen this in at least two PRs so far.

About 2 minutes after re-running the check reproduced the issue, I ran this locally, which resulted in fetching a correct merge, so I'm pretty sure the issue is on the action's end:

$ git fetch origin refs/pull/159/merge
$ git show FETCH_HEAD 
commit 5be19d326c828ac38ce307eb6db068e691504a7e
Merge: ad67c79 5177a12

Seeing this issue as well with the v2 of checkout.
Timeline

  • Committed and push code to a branch that failed a test *hashA
  • Committed code that fixed the test however didn't push *hashB
  • Merged in main then pushed *hashC

The commit *hashC still checked out *hashA code to run tests on.

+1 I had the same issue with this run and noticed because the commit was introducing a modification to the workflow YAML file that was not honored. A few of our contributors reported the same too, for instance in this PR https://github.com/spack/spack/pull/17755

If it matters, in my case the issue was with a force pushed commit on a PR where tests on previous commits were still running.

@hashtagchris should i set you as the assignee?

@ericsciple which issue should we follow this one (#299) or #237?

I believe this is a dupe of #237, please see my comment here: https://github.com/actions/checkout/issues/237#issuecomment-667158637

This seems to happen for me still, my action is checking out the wrong branch, static analysis is complaining about code which it's not supposed to be testing. :thinking:

@dkarlovi can you share the repository, commit and other info with us? If you can't do that publicly, please file a support issue here https://support.github.com/contact and link over to this issue.

@andymckay I was introducing CI in one branch and it started complaining about code from another, but they were mutex.

I had a couple of branches running at that point so don't want to send it in and it turns out it was PEBKAC so I don't waste your time. If it happens again, I'll be sure to let you know. Thanks.

I had the same problem in the pull-request.

Fix with:

- uses: actions/checkout@v2
  with:
    ref: ${{ github.event.pull_request.head.sha }}

I believe I encountered this issue on Monday morning. I had thought it was due to multiple parallel workflows, but a Partner has indicated that this is unlikely to be the case.

Please see my incident description in this thread.

I had the same problem in the pull-request.

Fix with:

- uses: actions/checkout@v2
  with:
    ref: ${{ github.event.pull_request.head.sha }}

Beware: this checks out the current head of the branch, whereas by
default the action checks out the merge commit. By using this
workaround, you will no longer catch conflicting changes in the base
branch.

Is there a way to check out the correct merge commit without race
conditions? There鈥檚 the [merge_commit_sha] field, but the docs
indicate that that may be null if mergeability has not yet been
computed.

@wchargin
Was you running on pull_request_target ? The ref and sha is different to pull_request

You can wait for the merge_commit_sha

- name: wait for mergeable
        id: wait-for-mergeable
        uses: tonyhallett/ReleaseManager/wait_for_mergeable@main
        env:
            GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: checkout
        uses: actions/checkout@v2
        with:
            ref: ${{ steps.wait-for-mergeable.outputs.mergeCommitSha}}

I have not released my actions from ReleaseManager yet so here is the typescript code.

import * as core from '@actions/core'
import * as github from '@actions/github'
import {PullRequest} from '@octokit/webhooks-definitions/schema'
import {getProcessEnv} from './helpers/getProcessEnv'
import {getNumberInput} from './helpers/inputHelpers'

async function run(): Promise<void> {
  try {
    const initialWait = getNumberInput('initialWait')
    const waitTime = getNumberInput('wait')
    const maxWait = getNumberInput('timeout')

    const pullRequest = github.context.payload.pull_request as PullRequest
    const pullNumber = pullRequest.number

    const githubToken = getProcessEnv('GITHUB_TOKEN')
    if (!githubToken) {
      core.error('no token')
    } else {
      let timedOut = false
      let mergeable: boolean | null = null
      let mergeableState: string | undefined
      let mergeCommitSha: string | null = null
      const octokit = github.getOctokit(githubToken)

      await wait(initialWait)
      const start = new Date().getTime()
      // eslint-disable-next-line no-constant-condition
      while (true) {
        const response = await octokit.pulls.get({
          ...github.context.repo,
          pull_number: pullNumber
        })
        mergeable = response.data.mergeable
        if (mergeable != null) {
          mergeCommitSha = response.data.merge_commit_sha
          mergeableState = response.data.mergeable_state
          break
        }
        await wait(waitTime)
        const now = new Date().getTime()
        if (now - start > maxWait) {
          timedOut = true
          break
        }
      }

      core.setOutput('timedOut', timedOut)
      core.setOutput('mergeable', mergeable)
      core.setOutput('mergeableState', mergeableState)
      core.setOutput('mergeCommitSha', mergeCommitSha)
    }
  } catch (e) {
    core.error(e)
  }
}

const wait = async (interval: number): Promise<void> => {
  return new Promise<void>(resolve => {
    setTimeout(() => {
      resolve()
    }, interval)
  })
}

run()

@tonyhallett: This is also incorrect, because it fetches the _most
recent_ merge commit rather than the merge commit for the commit being
tested. Consider the following sequence:

  1. Push commit A to PR 123.
  2. CI queued on commit A. Merge commit not yet computed.
  3. Push commit B to PR 123 (same PR).
  4. GitHub computes the new merge commit to merge B into master.
  5. CI run for commit A unqueues and starts running.

If at point (5) you fetch the _current_ merge commit for PR 123, you
will be running on the code in commit B, not commit A. This would mean
that when you click the CI status indicator on commit A, it actually
shows you tests that ran at a different commit, which is obviously
unacceptable.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hannesa2 picture hannesa2  路  5Comments

bnb picture bnb  路  3Comments

bk2204 picture bk2204  路  3Comments

grst picture grst  路  3Comments

jcharnley picture jcharnley  路  4Comments