What changed, and why it matters
This commit adds a GitHub Actions automation script that helps developers copy approved code changes from the main development branch to older release branches. It is purely a process improvement for maintainers and does not change any wallet, networking, or cryptographic code in the LND application itself.
No security action is required. As a routine hardening suggestion, maintainers may periodically review the pinned backport-action hash and its release notes, ensure branch protection rules on release branches still require the usual review/CI checks, and confirm that the GITHUB_TOKEN permissions are scoped only to what the workflow needs.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit introduces .github/workflows/backport.yml, a pull_request_target workflow that triggers on merged PRs carrying labels matching ‘backport-v*’. It validates that the referenced release branches exist and then invokes the pinned third-party action korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997 to cherry-pick the original PR onto each target branch and open new backport PRs. The workflow requests contents:write and pull-requests:write permissions and uses the repository’s built-in GITHUB_TOKEN. No LND source code, build scripts, or runtime configuration are modified.
Changed components
.github/workflows/backport.ymlInspect captured patch +121 / −0
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
new file mode 100644
index 0000000..f8bc580
--- /dev/null
+++ b/.github/workflows/backport.yml
@@ -0,0 +1,121 @@
+name: Backport
+
+on:
+ pull_request_target:
+ types: [closed, labeled]
+
+permissions:
+ contents: write
+ pull-requests: write
+ issues: read
+
+jobs:
+ backport:
+ name: Backport PR
+ runs-on: ubuntu-latest
+ # Only run on merged PRs with backport labels.
+ # Labels must match pattern: backport-v* (e.g., backport-v0.20.x-branch).
+ # This excludes labels like "backport candidate" or "backport-candidate".
+ if: |
+ github.event.pull_request.merged == true &&
+ contains(join(github.event.pull_request.labels.*.name, ','), 'backport-v')
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.base.ref }}
+
+ - name: Validate target branches exist
+ id: validate
+ shell: bash
+ run: |
+ # Extract all backport labels
+ labels='${{ toJSON(github.event.pull_request.labels.*.name) }}'
+ echo "All labels: $labels"
+
+ # Parse labels and extract branch names
+ # Only match labels starting with "backport-v" to exclude labels like
+ # "backport candidate" or "backport-candidate"
+ backport_labels=$(echo "$labels" | jq -r '.[] | select(startswith("backport-v"))')
+
+ if [ -z "$backport_labels" ]; then
+ echo "::error::No valid backport labels found (must start with 'backport-v')"
+ exit 1
+ fi
+
+ echo "Found backport labels:"
+ echo "$backport_labels"
+
+ # Check each target branch exists
+ missing_branches=()
+ valid_branches=()
+ while IFS= read -r label; do
+ # Extract branch name (everything after "backport-")
+ branch_name="${label#backport-}"
+ echo "Checking if branch exists: $branch_name"
+
+ # Check if branch exists in remote
+ if ! git ls-remote --heads origin "$branch_name" | grep -q "$branch_name"; then
+ echo "::warning::Target branch '$branch_name' does not exist (from label '$label')"
+ missing_branches+=("$branch_name")
+ else
+ echo "✓ Branch '$branch_name' exists"
+ valid_branches+=("$branch_name")
+ fi
+ done <<< "$backport_labels"
+
+ # Report validation results
+ if [ ${#missing_branches[@]} -gt 0 ]; then
+ echo "::warning::The following target branches do not exist and will be skipped: ${missing_branches[*]}"
+ echo "::warning::Please check the branch names or create the branches before retrying"
+ fi
+
+ # Only fail if ALL branches are invalid
+ if [ ${#valid_branches[@]} -eq 0 ]; then
+ echo "::error::No valid target branches found. All backport labels reference non-existent branches."
+ exit 1
+ fi
+
+ echo "✓ Found ${#valid_branches[@]} valid target branch(es): ${valid_branches[*]}"
+ if [ ${#missing_branches[@]} -gt 0 ]; then
+ echo "⚠ Skipping ${#missing_branches[@]} invalid branch(es): ${missing_branches[*]}"
+ fi
+
+ - name: Create backport PRs
+ # Uses version v3.4, we pin to a hash here. For more details to
+ # available versions, see:
+ # https://github.com/korthout/backport-action/releases.
+ uses: korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997
+ with:
+ # Automatically detect target branches from labels.
+ # Labels must be in format: backport-v0.20.x-branch (must start
+ # with "backport-v"). This excludes labels like "backport candidate"
+ # or "backport-candidate". The pattern extracts everything after
+ # "backport-" as the branch name.
+ label_pattern: '^backport-(v.+)$'
+
+ # GitHub token for creating PRs.
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+
+ # PR title format - shows it's a backport with original PR number.
+ pull_title: '[${target_branch}] Backport #${pull_number}: ${pull_title}'
+
+ # PR description template - links back to original PR.
+ pull_description: |-
+ Backport of #${pull_number}
+
+ ---
+
+ ${pull_description}
+
+ # Automatically add labels to backport PRs.
+ # The 'no-changelog' label skips the release notes check in CI.
+ labels: no-changelog
+
+ # Merge strategy - skip merge commits, use cherry-pick only.
+ merge_commits: skip
+
+ # If conflicts occur, create a draft PR with conflict markers.
+ experimental: '{"conflict_resolution": "draft_commit_conflicts"}'
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.