tooling: action to automatically backport changes to earlier branches #18

Closed
opened 2023-08-17 13:20:40 +00:00 by caesar · 34 comments

It would be great if PRs with a specific tag such as backport/v1.20 could be automatically cherry-picked onto that branch when the PR is merged.

Perhaps a Forgejo Action could achieve that?

It would be great if PRs with a specific tag such as `backport/v1.20` could be automatically cherry-picked onto that branch when the PR is merged. Perhaps a Forgejo Action could achieve that?
caesar added the
meta
label 2023-08-17 13:20:46 +00:00

We would need a bot user who has access to this repo if we want previews to work. If we don't care about that, the bot can use it's own fork to submit the pull requests.

UPDATE: It would definitely require a bot with write access to this repo if you just want to cherry-pick those commits to the target branch without a pull request, but I feel it would be safer to require at least one human approval in case the automated cherry-pick doesn't work as expected.

We would need a bot user who has access to this repo if we want previews to work. If we don't care about that, the bot can use it's own fork to submit the pull requests. UPDATE: It would definitely require a bot with write access to this repo if you just want to cherry-pick those commits to the target branch without a pull request, but I feel it would be safer to require at least one human approval in case the automated cherry-pick doesn't work as expected.
Poster
Owner

We would need a bot user who has access to this repo if we want previews to work.

I think that would be safe, because the action would only be triggered when a PR is merged, which by definition means it's been reviewed by at least one person who has commit access to the repo. That said, previews probably aren't very important for backports.

I'd actually been imagining it would commit directly to the version branches, but you're right, opening a PR would be better.

> We would need a bot user who has access to this repo if we want previews to work. I think that would be safe, because the action would only be triggered when a PR is merged, which by definition means it's been reviewed by at least one person who has commit access to the repo. That said, previews probably aren't very important for backports. I'd actually been imagining it would commit directly to the version branches, but you're right, opening a PR would be better.

With v1.21 it will be possible to run workflows on a regular basis (cron style). Creating or re-using an existing action that does that (cherry-pick from one branch to another + create a PR) is not too complicated and there are plenty of examples to draw inspiration from out there.

With v1.21 it will be possible to run workflows on a regular basis (cron style). Creating or re-using an existing action that does that (cherry-pick from one branch to another + create a PR) is not too complicated and there are plenty of examples to draw inspiration from out there.

Or it could be a workflow that is triggered on push and attempts the backport if the matching PR / issue has the backport label.

Or it could be a workflow that is triggered on push and attempts the backport if the matching PR / issue has the backport label. * https://github.com/sqren/backport-github-action (old but that's an example) * https://github.com/tibdex/backport (recent) * https://github.com/kiegroup/git-backporting (recent)

I suppose we could also just have a script and a cron job and port it over to Actions when Forgejo v1.21 is available on Codeberg.

I suppose we could also just have a script and a cron job and port it over to Actions when Forgejo v1.21 is available on Codeberg.
@pierreprinetti are you the author of https://github.com/pierreprinetti/backport?

Using mergify is another possibility. It is mature and robust has a lot more features but can also do backporting.I think it would be worth the time.

https://docs.mergify.com/actions/backport/

Using mergify is another possibility. It is mature and robust has a lot more features but can also do backporting.I think it would be worth the time. https://docs.mergify.com/actions/backport/

Backporting bots that are project specific, for inspiration:

Backporting bots that are project specific, for inspiration: * Nextcloud https://github.com/nextcloud/backportbot * Gitea https://github.com/GiteaBot/gitea-backporter

Given that there are not too many backports at the moment and there is no immediate need to automate that, I think the wiser choice would be to try and use mergify. The problem with all the other solutions is that they are ad-hoc or not very popular. There are a lot of tiny annoying details to deal with when it comes to backports and it requires regular maintenance.

That being said... my positive impression on mergify has to be mitigated with the fact that:

  • I never tried it myself
  • It is bound to GitHub actions and possibly vastly incompatible with Forgejo Actions
Given that there are not too many backports at the moment and there is no immediate need to automate that, I think the wiser choice would be to try and use mergify. The problem with all the other solutions is that they are ad-hoc or not very popular. There are a lot of tiny annoying details to deal with when it comes to backports and it requires regular maintenance. That being said... my positive impression on mergify has to be mitigated with the fact that: * I never tried it myself * It is bound to GitHub actions and possibly vastly incompatible with Forgejo Actions

@pierreprinetti are you the author of https://github.com/pierreprinetti/backport?

I am not! It’s Andrea Lamparelli and this is the original repository: https://github.com/kiegroup/git-backporting

