Skip to content

feat: Add label-triggered backport workflow#684

Open
ZPascal wants to merge 4 commits into
cloudfoundry:ubuntu-jammyfrom
ZPascal:feat/backport-automation
Open

feat: Add label-triggered backport workflow#684
ZPascal wants to merge 4 commits into
cloudfoundry:ubuntu-jammyfrom
ZPascal:feat/backport-automation

Conversation

@ZPascal

@ZPascal ZPascal commented Jul 3, 2026

Copy link
Copy Markdown

Summary

Adds .github/workflows/backport.yml — a GitHub Actions workflow that automatically cherry-picks merged PRs onto other distro branches when backport/* labels are applied.

  • When a PR is merged with a backport/ubuntu-noble, backport/ubuntu-jammy, or backport/ubuntu-resolute label, the workflow cherry-picks the commits onto the named branch and opens a [Backport <target>] <title> PR automatically
  • Clean cherry-pick → ready-for-review PR
  • Conflict → draft PR with the failing commit SHA noted in the body, so the reviewer knows exactly what to resolve
  • Idempotent — re-running on the same PR safely skips if the backport branch already exists
  • Squash-aware — detects squash vs merge commits and handles both correctly
  • No extra secrets required — uses GITHUB_TOKEN only

Labels to create (one-time repo setup)

gh label create "backport/ubuntu-jammy"    --color "0075ca" --description "Cherry-pick this PR onto ubuntu-jammy"
gh label create "backport/ubuntu-noble"    --color "e4e669" --description "Cherry-pick this PR onto ubuntu-noble"
gh label create "backport/ubuntu-resolute" --color "d93f0b" --description "Cherry-pick this PR onto ubuntu-resolute"

Also enable Settings → Actions → General → Allow GitHub Actions to create and approve pull requests.

Test plan

  • Clean cherry-pick path tested: PR with backport/ubuntu-noble label merged → ready-for-review backport PR opened automatically
  • Conflict path tested: PR targeting ubuntu-resolute (diverged branch) → draft PR opened with failing SHA in body
  • Idempotency tested: re-run on existing branch skips cleanly
  • Multi-target tested: two backport/* labels on one PR → two independent backport PRs opened in parallel (fail-fast: false)
  • Squash merge tested: single-parent commit correctly cherry-picked directly

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@ZPascal, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b4baf4ed-98a6-40d3-8903-e0495ada1168

📥 Commits

Reviewing files that changed from the base of the PR and between f189a86 and 5d1d41f.

📒 Files selected for processing (2)
  • .github/pull_request_template.md
  • .github/workflows/backport.yml

Walkthrough

This pull request adds a new GitHub Actions workflow for automated backporting of merged pull requests. It triggers on closed merged PRs, derives target branches from backport/ labels, checks for existing backport branches or PRs, cherry-picks the merged changes onto per-target branches, and opens either a clean or draft backport PR based on conflict status. It also updates the pull request template and CONTRIBUTING.md with backport instructions and label mappings.

Changes

Related Issues: None provided.

Related PRs: None provided.

Suggested labels: ci, github-actions, automation, backport

Suggested reviewers: mkocher, mariash

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description does not follow the repository template and omits the required Merge Forward guidance and AI Review Feedback section. Rewrite it to match the template: include the Merge Forward instructions, then add a complete AI Review Feedback section for any open comments.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: adding a label-triggered backport workflow.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ZPascal ZPascal marked this pull request as draft July 3, 2026 09:39

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/backport.yml:
- Around line 46-55: The backport workflow is directly interpolating the
label-derived matrix.target into the shell script in the “Check if backport
branch already exists” step and the final “Skip” step, creating a
template-injection sink. Move matrix.target (and any similar PR-derived values)
into env for those steps, and reference the environment variables inside the
script instead of using direct ${{ }} expansion in run:. Keep the fix consistent
with the other workflow steps that already use env in backport.yml.
- Around line 46-55: The backport workflow currently skips entirely when the
branch exists, which can leave the job stuck if no PR was actually created.
Update the logic around the existing branch check in backport.yml to use gh pr
lookup for backport/${{ github.event.pull_request.number }}-to-${{ matrix.target
}} before deciding to skip, and only treat the backport as complete when an open
or closed PR for that branch is found. Keep the branch existence check in the
Check if backport branch already exists step, but add PR existence/status
verification before setting the skip path.
- Around line 7-9: The workflow-level permissions are too broad because
`contents: write` and `pull-requests: write` are applied to every job, including
`build-matrix` which only reads labels. Move the write permissions into the
`backport` job in the backport workflow, and set a restrictive default at the
workflow root (such as empty or read-only permissions) so only the job that
needs repository write access receives it.
- Around line 3-5: Add a workflow-level concurrency setting to the backport
workflow so only one run per pull request can execute at a time; the issue is in
the backport job triggered by pull_request closed events, and it can race when
rerun. Update the workflow near the existing on.pull_request trigger by
introducing a concurrency group keyed on the PR number, and make sure the
backport workflow’s run is cancelled or serialized for the same PR to prevent
overlapping pushes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b847e4ec-2bd8-4f8d-b576-7f66eff93ab9

📥 Commits

Reviewing files that changed from the base of the PR and between be5da7a and d586bed.

📒 Files selected for processing (1)
  • .github/workflows/backport.yml

Comment thread .github/workflows/backport.yml
Comment thread .github/workflows/backport.yml Outdated
Comment thread .github/workflows/backport.yml Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 3, 2026
@github-project-automation github-project-automation Bot moved this from Waiting for Changes | Open for Contribution to Pending Merge | Prioritized in Foundational Infrastructure Working Group Jul 3, 2026
@ZPascal ZPascal force-pushed the feat/backport-automation branch from 2352894 to 54a10d1 Compare July 3, 2026 14:44
ZPascal added 3 commits July 3, 2026 17:18
Adds a GitHub Actions workflow that automatically cherry-picks merged
PRs onto other distro branches when backport/* labels are present.

Usage: label a PR with backport/ubuntu-noble, backport/ubuntu-jammy,
or backport/ubuntu-resolute before merging. The workflow opens a
ready-for-review PR when the cherry-pick applies cleanly, or a draft
PR with the failing commit noted when there are conflicts.

Signed-off-by: Pascal Zimmermann <pascal.zimmermann01@sap.com>
Signed-off-by: Pascal Zimmerman <pascal.zimmermann01@sap.com>

# Conflicts:
#	.github/pull_request_template.md
*fix: Add concurrency group keyed on PR number to prevent push races on re-runs (concurrency-limits)
*fix: Move matrix.target and PR number out of run: template strings into env: vars in the check and skip steps (template-injection)

Signed-off-by: Pascal Zimmermann <pascal.zimmermann01@sap.com>
@ZPascal ZPascal force-pushed the feat/backport-automation branch from 54a10d1 to f189a86 Compare July 3, 2026 15:19
@ZPascal ZPascal marked this pull request as ready for review July 3, 2026 15:19
@ZPascal ZPascal changed the title ci: add label-triggered backport workflow feat: Add label-triggered backport workflow Jul 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/pull_request_template.md:
- Around line 1-10: The pull request template starts with an H2 instead of the
required top-level heading, which will trip markdownlint. Update the heading in
the pull request template from the current Backporting section to a single H1 so
the template remains lint-clean. Keep the rest of the backporting instructions
unchanged.

In @.github/workflows/backport.yml:
- Around line 77-89: The backport recovery path is blocked because the
“Cherry-pick onto target branch” step in the backport workflow only runs for
steps.check.outputs.exists == 'false', so the branch_only case never sets
cherrypick outputs and the later PR-opening steps cannot run. Update the
conditional on the Cherry-pick step (and any related downstream gating if
needed) so it also executes for the branch_only recovery case, ensuring
steps.cherrypick.outputs.conflict is always populated for that path and the
“Open backport PR” steps can create the PR.
- Around line 91-116: The backport workflow’s merge-commit handling in the
commit collection logic includes the merge commit itself, which causes
cherry-pick to fail for clean merge PRs. Update the commit selection in the
backport step around the parent-count check and the `commits` array so merge
commits are excluded from the cherry-pick list (for example by filtering with
`--no-merges`) or explicitly handled with the proper merge cherry-pick strategy,
keeping the existing `git cherry-pick` loop and conflict fallback intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: db40b2c7-2a85-4615-96e8-21581cf945bd

📥 Commits

Reviewing files that changed from the base of the PR and between d586bed and f189a86.

📒 Files selected for processing (3)
  • .github/pull_request_template.md
  • .github/workflows/backport.yml
  • CONTRIBUTING.md

Comment thread .github/pull_request_template.md Outdated
Comment thread .github/workflows/backport.yml
Comment thread .github/workflows/backport.yml Outdated
@github-project-automation github-project-automation Bot moved this from Pending Merge | Prioritized to Waiting for Changes | Open for Contribution in Foundational Infrastructure Working Group Jul 3, 2026
@github-project-automation github-project-automation Bot moved this from Waiting for Changes | Open for Contribution to Pending Merge | Prioritized in Foundational Infrastructure Working Group Jul 3, 2026
…only ran for exists==false, so cherrypick outputs were never set for the recovery case and the PR-open steps never fired. Now runs for branch_only too

* fix: Merge commit included in cherry-pick range: git log BASE..MERGE on a merge commit includes the merge commit itself, which cherry-pick rejects without -m. Add --no-merges to exclude it
* docs: Satisfy markdownlint

Signed-off-by: Pascal Zimmermann <pascal.zimmermann01@sap.com>
@ZPascal ZPascal force-pushed the feat/backport-automation branch from cb1b348 to 5d1d41f Compare July 3, 2026 16:02

@aramprice aramprice left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the automation, thank you for putting in work to address this pain.

Instead of automating back-porting I think an automation that merges changes forward would be be better:

  • Opt-in back-porting relies on manual tagging, making it easy to miss small commits and causing greater branch drift over time.
  • Branch similarity should be the default. Diverging branches should be what requires extra effort, not harmonizing them.

The default should be keeping branches harmonized as much as possible (easy path), differences should be explicit and require effort (manual merge-forward conflict resolution).

Thoughts?

@github-project-automation github-project-automation Bot moved this from Pending Merge | Prioritized to Waiting for Changes | Open for Contribution in Foundational Infrastructure Working Group Jul 6, 2026
@ZPascal

ZPascal commented Jul 7, 2026

Copy link
Copy Markdown
Author

I like the automation, thank you for putting in work to address this pain.

Instead of automating back-porting I think an automation that merges changes forward would be be better:

  • Opt-in back-porting relies on manual tagging, making it easy to miss small commits and causing greater branch drift over time.
  • Branch similarity should be the default. Diverging branches should be what requires extra effort, not harmonizing them.

The default should be keeping branches harmonized as much as possible (easy path), differences should be explicit and require effort (manual merge-forward conflict resolution).

Thoughts?

I get the instinct - merge-forward as a default does sound cleaner in theory, but I think it doesn't quite fit how these branches actually work.

Noble, Resolute, and Jammy aren't release branches of the same thing. They track different Ubuntu LTS versions. The divergence between them is ~1700 commits, and a lot of that is intentional — different kernel versions, different package names, different service configs. Most commits to Jammy have no business going to Noble, and auto-forwarding them would just create a steady stream of conflicts that someone has to triage.

Backport-on-label captures what actually happens in practice:
Occasionally there's a security fix or a build tweak that applies cleanly across distributions, and that's the thing you want to automate.

If the concern is that people will forget to label things - fair, that's a real risk. I would rather solve the process issue (for example, a checklist item in the PR template) than sending each commit across branches by default and dealing with the fallout.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Waiting for Changes | Open for Contribution

Development

Successfully merging this pull request may close these issues.

2 participants