diff --git a/.github/workflows/jira-ticket-check.yaml b/.github/workflows/jira-ticket-check.yaml index 5319428..7b01cd2 100644 --- a/.github/workflows/jira-ticket-check.yaml +++ b/.github/workflows/jira-ticket-check.yaml @@ -120,14 +120,15 @@ jobs: id: pr-description-check if: steps.pr-title-check.outputs.ticket == '' run: | - PR_BODY="${{ github.event.pull_request.body }}" + # Use printf instead of echo to safely handle special characters + PR_BODY=$(printf '%s' "${{ github.event.pull_request.body }}") JIRA_PROJECT_PATTERN="${{ inputs.jira-project-pattern }}" if [ -z "$JIRA_PROJECT_PATTERN" ]; then JIRA_PROJECT_PATTERN="[A-Za-z]+" else # Make pattern case-insensitive by adding both cases if it's a simple pattern # For complex patterns, rely on grep -i flag - JIRA_PROJECT_PATTERN=$(echo "$JIRA_PROJECT_PATTERN" | sed 's/\[A-Z\]\+/[A-Za-z]+/g' | sed 's/\[A-Z\]/[A-Za-z]/g') + JIRA_PROJECT_PATTERN=$(printf '%s' "$JIRA_PROJECT_PATTERN" | sed 's/\[A-Z\]\+/[A-Za-z]+/g' | sed 's/\[A-Z\]/[A-Za-z]/g') fi JIRA_PATTERN="${JIRA_PROJECT_PATTERN}-[0-9]+" @@ -137,11 +138,11 @@ jobs: exit 0 fi - # Case-insensitive search - if echo "$PR_BODY" | grep -qiE "$JIRA_PATTERN"; then - TICKET=$(echo "$PR_BODY" | grep -oiE "$JIRA_PATTERN" | head -1) + # Case-insensitive search - use printf to safely pass content to grep + if printf '%s' "$PR_BODY" | grep -qiE "$JIRA_PATTERN"; then + TICKET=$(printf '%s' "$PR_BODY" | grep -oiE "$JIRA_PATTERN" | head -1) # Normalize to uppercase for Jira API (Jira ticket keys are uppercase) - TICKET=$(echo "$TICKET" | tr '[:lower:]' '[:upper:]') + TICKET=$(printf '%s' "$TICKET" | tr '[:lower:]' '[:upper:]') echo "ticket=$TICKET" >> $GITHUB_OUTPUT echo "found_in=pr_description" >> $GITHUB_OUTPUT echo "✅ Found Jira ticket in PR description: $TICKET" @@ -179,11 +180,11 @@ jobs: # Get all commit messages between base and head COMMIT_MESSAGES=$(git log --pretty=format:"%s" ${BASE_SHA}..${HEAD_SHA} 2>/dev/null || echo "") - # Case-insensitive search - if [ -n "$COMMIT_MESSAGES" ] && echo "$COMMIT_MESSAGES" | grep -qiE "$JIRA_PATTERN"; then - TICKET=$(echo "$COMMIT_MESSAGES" | grep -oiE "$JIRA_PATTERN" | head -1) + # Case-insensitive search - use printf to safely pass content to grep + if [ -n "$COMMIT_MESSAGES" ] && printf '%s' "$COMMIT_MESSAGES" | grep -qiE "$JIRA_PATTERN"; then + TICKET=$(printf '%s' "$COMMIT_MESSAGES" | grep -oiE "$JIRA_PATTERN" | head -1) # Normalize to uppercase for Jira API (Jira ticket keys are uppercase) - TICKET=$(echo "$TICKET" | tr '[:lower:]' '[:upper:]') + TICKET=$(printf '%s' "$TICKET" | tr '[:lower:]' '[:upper:]') echo "ticket=$TICKET" >> $GITHUB_OUTPUT echo "found_in=commits" >> $GITHUB_OUTPUT echo "✅ Found Jira ticket in commit messages: $TICKET" @@ -294,53 +295,67 @@ jobs: echo "🔍 Verifying ticket $TICKET exists in Jira..." - # Construct URL and validate it - API_URL="https://${JIRA_INSTANCE}/rest/api/3/issue/${TICKET}" + # Construct URL and validate it - only request fields we need (status) to avoid processing ticket description + API_URL="https://${JIRA_INSTANCE}/rest/api/3/issue/${TICKET}?fields=status" # Make API request to check if ticket exists # Force HTTP/1.1 to avoid HTTP/2 issues that can cause "Failed sending HTTP request" - BODY=$(curl -s \ + # Use a temporary file to safely store the response + TEMP_FILE=$(mktemp) + HTTP_CODE=$(curl -s \ --http1.1 \ -X GET \ -H "Authorization: Basic ${AUTH_STRING}" \ -H "Accept: application/json" \ --max-time 30 \ - "${API_URL}" 2>&1) + -w "%{http_code}" \ + -o "${TEMP_FILE}" \ + "${API_URL}" 2>&1 | tail -1) + + # Read response body from temp file + BODY=$(cat "${TEMP_FILE}" 2>/dev/null || echo "") + rm -f "${TEMP_FILE}" - # Check if response indicates ticket doesn't exist (404 error in JSON) - if echo "$BODY" | grep -qiE '"errorMessages"|"statusCode":\s*404'; then + # Check HTTP status code first + if [ "$HTTP_CODE" = "404" ]; then echo "❌ Ticket $TICKET does not exist in Jira" echo "exists=false" >> $GITHUB_OUTPUT exit 1 fi - # Check if response indicates authentication failure (401/403 in JSON) - if echo "$BODY" | grep -qiE '"statusCode":\s*(401|403)'; then + if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then echo "⚠️ Authentication failed or insufficient permissions to verify ticket" echo "⚠️ Continuing without verification..." echo "exists=false" >> $GITHUB_OUTPUT exit 0 fi + # Check if response indicates ticket doesn't exist (error in JSON) + if echo "$BODY" | grep -qiE '"errorMessages"'; then + echo "❌ Ticket $TICKET does not exist in Jira" + echo "exists=false" >> $GITHUB_OUTPUT + exit 1 + fi + # If we get here, assume the ticket exists and try to extract status echo "✅ Ticket $TICKET exists in Jira" echo "exists=true" >> $GITHUB_OUTPUT - # Extract status from Jira API response (status is nested: fields.status.name) - # Try using jq first (if available), then fall back to grep/sed + # Extract status from Jira API response using jq (safest method) + # Use --raw-output to get plain text, and handle errors properly if command -v jq >/dev/null 2>&1; then - STATUS=$(echo "$BODY" | jq -r '.fields.status.name // empty' 2>/dev/null || echo "") + STATUS=$(printf '%s' "$BODY" | jq -r '.fields.status.name // empty' 2>/dev/null || echo "") fi + # Fallback: extract status using grep/sed pattern matching (only if jq fails) if [ -z "$STATUS" ]; then - # Fallback: extract status using grep/sed pattern matching - # Look for "status" object followed by "name" field - STATUS=$(echo "$BODY" | grep -o '"status"[^}]*"name":"[^"]*' | sed 's/.*"name":"\([^"]*\)".*/\1/' | head -1 || echo "") + # Use printf instead of echo to avoid interpretation of escape sequences + STATUS=$(printf '%s' "$BODY" | grep -o '"status"[^}]*"name":"[^"]*' | sed 's/.*"name":"\([^"]*\)".*/\1/' | head -1 || echo "") fi if [ -z "$STATUS" ]; then # Alternative: look for any "name" field that appears after "status" in the JSON - STATUS=$(echo "$BODY" | sed -n 's/.*"status"[^}]*"name":"\([^"]*\)".*/\1/p' | head -1 || echo "") + STATUS=$(printf '%s' "$BODY" | sed -n 's/.*"status"[^}]*"name":"\([^"]*\)".*/\1/p' | head -1 || echo "") fi # Normalize status to lowercase for comparison diff --git a/.github/workflows/slack-deploy-notification.yaml b/.github/workflows/slack-deploy-notification.yaml index b86f269..c8d4db1 100644 --- a/.github/workflows/slack-deploy-notification.yaml +++ b/.github/workflows/slack-deploy-notification.yaml @@ -36,14 +36,13 @@ jobs: with: payload: | { - "channel": "#release", "text": "${{ github.event.repository.name }} deployed", "blocks": [ { "type": "section", "text": { "type": "mrkdwn", - "text": "*${{ github.event.repository.name }} deployed by ${{ github.triggering_actor }}*\n\tView the <${{ inputs.apm_url }}|Service APM>" + "text": "*${{ github.event.repository.name }} deployed by ${{ github.triggering_actor }}*\n\tView the <${{ inputs.dashboard_url }}|Deployment>\n\tView the <${{ inputs.apm_url }}|Service APM>" }, "accessory": { "type": "button",