jycouet / VSTSExtensions

MIT License
30 stars 11 forks source link

Ability to run renovatebot multiple times when it has successfully merged a PR #41

Closed elwynelwyn closed 3 years ago

elwynelwyn commented 3 years ago

Is your feature request related to a problem? Please describe.

Now that RenovateBot supports automerge on PRs for Azure ( https://docs.renovatebot.com/configuration-options/#automerge ) it has uncovered an issue with running renovate via an azure pipeline - once renovatebot automerges a PR it stops the rest of the run and bails out. (this is by design, since after merging, it's baseBranch has changed).

Describe the solution you'd like Perhaps the RenovateMe task could look at the log output from RenovateBot, and if it detects RenovateBot has exited due to a successful automerge, re-run renovate.

Describe alternatives you've considered My current workaround is to just copy paste the RenovateMe task inside the pipeline a bunch of times. Then our pipeline runs (once in the middle of the night) and runs renovate over and over. If there are multiple PRs to merge, it will work through them. But it's a crappy solution since it results in a bunch of unnecessary work. And if there are more PRs to merge than times I copy pasted the task, it will not merge them all.

Additional context

https://github.com/renovatebot/renovate/blob/771ef170d755179e18780f4700a3239679812fda/lib/workers/repository/process/write.ts#L46-L54

Log when automerge has succeeded:

2021-02-22T20:26:47.9064898Z  INFO: PR automerged (repository=MyOrg/MyRepo, branch=renovate/npm/my-update-branch)

(not sure how we could tell if this has happened if logLevel > debug? we'd get no output for that ^^ in that situation.) (perhaps we could PR to renovatebot to get something rel8iably logged out in this situation?)

Keen to know of any other ideas for how to resolve this situation!

jycouet commented 3 years ago

I never tried automerge, I'm curious to learn more.

You have this automerge for all matchDepTypes? Or just some? Each how long you run your pipeline today? Your pipeline is configured via a *.yml file?

To reproduce, I have to have 2 updates at the same time right?

elwynelwyn commented 3 years ago

We don't automerge major:

You have this automerge for all matchDepTypes? Or just some?

"packageRules": [
    {
        "updateTypes": [
            "minor",
            "patch",
            "pin",
            "digest"
        ],
        "automerge": true
    },
    {
        "updateTypes": [
            "major"
        ],
        "automerge": false,
        "reviewers": [
            // manually reviewed and approved
        ]
    },
    ...
}

Each how long you run your pipeline today?

The RenovateMe task in the pipeline usually takes 1 - 2 minutes, although I have seen it take as long as 5 minutes.

Your pipeline is configured via a *.yml file?

Our main renovate pipeline is not yml (yet... it's on my todo list!).

To reproduce, I have to have 2 updates at the same time right?

Yep, two dependency updates which match automerge=true, and all other requirements on those updates met (e.g. stabilityDays, build verification). Turn log level on to debug (or trace) and you should see renovate automerge the first, then exit.

jycouet commented 3 years ago

Sorry, I wanted to know you run RenovateMe each 2hours? 6hours? 24hours? Mondays? I'll look tomorrow

elwynelwyn commented 3 years ago

Ah, we run it on a schedule Monday - Friday at 2am

jycouet commented 3 years ago

I'm not sure it's a good idea to enforce a debug level & parse logs to find INFO: PR automerged. But I did it, with a max of 10 automerge.

I pushed also an example of RenovateMe.yaml if you want to have a look.

Let me know if it's working 🌝

elwynelwyn commented 3 years ago

Awesome, thanks very much for the update!

Will keep an eye on the pipeline over the next week or so and see how it goes :)

elwynelwyn commented 3 years ago

This seems to be working perfectly for us! We've got a big backlog of unmerged PRs due to the original issue, but the last few runs have been clearing through them. Run time on the RenovateMe task has been between 12 - 17 minutes, processing the max 10 PRs each time.

Thanks again!

jycouet commented 3 years ago

Thank you for the feedback, really appreciate it 👍. I think it could go faster if I don't npx renovate each time. But just npm i renovate -g and use the globale renovate at each run...

But let's do this another time ;)

elwynelwyn commented 3 years ago

ok, looks like I didn't actually read the logs close enough and spoke too soon :(

It is running 10 times correctly, however it's merging the first PR and the next 9 are failing. Since the first merge changes the target branch, all other PRs start building with the new changes in, and the subsequent PR merges fail as their build is still pending. I checked back to my previous pipeline where I had copy pasted the RenovateMe step a bunch of times, it seems to have been doing the same thing then as well.

Sorry about that!

jycouet commented 3 years ago

Hummm, so I don't have any magic to propose you here...

Maybe a quick solution is to run renovateMe each day? or each 2 hours? instead of once a week?

elwynelwyn commented 3 years ago

Yeah unfortunately I don't have a great solution :/

I ported our pipeline to YML to try out a few things, and the best I have got going so far is something like:

  - stage: RenovateBot
    displayName: RenovateBot
    jobs:
      - job: renovate_run_1
        pool:
          vmimage: 'ubuntu-latest'
        steps:
          - template: RenovateSteps.yml #contains steps for yarn install, runs renovate, etc
            parameters:
              runOfRuns: '1/10'
      - job: renovate_delay_1
        dependsOn: renovate_run_1
        pool: server
        steps:
          - task: Delay@1
            displayName: 'Delay by 15 minutes'
            inputs:
              delayForMinutes: 15

      - job: renovate_run_2
        dependsOn: renovate_delay_1
        pool:
          vmimage: 'ubuntu-latest'
        steps:
          - template: RenovateSteps.yml
            parameters:
                runOfRuns: '2/10'
      - job: renovate_delay_2
        dependsOn: renovate_run_2
        pool: server
        steps:
          - task: Delay@1
            displayName: 'Delay by 15 minutes'
            inputs:
              delayForMinutes: 15

    ....

15 minutes is a bit more than our build pipeline usually takes to run, so it lets a build queue and pass in between renovate runs. Using pool: server means the pipelines does not consume an agent while it waits.

Not super happy with it, (I couldn't even get the "Each" yml templating to work with chained dependsOn, so it's a big old block of copy pasta) but it's kind of working. It might have just been easier to tweak the schedule to run hourly a bunch of times over night, but our pipeline currently does more than just renovate so I'd need to split things up a bit more to make that work without re-running a bunch of non-renovate tasks over and over.

Hopefully someone has some amazing idea!