dependabot / dependabot-core

🤖 Dependabot's core logic for creating update PRs.
https://docs.github.com/en/code-security/dependabot
MIT License
4.73k stars 1.02k forks source link

Dependabot creating PR too soon after last PR auto-merges, resulting in on out-of-date with base branch #10969

Open devanubis opened 5 days ago

devanubis commented 5 days ago

Is there an existing issue for this?

Package ecosystem

pip

Package manager version

poetry

Language version

python 3.11

Manifest location and content before the Dependabot update

No response

dependabot.yml content

version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    reviewers:
      - "scene-connect/dependabot-reviewers"
    schedule:
      day: "monday"
      interval: "weekly"
      time: "08:00"
      timezone: "Europe/London"
    open-pull-requests-limit: 1
  - package-ecosystem: "pip"
    allow:
      - dependency-type: all
    directory: "/"
    reviewers:
      - "scene-connect/dependabot-reviewers"
    schedule:
      interval: "daily"
      time: "08:00"
      timezone: "Europe/London"
    open-pull-requests-limit: 1
    insecure-external-code-execution: allow # apparently pip executes code see https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#insecure-external-code-execution

Updated dependency

No response

What you expected to see, versus what you actually saw

Similar to #4031 and #5234.

We have a github action which marks dependabot PRs to auto-merge, if they pass our CI workflow.

name: Dependabot auto-merge
on:
  workflow_call:
    inputs:
      merge_major_versions:
        default: false
        description: Auto merge on major version changes
        required: false
        type: boolean

permissions:
  pull-requests: write
  contents: write

jobs:
  dependabot-auto-merge:
    runs-on: ubuntu-22.04
    if: ${{ github.actor == 'dependabot[bot]' }}
    env:
      PR_URL: ${{ github.event.pull_request.html_url }}
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - name: Dependabot metadata
        id: metadata
        uses: dependabot/fetch-metadata@v2.2.0
        with:
          github-token: "${{ secrets.GITHUB_TOKEN }}"
      - name: Approve PR
        run: gh pr review --approve "$PR_URL"
      - name: Merge PR
        if: ${{ inputs.merge_major_versions || steps.metadata.outputs.update-type != 'version-update:semver-major' }}
        run: gh pr merge --auto --squash "$PR_URL"

When the first dependabot PR of the day successfully auto-merges, dependabot appears to create the second PR almost instantly, and that second PR gets based on HEAD^ missing the commit from the first dependabot PR, which just auto-merged.

That means we have to go around our multiple repos and @ dependabot rebase each of them to get them moving again,

This all pretty much defeats the point of auto-merging our dependabot PRs in the first place, and also doubles up on CI workflow runs. (I've actually just added a job to fail and halt our CI if not up to date with the base branch, just to save us wasting the github actions minutes.

It also means that typically we only get 2 dependabot PRs per repository each day. We might be able to avoid that by changing our schedule.time and reacting quickly, but that also defeats the point of having dependabot do anything for us, we might as well have a daily task for someone to run poetry lock every morning and just test all our updates in one PR...


We deliberately set open-pull-requests-limit: 1 to avoid having to have multiple PRs which we needed to repeatedly rebase and run our CI workflow. (Yes that could possibly also be avoided by not requiring PRs be up to date with the base branch, but we can't disable that requirement just for dependabot nor really do I want to, we do occasionally run into dependency clashes particularly with type-checking).

Native package manager behavior

No response

Images of the diff or a link to the PR, issue, or logs

No response

Smallest manifest that reproduces the issue

I'll see if I can set up a bare public repo with some generic dependencies and make dependabot reproduce this behaviour.

devanubis commented 5 days ago

OK I think I've reproduced this fairly simply.

I didn't get out auto-merge workflow working, but it doesn't matter.

When I manually approved the first dependabot PR (devanubis/dependabot-race-condition#1) and merged it (@ dependabot squash and merge) dependabot almost instantly created the next PR devanubis/dependabot-race-condition#2 from the main branch at HEAD^ as if PR 1 had not yet merged.

The timestamps on the commits show that it did happen in the expected order:

So it's not like the 2nd PR's branch is being pre-created ahead of the 1st PR even merging (although it may have pre checked-out the main branch ?) and it's not like 14 seconds isn't enough time for that commit to actually hit the github main branch...

So I'm fairly sure now that nothing in our private repo workflows/actions is causing this behaviour and that using dependabot is hitting some sort of race condition with itself when open-pull-requests-limit: 1.