Skip to content

[ci] Added automated backport workflow#567

Open
atif09 wants to merge 1 commit intoopenwisp:masterfrom
atif09:feature/backport-workflow
Open

[ci] Added automated backport workflow#567
atif09 wants to merge 1 commit intoopenwisp:masterfrom
atif09:feature/backport-workflow

Conversation

@atif09
Copy link

@atif09 atif09 commented Feb 22, 2026

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.

Reference to Existing Issue

Related to openwisp/openwisp-utils#501

@coderabbitai
Copy link

coderabbitai bot commented Feb 22, 2026

📝 Walkthrough

Walkthrough

A new GitHub Actions workflow file is introduced to automate backporting fixes to a stable branch. The workflow triggers on pushes to master/main and on issue comments. It defines two jobs: one that automatically backports on push events using commit SHA, and another that backports on demand when a pull request comment starting with /backport is created by repository members or owners. Both jobs delegate to a centralized reusable backport workflow, passing relevant parameters and bot secrets.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description includes completed checklist items and references a related issue, but lacks a detailed description of changes and does not fill out required sections like 'Description of Changes' and 'Screenshot'. Provide a detailed 'Description of Changes' section explaining the backport workflow design and why certain sections (tests, documentation) were unchecked.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title '[ci] Added automated backport workflow' directly reflects the main change—introducing a new GitHub Actions workflow for automated backporting to stable branches.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8f378f3 and 9d0cdda.

📒 Files selected for processing (1)
  • .github/workflows/backport.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CI Build
🤖 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:
- Around line 30-36: Remove the redundant state check and include COLLABORATOR
in the author association whitelist: update the workflow conditional by removing
the clause "github.event.issue.state == 'closed'" (since merged_at != null
already implies closed) and expand the JSON array passed to contains(...) to
include "COLLABORATOR" alongside "MEMBER" and "OWNER" so the expression becomes
contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'),
github.event.comment.author_association); keep the existing merged_at and
startsWith(github.event.comment.body, '/backport') checks unchanged.
- Around line 11-13: The concurrency group currently uses github.workflow and
github.ref which collapses different event types (issue_comment vs push) into
the same slot; update the concurrency.group value so it includes the event type
and a per-PR identifier to avoid conflation and serialization — e.g. change the
group key built from concurrency.group: backport-${{ github.workflow }}-${{
github.ref }} to include ${{ github.event_name }} and a PR/issue identifier
(like ${{ github.event.pull_request.number || github.event.issue.number }}) and
keep a commit identifier when relevant (e.g. ${{ github.sha }}), so jobs
triggered by different events or different PRs no longer produce the same group
key.
- Line 22: Replace the mutable branch reference in the reusable workflow usage
by pinning both occurrences of
"openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master" to a
full-length commit SHA (use the commit SHA for the target revision) and add a
short human-readable comment next to each pinned SHA explaining why it’s pinned;
update both "uses:" entries so they reference the immutable commit SHA instead
of "@master" and rely on Dependabot/Renovate to keep the SHA current.

Comment on lines +11 to +13
concurrency:
group: backport-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Concurrency group conflates unrelated events and serializes independent PR backports

github.sha and github.ref always point to the default branch for issue_comment events. This means both jobs produce the identical group key backport-Backport fixes to stable branch-refs/heads/master, causing two problems:

  1. A push-triggered backport and any /backport comment always land in the same concurrency slot, blocking each other even though they are completely independent operations.
  2. Multiple /backport comments on different PRs are serialized unnecessarily, since they all resolve to the same group key.
🔧 Proposed fix
 concurrency:
-  group: backport-${{ github.workflow }}-${{ github.ref }}
+  group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'issue_comment' && github.event.issue.number || github.ref }}
   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.workflow and github.ref which collapses different event
types (issue_comment vs push) into the same slot; update the concurrency.group
value so it includes the event type and a per-PR identifier to avoid conflation
and serialization — e.g. change the group key built from concurrency.group:
backport-${{ github.workflow }}-${{ github.ref }} to include ${{
github.event_name }} and a PR/issue identifier (like ${{
github.event.pull_request.number || github.event.issue.number }}) and keep a
commit identifier when relevant (e.g. ${{ github.sha }}), so jobs triggered by
different events or different PRs no longer produce the same group key.

jobs:
backport-on-push:
if: github.event_name == 'push'
uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/backport.yml

Repository: openwisp/docker-openwisp

Length of output: 1656


🌐 Web query:

GitHub security best practices reusable workflows pinning commit SHA

💡 Result:

Best practices (GitHub Actions) for reusable workflows + SHA pinning

1) Pin all third‑party actions to a full-length commit SHA

Use immutable refs to reduce supply-chain risk from moved tags/branches. Prefer a SHA that corresponds to a tagged release, and add a comment with the human version for readability (and easier updates). Example:

- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

[1]

2) Pin reusable workflow calls to a commit SHA (safest)

When calling a reusable workflow (jobs.<job_id>.uses), {ref} can be a SHA, tag, or branch—but GitHub recommends SHA as the safest for stability and security.

jobs:
  ci:
    uses: org/repo/.github/workflows/ci.yml@<full_commit_sha>

[2]

Note: If the reusable workflow is in the same repo and you use ./.github/workflows/<file>, it’s taken from the same commit as the caller workflow (no @ref). [2]

3) Enforce SHA pinning via org/enterprise policy (where available)

