Skip to content
Draft
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
124 changes: 124 additions & 0 deletions .github/workflows/ticket-issue-number-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: ticket-issue-number-sync

on:
pull_request:
types: [opened, synchronize]

jobs:
ticket-issue-number-sync:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Extract JIRA ticket number from PR title
id: extract_ticket
run: |
# Extract JIRA ticket number from PR title (e.g., "fix(BA-1234): aaaa" -> "BA-1234")
TITLE="${{ github.event.pull_request.title }}"
echo "PR Title: $TITLE"

# Extract ticket number using regex pattern BA-XXXX format
TICKET_NUMBER=$(echo "$TITLE" | grep -oE 'BA-[0-9]+' | head -1)

if [ -n "$TICKET_NUMBER" ]; then
echo "Extracted ticket: $TICKET_NUMBER"
echo "ticket_number=$TICKET_NUMBER" >> $GITHUB_OUTPUT
echo "has_ticket=true" >> $GITHUB_OUTPUT
else
echo "No JIRA ticket number found in PR title"
echo "has_ticket=false" >> $GITHUB_OUTPUT
fi

- name: Get GitHub Issue URL from JIRA
if: steps.extract_ticket.outputs.has_ticket == 'true'
id: get_jira_issue
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USERNAME: ${{ secrets.JIRA_USERNAME }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
run: |
TICKET_NUMBER="${{ steps.extract_ticket.outputs.ticket_number }}"
echo "Fetching GitHub Issue URL for JIRA ticket: $TICKET_NUMBER"

# Get ticket information through JIRA API
JIRA_RESPONSE=$(curl -s -u "$JIRA_USERNAME:$JIRA_API_TOKEN" \
-H "Accept: application/json" \
"$JIRA_BASE_URL/rest/api/3/issue/$TICKET_NUMBER")

echo "JIRA API Response: $JIRA_RESPONSE"

# Extract issue number from GitHub Issue URL field
# Search for fields containing GitHub issue URLs (customfield_* or regular fields)
GITHUB_ISSUE_URL=$(echo "$JIRA_RESPONSE" | jq -r '
.fields
| to_entries[]
| select(.value != null and .value != "")
| select(
(.value | type == "string" and test("github.com/.*/issues/[0-9]+"))
)
| .value
' 2>/dev/null | head -1)

# Fail immediately if GitHub Issue URL is not found
if [ -z "$GITHUB_ISSUE_URL" ] || [ "$GITHUB_ISSUE_URL" = "null" ]; then
echo "❌ No GitHub Issue URL found in JIRA ticket $TICKET_NUMBER"
echo "Available fields (first 20):"
echo "$JIRA_RESPONSE" | jq -r '.fields | keys[]' 2>/dev/null | head -20
exit 1
fi

echo "Found GitHub Issue URL: $GITHUB_ISSUE_URL"
# Extract GitHub issue number (e.g., https://github.com/owner/repo/issues/123 -> 123)
GITHUB_ISSUE_NUMBER=$(echo "$GITHUB_ISSUE_URL" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+' | head -1)

if [ -n "$GITHUB_ISSUE_NUMBER" ]; then
echo "✅ Extracted GitHub Issue Number: $GITHUB_ISSUE_NUMBER"
echo "github_issue_number=$GITHUB_ISSUE_NUMBER" >> $GITHUB_OUTPUT
echo "has_github_issue=true" >> $GITHUB_OUTPUT
else
echo "❌ Could not extract issue number from GitHub Issue URL: $GITHUB_ISSUE_URL"
echo "Please verify the GitHub Issue URL format is correct (expected: https://github.com/owner/repo/issues/NUMBER)"
exit 1
fi

- name: Update PR body with resolves clause
if: steps.extract_ticket.outputs.has_ticket == 'true' && steps.get_jira_issue.outputs.has_github_issue == 'true'
env:
TICKET_NUMBER: ${{ steps.extract_ticket.outputs.ticket_number }}
GITHUB_ISSUE_NUMBER: ${{ steps.get_jira_issue.outputs.github_issue_number }}
run: |
echo "Using GitHub issue number: $GITHUB_ISSUE_NUMBER from JIRA"

# Get current PR body
PR_BODY=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | \
jq -r '.body // ""')

echo "Current PR body: $PR_BODY"

# Generate resolves clause
RESOLVES_CLAUSE="resolves #$GITHUB_ISSUE_NUMBER ($TICKET_NUMBER)"
echo "Generated resolves clause: $RESOLVES_CLAUSE"

# Replace existing resolves clause or add new one
if echo "$PR_BODY" | grep -qiE "resolves #[0-9]+ ?\("; then
# Replace existing resolves clause (case-insensitive)
NEW_BODY=$(echo "$PR_BODY" | sed -E "s/[Rr]esolves #[0-9]+ ?\([^)]+\)/$RESOLVES_CLAUSE/g")
echo "Replaced existing resolves clause"
else
# Add new resolves clause at the beginning
NEW_BODY=$(printf "%s\n\n%s" "$RESOLVES_CLAUSE" "$PR_BODY")
echo "Added new resolves clause"
fi

# Update PR body
curl -s -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" \
-d "{\"body\": $(echo "$NEW_BODY" | jq -R -s .)}"

echo "✅ Added resolves clause: $RESOLVES_CLAUSE"
Comment on lines +9 to +124

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI 4 months ago

To fix this, add an explicit permissions block so the GITHUB_TOKEN used by this workflow follows the principle of least privilege. This workflow needs to read PR metadata and update the PR body via the GitHub API, which maps to pull-requests: write. It does not need to push commits or modify repository contents, so contents can be limited to read. The cleanest fix is to add a job-level permissions block under the ticket-issue-number-sync job, above runs-on. This keeps the scope tight and avoids affecting other workflows.

Concretely, in .github/workflows/ticket-issue-number-sync.yml, under jobs:, inside the ticket-issue-number-sync: job, insert:

permissions:
  contents: read
  pull-requests: write

indented to match other job keys. No imports or additional methods are required, since this is purely a workflow configuration change.

Suggested changeset 1
.github/workflows/ticket-issue-number-sync.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/ticket-issue-number-sync.yml b/.github/workflows/ticket-issue-number-sync.yml
--- a/.github/workflows/ticket-issue-number-sync.yml
+++ b/.github/workflows/ticket-issue-number-sync.yml
@@ -6,6 +6,9 @@
 
 jobs:
   ticket-issue-number-sync:
+    permissions:
+      contents: read
+      pull-requests: write
     runs-on: ubuntu-latest
     steps:
     - name: Checkout code
EOF
@@ -6,6 +6,9 @@

jobs:
ticket-issue-number-sync:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout code
Copilot is powered by AI and may make mistakes. Always verify output.
Loading