We happily use it in Gophercloud (hosted on Github).

> @pierreprinetti are you the author of https://github.com/pierreprinetti/backport? I am not! It’s Andrea Lamparelli and this is the original repository: https://github.com/kiegroup/git-backporting We happily use it in [Gophercloud](https://github.com/gophercloud/gophercloud) (hosted on Github).

Great. Do you think it would be a good fit for Forgejo backports?

Great. Do you think it would be a good fit for Forgejo backports?

It worked for our use-case. I don’t know the requirements of this one well enough to say.

It worked for our use-case. I don’t know the requirements of this one well enough to say.
Poster
Owner

Or it could be a workflow that is triggered on push and attempts the backport if the matching PR / issue has the backport label.

That's what I'd envisaged. I think that would be better than a cron job.

I'd been looking at https://github.com/tibdex/backport, and it looks fine for our use case, but https://github.com/kiegroup/git-backporting also looks interesting.

Using mergify is another possibility. It is mature and robust has a lot more features but can also do backporting.I think it would be worth the time.

So far as I can tell it's a proprietary hosted service, which doesn't seem like the sort of thing we tend to use. Or am I missing something? When I click the "Get Started" link for open-source projects on their pricing page, it requires me to sign in with GitHub.

> Or it could be a workflow that is triggered on push and attempts the backport if the matching PR / issue has the backport label. That's what I'd envisaged. I think that would be better than a cron job. I'd been looking at https://github.com/tibdex/backport, and it looks fine for our use case, but https://github.com/kiegroup/git-backporting also looks interesting. > Using mergify is another possibility. It is mature and robust has a lot more features but can also do backporting.I think it would be worth the time. So far as I can tell it's a proprietary hosted service, which doesn't seem like the sort of thing we tend to use. Or am I missing something? When I click the "Get Started" link for open-source projects on their [pricing page](https://mergify.com/pricing), it requires me to sign in with GitHub.

It worked for our use-case. I don’t know the requirements of this one well enough to say.

For how long have you been happy with it?

> It worked for our use-case. I don’t know the requirements of this one well enough to say. For how long have you been happy with it?
Poster
Owner

there are not too many backports at the moment and there is no immediate need to automate that

I forgot to reply to this. But my hope is that by making backports very easy, there will be many more of them and at least the last major version of the docs will be kept up to date with the next branch as much as possible.

But in the meantime, of course, we can do them manually, so indeed it is more important to do it well rather than to do it quickly.

> there are not too many backports at the moment and there is no immediate need to automate that I forgot to reply to this. But my hope is that by making backports very easy, there will be many more of them and at least the last major version of the docs will be kept up to date with the `next` branch as much as possible. But in the meantime, of course, we can do them manually, so indeed it is more important to do it well rather than to do it quickly.
Poster
Owner

After looking at all the options mentioned so far, https://github.com/tibdex/backport seems to me to be the cleanest and easiest to use. I'll have a go at setting it up tomorrow if nobody else does it first.

After looking at all the options mentioned so far, https://github.com/tibdex/backport seems to me to be the cleanest and easiest to use. I'll have a go at setting it up tomorrow if nobody else does it first.

It worked for our use-case. I don’t know the requirements of this one well enough to say.

For how long have you been happy with it?

Just months, but we’ve had a couple edge cases already.

Our requirements were:

  • keep the original commits (with their commit signatures) and use merge commits
  • control over the trigger (down the road, we may want to use labels to backport to two different branches)
  • fail in case of conflict

Once you start testing, you’ll likely realise that some of them make assumptions that don’t match your use-case (e.g. the merge strategy). My suggestion is to try them and thoroughly analyse the resulting backports (to a throwaway branch) to see if that’s what you want.

Checks you may want to run:

  • long commit messages
  • multiple commits
  • multiple commits with long messages
  • what happens to the original PR message?
  • what happens to a LONG original PR message?
  • what happens in case of conflict with the target branch?
  • where is the new PR branch created?
> > It worked for our use-case. I don’t know the requirements of this one well enough to say. > > For how long have you been happy with it? Just months, but we’ve had a couple edge cases already. Our requirements were: * keep the original commits (with their commit signatures) and use merge commits * control over the trigger (down the road, we may want to use labels to backport to two different branches) * fail in case of conflict Once you start testing, you’ll likely realise that some of them make assumptions that don’t match your use-case (e.g. the merge strategy). My suggestion is to try them and thoroughly analyse the resulting backports (to a throwaway branch) to see if that’s what you want. Checks you may want to run: * long commit messages * multiple commits * multiple commits with long messages * what happens to the original PR message? * what happens to a LONG original PR message? * what happens in case of conflict with the target branch? * where is the new PR branch created?