Admins can require actions to be pinned to a full-length commit SHA using the Allowed actions and reusable workflows policy controls. This is explicitly supported as an enforcement option, and GitHub has continued improving these controls (including enforcement and blocking). [3] [4]

4) Restrict what can run (allowlist/denylist)

Use the same policy area to allow only:

  • enterprise/internal actions and workflows, plus
  • selected external orgs/repos (and optionally block specific ones/versions). [4]

5) Don’t treat SHA pinning as sufficient by itself

Even pinned actions can remain risky if they pull mutable dependencies (e.g., downloading binaries at runtime, unpinned container images, nested unpinned actions). Review for “mutable dependencies,” not just the uses: line. [1]

Sources: GitHub Well-Architected Actions security recommendations [1], GitHub Docs on reusable workflows [2], GitHub Changelog on SHA pinning enforcement & blocking [3], GitHub Enterprise Cloud Docs on Actions policies (allowed actions/reusable workflows + “require pinned SHA”) [4].


🌐 Web query:

tj-actions changed-files compromise March 2025

💡 Result:

In March 2025, the popular GitHub Action tj-actions/changed-files was hit by a supply-chain compromise (tracked as CVE-2025-30066) that caused CI secrets to be exposed via workflow logs, especially in public repositories. [1][2]

What happened

  • Attackers added/pointed tags to a malicious commit (widely reported as 0e58ed8…) so that many workflows referencing seemingly “safe” version tags would execute malicious code. [2][3]
  • The payload pulled and executed a script intended to dump credentials/secrets from the GitHub runner process memory and print them into action logs (often double-base64 encoded/obfuscated). [1][3]

When / who was at risk

  • CISA’s alert highlights an exposure window commonly cited as 2025-03-12 00:00 UTC to 2025-03-15 12:00 UTC for repos running the malicious code. [1]
  • Public repos were at highest risk because logs (and thus leaked secrets) could be publicly readable; private repos still had exposure risk depending on who could access logs. [2][3]

Remediation (what to do)

  • Assume secrets are compromised if your workflows ran the action in the window; identify exposed secrets and rotate them immediately (PATs, cloud keys, npm tokens, RSA keys, etc.). [1][2]
  • Update: CISA notes it was patched in v46.0.1. [1]
  • Consider replacing with a hardened drop-in alternative (e.g., step-security/changed-files) and adopt best practices like pinning to commit SHAs and reducing token permissions. [2]

Key references: CISA Alert (CVE-2025-30066) [1], StepSecurity incident write-up/timeline [2], Wiz & Orca technical analyses [3][4].

Sources

[1] CISA alert on tj-actions/changed-files (CVE-2025-30066)
[2] StepSecurity: “Harden-Runner detection: tj-actions/changed-files action is compromised”
[3] Wiz: “GitHub Action tj-actions/changed-files supply chain attack (CVE-2025-30066)”
[4] Orca Security: “GitHub Action Hack: Malicious Commit in tj-actions/changed-files”


Supply-chain risk: reusable workflow pinned to 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. Although pinning to a commit SHA is the most secure option, specifying a tag is more convenient and is widely used; however, there is risk to this approach even if you trust the author, because a tag can be moved or deleted if a bad actor gains access to the repository. The same principles described above for using third-party actions also apply to using third-party workflows.

Using @master means any future commit to openwisp/openwisp-utils is picked up immediately with no review gate. This exact scenario occurred in March 2025 when the popular tj-actions/changed-files action was compromised — more than 23,000 Git repositories were affected when attackers pointed tags to a malicious commit that attempted to dump runner secrets.

Pin both uses: references (lines 22 and 37) to a full-length commit SHA and keep a human-readable comment alongside it:

🔒 Proposed fix
-    uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master
+    uses: openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@<full-commit-sha> # `@master`

Apply the same change on Line 37. Use Dependabot or Renovate to keep the pinned SHA up to date automatically.

🤖 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 in the reusable workflow usage by pinning both occurrences of
"openwisp/openwisp-utils/.github/workflows/reusable-backport.yml@master" to a
full-length commit SHA (use the commit SHA for the target revision) and add a
short human-readable comment next to each pinned SHA explaining why it’s pinned;
update both "uses:" entries so they reference the immutable commit SHA instead
of "@master" and rely on Dependabot/Renovate to keep the SHA current.

Comment on lines +30 to +36
if: >
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')
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Verify COLLABORATOR exclusion and remove the redundant state check

Two independent observations:

  1. Redundant guard (Line 34): github.event.issue.pull_request.merged_at != null already guarantees the PR was merged (and therefore closed), making github.event.issue.state == 'closed' a no-op. Removing it reduces noise:
♻️ Proposed simplification
     if: >
       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')
  1. COLLABORATOR exclusion (Line 35): Direct repository collaborators (author association COLLABORATOR) cannot trigger backports under the current check. Confirm this is intentional — external collaborators with commit access are commonly expected to have the same backport privileges as MEMBERs.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/backport.yml around lines 30 - 36, Remove the redundant
state check and include COLLABORATOR in the author association whitelist: update
the workflow conditional by removing the clause "github.event.issue.state ==
'closed'" (since merged_at != null already implies closed) and expand the JSON
array passed to contains(...) to include "COLLABORATOR" alongside "MEMBER" and
"OWNER" so the expression becomes
contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'),
github.event.comment.author_association); keep the existing merged_at and
startsWith(github.event.comment.body, '/backport') checks unchanged.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant