[ci] Added automated backport workflow#346
Conversation
📝 WalkthroughWalkthroughAdds a new GitHub Actions workflow at .github/workflows/backport.yml named "Backport fixes to stable branch". It defines two triggers: a push-based job that runs on pushes to master and passes Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant Repo as Repository (.github/workflows/backport.yml)
participant GH as GitHub Actions
participant Reusable as openwisp/openwisp-utils reusable workflow
opt Push-triggered backport
Dev->>Repo: Push to master (commit)
GH->>Repo: Detect push -> run backport-on-push
Repo->>Reusable: Invoke reusable-backport (input: commit_sha, secrets)
Reusable->>GH: Execute backport steps (uses provided secrets)
GH->>Repo: Report result / update status
end
opt Comment-triggered backport
Dev->>Repo: Comment "/backport" on merged PR
GH->>Repo: Detect issue_comment -> run backport-on-comment
Repo->>Reusable: Invoke reusable-backport (inputs: pr_number, comment_body, secrets)
Reusable->>GH: Execute backport steps (uses provided secrets)
GH->>Repo: Report result / update status
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/backport.yml
🔇 Additional comments (1)
.github/workflows/backport.yml (1)
3-7: The reusable workflow already handles non-backport pushes gracefully. Thereusable-backport.ymlworkflow reads the commit message for a[backport: branches]label and only executes the backport job if backport targets are explicitly specified. Commits tomaster/mainwithout this label will cause the parse job to output an empty branches list, which prevents the backport job from running due to its conditional check. Non-backport commits therefore do not trigger spurious PR creation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/backport.yml:
- Line 35: The workflow guard currently checks contains(fromJSON('["MEMBER",
"OWNER"]'), github.event.comment.author_association) and therefore excludes
repository collaborators; if collaborators with write access should be allowed
to trigger backports, update that array to include "COLLABORATOR" (i.e., add
"COLLABORATOR" to the fromJSON array in the contains(...) check in backport.yml)
so the condition permits MEMBER, OWNER, and COLLABORATOR associations.
- Around line 11-13: The concurrency group currently uses github.ref which is
identical across push and issue_comment events and causes unrelated runs to
serialize; update the concurrency.group value (the concurrency: group setting)
to include the event name and a per-request identifier so runs for different
PRs/issues can run in parallel—for example use an expression combining
github.event_name and a coalesced identifier like ${{
github.event.pull_request.number || github.event.issue.number || github.sha }}
(keep cancel-in-progress: false or adjust as desired) so concurrency.group
becomes something like backport-${{ github.workflow }}-${{ github.event_name
}}-${{ github.event.pull_request.number || github.event.issue.number ||
github.sha }} referencing the symbols concurrency.group, cancel-in-progress,
github.ref, github.event.pull_request.number, github.event.issue.number,
github.sha, and github.event_name.
- Line 22: Replace the mutable branch reference for the reusable workflow with a
full commit SHA: locate the two occurrences of "uses:
openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master" and
replace "@master" with the current full-length commit SHA for
openwisp/openwisp-utils (you can obtain it via `gh api
repos/openwisp/openwisp-utils/commits/master --jq '.sha'`), updating both
instances so the workflow is pinned to that exact commit SHA.
| concurrency: | ||
| group: backport-${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false |
There was a problem hiding this comment.
Concurrency group key collapses all runs into one queue.
github.ref for issue_comment events is always the default branch. That is the same value the push trigger produces when a commit lands on master/main, so every run — push-triggered or comment-triggered, regardless of which PR is being backported — shares a single concurrency group. With cancel-in-progress: false they all queue sequentially, meaning two concurrent /backport requests on unrelated PRs (e.g. targeting different stable branches) unnecessarily block each other.
Scope the key more narrowly so unrelated runs can proceed in parallel:
🔧 Proposed fix
concurrency:
- group: backport-${{ github.workflow }}-${{ github.ref }}
+ group: >-
+ ${{ github.event_name == 'issue_comment'
+ && format('backport-comment-{0}', github.event.issue.number)
+ || format('backport-push-{0}', github.sha) }}
cancel-in-progress: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| concurrency: | |
| group: backport-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: false | |
| concurrency: | |
| group: >- | |
| ${{ github.event_name == 'issue_comment' | |
| && format('backport-comment-{0}', github.event.issue.number) | |
| || format('backport-push-{0}', github.sha) }} | |
| cancel-in-progress: false |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/backport.yml around lines 11 - 13, The concurrency group
currently uses github.ref which is identical across push and issue_comment
events and causes unrelated runs to serialize; update the concurrency.group
value (the concurrency: group setting) to include the event name and a
per-request identifier so runs for different PRs/issues can run in parallel—for
example use an expression combining github.event_name and a coalesced identifier
like ${{ github.event.pull_request.number || github.event.issue.number ||
github.sha }} (keep cancel-in-progress: false or adjust as desired) so
concurrency.group becomes something like backport-${{ github.workflow }}-${{
github.event_name }}-${{ github.event.pull_request.number ||
github.event.issue.number || github.sha }} referencing the symbols
concurrency.group, cancel-in-progress, github.ref,
github.event.pull_request.number, github.event.issue.number, github.sha, and
github.event_name.
| jobs: | ||
| backport-on-push: | ||
| if: github.event_name == 'push' | ||
| uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master |
There was a problem hiding this comment.
Pin the external reusable workflow to a commit SHA, not the mutable @master branch.
"Pinning an action to a full-length commit SHA is currently the only way to use an action as an immutable release." A tag (or branch name) can be moved or deleted if a bad actor gains access to the upstream repository, and the same principles apply to third-party reusable workflows. Additionally, when re-running a workflow that uses a reusable workflow and the reference is not a SHA, re-running all jobs will use the reusable workflow from the specified reference at that point in time, making reruns non-deterministic.
🔧 Proposed fix (apply to both lines 22 and 37)
- uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master
+ uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@<full-commit-sha> # `@master` as of <date>Retrieve the current SHA with:
gh api repos/openwisp/openwisp-utils/commits/master --jq '.sha'Also applies to: 37-37
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/backport.yml at line 22, Replace the mutable branch
reference for the reusable workflow with a full commit SHA: locate the two
occurrences of "uses:
openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master" and
replace "@master" with the current full-length commit SHA for
openwisp/openwisp-utils (you can obtain it via `gh api
repos/openwisp/openwisp-utils/commits/master --jq '.sha'`), updating both
instances so the workflow is pinned to that exact commit SHA.
| github.event.issue.pull_request && | ||
| github.event.issue.pull_request.merged_at != null && | ||
| github.event.issue.state == 'closed' && | ||
| contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider whether COLLABORATOR should be included in the author association check.
The guard currently restricts comment-triggered backports to MEMBER and OWNER. Repository collaborators with explicit write access (COLLABORATOR association) are excluded. If outside contributors with write access should be able to trigger backports, add "COLLABORATOR" to the list.
🔧 Proposed fix (if collaborators should be allowed)
- contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) &&
+ contains(fromJSON('["MEMBER", "OWNER", "COLLABORATOR"]'), github.event.comment.author_association) &&📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && | |
| contains(fromJSON('["MEMBER", "OWNER", "COLLABORATOR"]'), github.event.comment.author_association) && |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/backport.yml at line 35, The workflow guard currently
checks contains(fromJSON('["MEMBER", "OWNER"]'),
github.event.comment.author_association) and therefore excludes repository
collaborators; if collaborators with write access should be allowed to trigger
backports, update that array to include "COLLABORATOR" (i.e., add "COLLABORATOR"
to the fromJSON array in the contains(...) check in backport.yml) so the
condition permits MEMBER, OWNER, and COLLABORATOR associations.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
.github/workflows/backport.yml (2)
21-21:⚠️ Potential issue | 🟠 MajorPin reusable workflow to a full commit SHA.
Both
usesentries reference mutable@master, which is non-deterministic on reruns and weaker from a supply-chain perspective.🔧 Proposed fix
- uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master + uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@<full-commit-sha> ... - uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master + uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@<full-commit-sha>#!/bin/bash # Fetch current SHA of openwisp-utils master (read-only verification) gh api repos/openwisp/openwisp-utils/commits/master --jq '.sha'Also applies to: 36-36
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/backport.yml at line 21, The workflow uses a mutable ref ("uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master") which must be pinned to an immutable full commit SHA; update every "uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master" occurrence (including the second occurrence referenced in the comment) to the corresponding full commit SHA for openwisp-utils master (you can obtain it via GitHub API/gh cli) and replace the `@master` suffix with @<full-sha> so the reusable workflow is pinned.
11-12:⚠️ Potential issue | 🟠 MajorScope concurrency per request, not per branch ref.
Using
github.refhere causes unrelated runs to queue behind each other (same ref for push tomasterandissue_commentworkflows). Use event + per-request identifier to avoid unnecessary serialization.🔧 Proposed fix
concurrency: - group: backport-${{ github.workflow }}-${{ github.ref }} + group: backport-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.issue.number || github.sha }} cancel-in-progress: false🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/backport.yml around lines 11 - 12, The workflow concurrency group uses github.ref which serializes unrelated runs; change the group to scope by workflow + event/run id instead — replace github.ref with github.event_name and a per-request identifier such as github.run_id (e.g., use group values built from github.workflow, github.event_name and github.run_id) so each request is isolated; update the group key where "group:" is defined and remove the reference to github.ref.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/backport.yml:
- Line 32: Remove the invalid condition reference to
github.event.issue.pull_request.merged_at from the issue_comment trigger in the
workflow (the check github.event.issue.pull_request.merged_at != null) because
merged_at is not present in issue_comment payloads; instead, call the reusable
workflow as-is on issue_comment and move merged-state verification into the
reusable workflow by querying the Pull Requests API for the PR number (from
github.event.issue.pull_request.url or related fields) and confirming merged
status before performing backport logic.
---
Duplicate comments:
In @.github/workflows/backport.yml:
- Line 21: The workflow uses a mutable ref ("uses:
openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master") which
must be pinned to an immutable full commit SHA; update every "uses:
openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master"
occurrence (including the second occurrence referenced in the comment) to the
corresponding full commit SHA for openwisp-utils master (you can obtain it via
GitHub API/gh cli) and replace the `@master` suffix with @<full-sha> so the
reusable workflow is pinned.
- Around line 11-12: The workflow concurrency group uses github.ref which
serializes unrelated runs; change the group to scope by workflow + event/run id
instead — replace github.ref with github.event_name and a per-request identifier
such as github.run_id (e.g., use group values built from github.workflow,
github.event_name and github.run_id) so each request is isolated; update the
group key where "group:" is defined and remove the reference to github.ref.
| if: > | ||
| github.event_name == 'issue_comment' && | ||
| github.event.issue.pull_request && | ||
| github.event.issue.pull_request.merged_at != null && |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
GitHub Actions issue_comment event payload github.event.issue.pull_request merged_at field documentation
💡 Result:
In an issue_comment workflow run, github.event is the webhook payload, and the issue object is the same “issue (or PR-as-issue)” shape you get from the Issues API. GitHub’s Actions docs note you can detect PR comments with github.event.issue.pull_request (it’s present for PRs, absent for issues). [1]
However, for issue_comment, github.event.issue.pull_request is only a link object (e.g., url, html_url, diff_url, patch_url) and does not include PR fields like merged_at. This is shown in the Issues API example response where pull_request contains only those URLs. [2]
To get merged_at, you must fetch the PR itself (e.g., via the Pull Requests API using the URL in github.event.issue.pull_request.url) or at least check merged status via the dedicated endpoint (GET /repos/{owner}/{repo}/pulls/{pull_number}/merge). [3]
Sources
[1] https://docs.github.com/actions/learn-github-actions/events-that-trigger-workflows
[2] https://docs.github.com/en/rest/issues/issues
[3] https://docs.github.com/en/rest/pulls/pulls
Remove merged_at check from trigger—this field does not exist in issue_comment payloads.
In issue_comment events, github.event.issue.pull_request contains only link metadata (url, html_url, diff_url, patch_url). The merged_at field is not present, making the current guard ineffective. Move merged status verification into the reusable workflow using the Pull Requests API.
🔧 Proposed fix
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
- github.event.issue.pull_request.merged_at != null &&
github.event.issue.state == 'closed' &&
contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) &&
startsWith(github.event.comment.body, '/backport')📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| github.event.issue.pull_request.merged_at != null && | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| github.event.issue.state == 'closed' && | |
| contains(fromJSON('["MEMBER", "OWNER"]'), github.event.comment.author_association) && | |
| startsWith(github.event.comment.body, '/backport') |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/backport.yml at line 32, Remove the invalid condition
reference to github.event.issue.pull_request.merged_at from the issue_comment
trigger in the workflow (the check github.event.issue.pull_request.merged_at !=
null) because merged_at is not present in issue_comment payloads; instead, call
the reusable workflow as-is on issue_comment and move merged-state verification
into the reusable workflow by querying the Pull Requests API for the PR number
(from github.event.issue.pull_request.url or related fields) and confirming
merged status before performing backport logic.
Checklist
Reference to Existing Issue
openwisp/openwisp-utils#501