@pierreprinetti very interesting feedback. One last question: have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution?

@pierreprinetti very interesting feedback. One last question: have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution?

have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution?

We have not; it didn’t come into our radar range at the time. I wouldn’t be able to compare them unfortunately.

> have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution? We have not; it didn’t come into our radar range at the time. I wouldn’t be able to compare them unfortunately.
Our config, for reference: https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml
Poster
Owner

Thanks for the tips @pierreprinetti, there's some very useful things to think about there, though in the case of this docs repo our merge strategy is the opposite of yours (preferring cherry-picking over merging).

have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution?

@earl-warren I'm still confused by the focus on a proprietary hosted platform which, so far as I can tell, is only compatible with GitHub. What am I missing?

Thanks for the tips @pierreprinetti, there's some very useful things to think about there, though in the case of this docs repo our merge strategy is the opposite of yours (preferring cherry-picking over merging). > have you considered using https://docs.mergify.com/actions/backport/ when you were researching a solution? @earl-warren I'm still confused by the focus on a proprietary hosted platform which, so far as I can tell, is [only compatible with GitHub](https://docs.mergify.com/getting-started/#installation). What am I missing?

It may be compatible with Forgejo if it is not too tightly GitHub dependent because Forgejo is a little compatible. But the devil is in the details and going with mergify would be a lot of work.

It may be compatible with Forgejo if it is not too tightly GitHub dependent because Forgejo is a little compatible. But the devil is in the details and going with mergify would be a lot of work.

After looking at all the options mentioned so far, https://github.com/tibdex/backport seems to me to be the cleanest and easiest to use. I'll have a go at setting it up tomorrow if nobody else does it first.

You will want to adapt the example backport.yml in your experiments to use a more recent image because it will otherwise fail because the git version is outdated. You need:

    runs-on: docker
    container:
      image: node:20-bookworm

The complete modified example is:

name: Backport
on:
  pull_request_target:
    types:
      - closed
      - labeled

jobs:
  backport:
    name: Backport
    runs-on: docker
    container:
      image: node:20-bookworm
    # Only react to merged PRs for security reasons.
    # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
    if: >
      github.event.pull_request.merged
      && (
        github.event.action == 'closed'
        || (
          github.event.action == 'labeled'
          && contains(github.event.label.name, 'backport')
        )
      )      
    steps:
      - uses: https://github.com/tibdex/backport@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
> After looking at all the options mentioned so far, https://github.com/tibdex/backport seems to me to be the cleanest and easiest to use. I'll have a go at setting it up tomorrow if nobody else does it first. You will want to adapt the [example `backport.yml`](https://github.com/tibdex/backport/blob/main/.github/workflows/backport.yml) in your experiments to use a more recent image because it will otherwise fail because the git version is outdated. You need: ```yaml runs-on: docker container: image: node:20-bookworm ``` The complete modified example is: ```yaml name: Backport on: pull_request_target: types: - closed - labeled jobs: backport: name: Backport runs-on: docker container: image: node:20-bookworm # Only react to merged PRs for security reasons. # See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target. if: > github.event.pull_request.merged && ( github.event.action == 'closed' || ( github.event.action == 'labeled' && contains(github.event.label.name, 'backport') ) ) steps: - uses: https://github.com/tibdex/backport@v2 with: github_token: ${{ secrets.GITHUB_TOKEN }} ```
Poster
Owner

It may be compatible with Forgejo if it is not too tightly GitHub dependent because Forgejo is a little compatible. But the devil is in the details and going with mergify would be a lot of work.

So far as I can tell it's literally impossible to use outside GitHub because it's a GitHub Application that requires signing in with GitHub to use it. Since it's a hosted SaaS product and not an open source self-hostable tool, I don't see any way we could run it ourselves. Again, unless I'm missing something, I don't see any possibility of using it at all.

> It may be compatible with Forgejo if it is not too tightly GitHub dependent because Forgejo is a little compatible. But the devil is in the details and going with mergify would be a lot of work. So far as I can tell it's literally impossible to use outside GitHub because [it's a GitHub Application](https://docs.mergify.com/getting-started/#installation) that requires signing in with GitHub to use it. Since it's a hosted SaaS product and not an open source self-hostable tool, I don't see any way we could run it ourselves. Again, unless I'm missing something, I don't see any possibility of using it at all.

Going for the simpler action seems a good choice for now. https://github.com/tibdex/backport should work out of the box. If you would like me to set it up, I'll do it today. Just say the word.

Going for the simpler action seems a good choice for now. https://github.com/tibdex/backport should work out of the box. If you would like me to set it up, I'll do it today. Just say the word.
Poster
Owner

If you would like me to set it up, I'll do it today. Just say the word.

Sure, that would be great. Thanks!

> If you would like me to set it up, I'll do it today. Just say the word. Sure, that would be great. Thanks!

Our config, for reference: https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml

I'm interested to know why there is a need for an additional token? GITHUB_TOKEN is not enough?

> Our config, for reference: https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml I'm interested to know why there is a [need for an additional token](https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml#L26-L32)? GITHUB_TOKEN is not enough?

@caesar @crystal except for a glitch for which a workaround was implemented, it seems to work fine. See this backported PR for an example.

@caesar @crystal except for [a glitch](https://codeberg.org/forgejo/forgejo/issues/1286) for which a workaround was implemented, it seems to work fine. See [this backported PR](https://codeberg.org/forgejo/docs/pulls/29) for an example.
Poster
Owner

Looks good @earl-warren!

Perhaps we could set the head_template parameter to backport/<%= base %>/<%= number %>? This would be more like the structure we already use for PRs (pr/foo). I prefer it with the slashes because many Git GUIs represent branches with slashes in a directory structure, which significantly reduces visual clutter.

Similarly, I would set label_pattern to ^backport/(?<base>([^ ]+))$ and add the slash back to the label, though that's less important as Forgejo doesn't display labels in a directory structure, and only displays them in groups if they are exclusive. But it would still match better with the label format we use elsewhere.

I'll send a PR with both those changes if you agree.

Looks good @earl-warren! Perhaps we could set the [`head_template`](https://github.com/tibdex/backport/blob/7005ef85c4562bc23b0e9b4a9940d5922f439750/action.yml#L19) parameter to `backport/<%= base %>/<%= number %>`? This would be more like the structure we already use for PRs (`pr/foo`). I prefer it with the slashes because many Git GUIs represent branches with slashes in a directory structure, which significantly reduces visual clutter. Similarly, I would set [`label_pattern`](https://github.com/tibdex/backport/blob/7005ef85c4562bc23b0e9b4a9940d5922f439750/action.yml#L27C3-L27C16) to `^backport/(?<base>([^ ]+))$` and add the slash back to the label, though that's less important as Forgejo doesn't display labels in a directory structure, and only displays them in groups if they are exclusive. But it would still match better with the label format we use elsewhere. I'll send a PR with both those changes if you agree.

I'll send a PR with both those changes if you agree.

Sounds good, let's do that.

Update: by that I meant that I agree you do that.

> I'll send a PR with both those changes if you agree. Sounds good, let's do that. Update: by that I meant that I agree you do that.

Our config, for reference: https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml

I'm interested to know why there is a need for an additional token? GITHUB_TOKEN is not enough?

The PR must be done by a non-bot account if you want it to trigger actions. Github (and maybe Forgejo?) forbids bot actions to trigger further actions, in order to avoid infinite loops. And we want the backport PRs to trigger CI

> > Our config, for reference: https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml > > I'm interested to know why there is a [need for an additional token](https://github.com/gophercloud/gophercloud/blob/master/.github/workflows/backport_v1.yaml#L26-L32)? GITHUB_TOKEN is not enough? The PR must be done by a non-bot account if you want it to trigger actions. Github (and maybe Forgejo?) forbids bot actions to trigger further actions, in order to avoid infinite loops. And we want the backport PRs to trigger CI

There are improvements to make but the logic works well enough to close this issue. If someone feels differently, please re-open.

There are improvements to make but the logic works well enough to close this issue. If someone feels differently, please re-open.
Poster
Owner

The backport cherry-picks are committed with Git user github-actions[bot] with email github-actions[bot]@users.noreply.github.com.

Unfortunately this value is hardcoded in the backport action.

It's not a huge deal, just a bit annoying and seemed worth noting here.

The backport cherry-picks [are committed](https://codeberg.org/forgejo/docs/commit/7c1caace0638b03c15e65dc83388859bcab2925b) with Git user `github-actions[bot]` with email `github-actions[bot]@users.noreply.github.com`. Unfortunately this value [is hardcoded](https://github.com/tibdex/backport/blob/7005ef85c4562bc23b0e9b4a9940d5922f439750/src/backport.ts#L264C6-L264C50) in the `backport` action. It's not a huge deal, just a bit annoying and seemed worth noting here.
Collaborator
Opened an issue upstream: https://github.com/tibdex/backport/issues/106
Sign in to join this conversation.
No Milestone
No Assignees
6 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: forgejo/docs#18
There is no content yet.