Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: automatically relate a backport PR to the backport issue #3255

Merged
merged 1 commit into from
Nov 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/backport-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Link-Backport-PR-Issue

on:
pull_request:
types: [opened]
branches:
- master
- "v*"

jobs:
check-backport:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Check if PR is a backport
run: |
if [[ "${{ github.event.pull_request.title }}" =~ "backport #" ]]; then
echo "BACKPORT=true" >> $GITHUB_ENV
else
echo "BACKPORT=false" >> $GITHUB_ENV
fi
Comment on lines +17 to +24
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Enhance security by properly handling untrusted input.

The PR title, which is user-controlled input, is being used directly in the shell script. This could potentially lead to command injection.

Apply this diff to handle the input more securely:

       - name: Check if PR is a backport
         run: |
-          if [[ "${{ github.event.pull_request.title }}" =~ "backport #" ]]; then
+          PR_TITLE='${{ github.event.pull_request.title }}'
+          if [[ "${PR_TITLE}" =~ backport[[:space:]]+#[0-9]+ ]]; then
             echo "BACKPORT=true" >> $GITHUB_ENV
           else
             echo "BACKPORT=false" >> $GITHUB_ENV
           fi
📝 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.

Suggested change
- name: Check if PR is a backport
run: |
if [[ "${{ github.event.pull_request.title }}" =~ "backport #" ]]; then
echo "BACKPORT=true" >> $GITHUB_ENV
else
echo "BACKPORT=false" >> $GITHUB_ENV
fi
- name: Check if PR is a backport
run: |
PR_TITLE='${{ github.event.pull_request.title }}'
if [[ "${PR_TITLE}" =~ backport[[:space:]]+#[0-9]+ ]]; then
echo "BACKPORT=true" >> $GITHUB_ENV
else
echo "BACKPORT=false" >> $GITHUB_ENV
fi
🧰 Tools
🪛 actionlint

18-18: shellcheck reported issue in this script: SC2086:info:2:27: Double quote to prevent globbing and word splitting

(shellcheck)


18-18: shellcheck reported issue in this script: SC2086:info:4:28: Double quote to prevent globbing and word splitting

(shellcheck)


18-18: "github.event.pull_request.title" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions for more details

(expression)

- name: Extract backport branch and issue number
if: env.BACKPORT == 'true'
run: |
# Extract branch from the target branch of the PR
BRANCH=$(echo "${{ github.event.pull_request.base.ref }}")
BRANCH=${BRANCH%.x} # Remove the '.x' suffix
BRANCH=$(echo "${BRANCH}" | sed 's/\./\\./g') # Escape periods
echo "BRANCH=$BRANCH" >> $GITHUB_ENV
# Extract issue number from the PR description
ORIGINAL_ISSUE_NUMBER=$(echo "${{ github.event.pull_request.body }}" | grep -oE 'issues/[0-9]+' | cut -d'/' -f2)
echo "ORIGINAL_ISSUE_NUMBER=$ORIGINAL_ISSUE_NUMBER" >> $GITHUB_ENV
Comment on lines +25 to +37
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and improve shell script robustness.

The current implementation lacks error handling and could be more robust:

  1. No validation of extracted issue number
  2. Shell commands could be improved
  3. Missing error handling for malformed PR body

Apply these improvements:

       - name: Extract backport branch and issue number
         if: env.BACKPORT == 'true'
         run: |
           # Extract branch from the target branch of the PR
-          BRANCH=$(echo "${{ github.event.pull_request.base.ref }}")
-          BRANCH=${BRANCH%.x}   # Remove the '.x' suffix
-          BRANCH=$(echo "${BRANCH}" | sed 's/\./\\./g')   # Escape periods
+          BRANCH="${{ github.event.pull_request.base.ref }}"
+          BRANCH="${BRANCH%.x}"   # Remove the '.x' suffix
+          BRANCH="${BRANCH//./\\.}"   # Escape periods
           echo "BRANCH=$BRANCH" >> $GITHUB_ENV

           # Extract issue number from the PR description
-          ORIGINAL_ISSUE_NUMBER=$(echo "${{ github.event.pull_request.body }}" | grep -oE 'issues/[0-9]+' | cut -d'/' -f2)
+          PR_BODY='${{ github.event.pull_request.body }}'
+          if [[ -z "${PR_BODY}" ]]; then
+            echo "Error: PR body is empty"
+            exit 1
+          fi
+          
+          ORIGINAL_ISSUE_NUMBER=$(echo "${PR_BODY}" | grep -oE 'issues/[0-9]+' | cut -d'/' -f2)
+          if [[ -z "${ORIGINAL_ISSUE_NUMBER}" ]]; then
+            echo "Error: Could not find original issue number in PR body"
+            exit 1
+          fi
+          
+          if ! [[ "${ORIGINAL_ISSUE_NUMBER}" =~ ^[0-9]+$ ]]; then
+            echo "Error: Invalid issue number format"
+            exit 1
+          fi
+          
           echo "ORIGINAL_ISSUE_NUMBER=$ORIGINAL_ISSUE_NUMBER" >> $GITHUB_ENV
📝 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.

Suggested change
- name: Extract backport branch and issue number
if: env.BACKPORT == 'true'
run: |
# Extract branch from the target branch of the PR
BRANCH=$(echo "${{ github.event.pull_request.base.ref }}")
BRANCH=${BRANCH%.x} # Remove the '.x' suffix
BRANCH=$(echo "${BRANCH}" | sed 's/\./\\./g') # Escape periods
echo "BRANCH=$BRANCH" >> $GITHUB_ENV
# Extract issue number from the PR description
ORIGINAL_ISSUE_NUMBER=$(echo "${{ github.event.pull_request.body }}" | grep -oE 'issues/[0-9]+' | cut -d'/' -f2)
echo "ORIGINAL_ISSUE_NUMBER=$ORIGINAL_ISSUE_NUMBER" >> $GITHUB_ENV
- name: Extract backport branch and issue number
if: env.BACKPORT == 'true'
run: |
# Extract branch from the target branch of the PR
BRANCH="${{ github.event.pull_request.base.ref }}"
BRANCH="${BRANCH%.x}" # Remove the '.x' suffix
BRANCH="${BRANCH//./\\.}" # Escape periods
echo "BRANCH=$BRANCH" >> $GITHUB_ENV
# Extract issue number from the PR description
PR_BODY='${{ github.event.pull_request.body }}'
if [[ -z "${PR_BODY}" ]]; then
echo "Error: PR body is empty"
exit 1
fi
ORIGINAL_ISSUE_NUMBER=$(echo "${PR_BODY}" | grep -oE 'issues/[0-9]+' | cut -d'/' -f2)
if [[ -z "${ORIGINAL_ISSUE_NUMBER}" ]]; then
echo "Error: Could not find original issue number in PR body"
exit 1
fi
if ! [[ "${ORIGINAL_ISSUE_NUMBER}" =~ ^[0-9]+$ ]]; then
echo "Error: Invalid issue number format"
exit 1
fi
echo "ORIGINAL_ISSUE_NUMBER=$ORIGINAL_ISSUE_NUMBER" >> $GITHUB_ENV
🧰 Tools
🪛 actionlint

27-27: shellcheck reported issue in this script: SC2116:style:2:8: Useless echo? Instead of 'cmd $(echo foo)', just use 'cmd foo'

(shellcheck)


27-27: shellcheck reported issue in this script: SC2001:style:4:10: See if you can use ${variable//search/replace} instead

(shellcheck)


27-27: shellcheck reported issue in this script: SC2086:info:5:26: Double quote to prevent globbing and word splitting

(shellcheck)


27-27: shellcheck reported issue in this script: SC2086:info:9:56: Double quote to prevent globbing and word splitting

(shellcheck)


27-27: "github.event.pull_request.body" is potentially untrusted. avoid using it directly in inline scripts. instead, pass it through an environment variable. see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions for more details

(expression)

- name: Get the original issue
if: env.BACKPORT == 'true'
id: original-issue
uses: octokit/[email protected]
with:
route: GET /repos/longhorn/longhorn/issues/${{ env.ORIGINAL_ISSUE_NUMBER }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: URL encode the original issue title
if: env.BACKPORT == 'true'
run: echo "ORIGINAL_ISSUE_TITLE=$(node -e 'console.log(encodeURIComponent("${{ fromJson(steps.original-issue.outputs.data).title }}"))')" >> $GITHUB_ENV

- name: Find corresponding backport issue number
if: env.BACKPORT == 'true'
run: |
BACKPORT_ISSUE_NUMBER=$(curl -s "https://api.github.com/search/issues?q=repo:longhorn/longhorn+is:open+is:issue+in:title+${{ env.BRANCH }}+${{ env.ORIGINAL_ISSUE_TITLE }}" | jq .items[0].number)
echo "BACKPORT_ISSUE_NUMBER=$BACKPORT_ISSUE_NUMBER" >> $GITHUB_ENV
Comment on lines +51 to +56
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve reliability of backport issue search.

The current implementation has several potential failure points:

  1. No handling of API errors
  2. No validation of search results
  3. No handling of API rate limits

Apply these improvements:

       - name: Find corresponding backport issue number
         if: env.BACKPORT == 'true'
         run: |
-          BACKPORT_ISSUE_NUMBER=$(curl -s "https://api.github.com/search/issues?q=repo:longhorn/longhorn+is:open+is:issue+in:title+${{ env.BRANCH }}+${{ env.ORIGINAL_ISSUE_TITLE }}" | jq .items[0].number)
+          SEARCH_RESPONSE=$(curl -s -w "%{http_code}" "https://api.github.com/search/issues?q=repo:longhorn/longhorn+is:open+is:issue+in:title+${{ env.BRANCH }}+${{ env.ORIGINAL_ISSUE_TITLE }}")
+          HTTP_CODE=${SEARCH_RESPONSE: -3}
+          RESPONSE_BODY=${SEARCH_RESPONSE::-3}
+          
+          if [ "$HTTP_CODE" != "200" ]; then
+            echo "Error: GitHub API request failed with status $HTTP_CODE"
+            echo "Response: $RESPONSE_BODY"
+            exit 1
+          fi
+          
+          ITEMS_COUNT=$(echo "$RESPONSE_BODY" | jq '.total_count')
+          if [ "$ITEMS_COUNT" -eq 0 ]; then
+            echo "Error: No matching backport issue found"
+            exit 1
+          elif [ "$ITEMS_COUNT" -gt 1 ]; then
+            echo "Warning: Multiple matching issues found, using the first one"
+          fi
+          
+          BACKPORT_ISSUE_NUMBER=$(echo "$RESPONSE_BODY" | jq '.items[0].number')
+          if [ "$BACKPORT_ISSUE_NUMBER" = "null" ]; then
+            echo "Error: Failed to extract issue number from response"
+            exit 1
+          fi
+          
           echo "BACKPORT_ISSUE_NUMBER=$BACKPORT_ISSUE_NUMBER" >> $GITHUB_ENV
📝 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.

Suggested change
- name: Find corresponding backport issue number
if: env.BACKPORT == 'true'
run: |
BACKPORT_ISSUE_NUMBER=$(curl -s "https://api.github.com/search/issues?q=repo:longhorn/longhorn+is:open+is:issue+in:title+${{ env.BRANCH }}+${{ env.ORIGINAL_ISSUE_TITLE }}" | jq .items[0].number)
echo "BACKPORT_ISSUE_NUMBER=$BACKPORT_ISSUE_NUMBER" >> $GITHUB_ENV
- name: Find corresponding backport issue number
if: env.BACKPORT == 'true'
run: |
SEARCH_RESPONSE=$(curl -s -w "%{http_code}" "https://api.github.com/search/issues?q=repo:longhorn/longhorn+is:open+is:issue+in:title+${{ env.BRANCH }}+${{ env.ORIGINAL_ISSUE_TITLE }}")
HTTP_CODE=${SEARCH_RESPONSE: -3}
RESPONSE_BODY=${SEARCH_RESPONSE::-3}
if [ "$HTTP_CODE" != "200" ]; then
echo "Error: GitHub API request failed with status $HTTP_CODE"
echo "Response: $RESPONSE_BODY"
exit 1
fi
ITEMS_COUNT=$(echo "$RESPONSE_BODY" | jq '.total_count')
if [ "$ITEMS_COUNT" -eq 0 ]; then
echo "Error: No matching backport issue found"
exit 1
elif [ "$ITEMS_COUNT" -gt 1 ]; then
echo "Warning: Multiple matching issues found, using the first one"
fi
BACKPORT_ISSUE_NUMBER=$(echo "$RESPONSE_BODY" | jq '.items[0].number')
if [ "$BACKPORT_ISSUE_NUMBER" = "null" ]; then
echo "Error: Failed to extract issue number from response"
exit 1
fi
echo "BACKPORT_ISSUE_NUMBER=$BACKPORT_ISSUE_NUMBER" >> $GITHUB_ENV
🧰 Tools
🪛 actionlint

53-53: shellcheck reported issue in this script: SC2086:info:2:56: Double quote to prevent globbing and word splitting

(shellcheck)

- name: Link the PR with the corresponding backport issue
if: env.BACKPORT == 'true'
run: |
# Relate the pull request to the backport issue
gh issue comment --repo longhorn/longhorn ${{ env.BACKPORT_ISSUE_NUMBER }} --body "Related PR: ${{ github.event.pull_request.html_url }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}