diff --git a/.github/scripts/handle_warning_violations.sh b/.github/scripts/handle_warning_violations.sh index 8fd0018290..48a91c3b76 100755 --- a/.github/scripts/handle_warning_violations.sh +++ b/.github/scripts/handle_warning_violations.sh @@ -11,16 +11,21 @@ fi VIOLATION_DETAILS="" if [ -f "tools/spectral/ipa/metrics/outputs/warning-violations.json" ]; then VIOLATION_DETAILS=$(jq -r ' - group_by(.code) | - map("• " + .[0].code + " (" + (length | tostring) + " violations)") | - join("\n") + group_by(.code) | + map( + "• " + .[0].code + " (" + (length | tostring) + " violations):\n" + + (map(" - " + .component_id) | join("\n")) + ) | + join("\n\n") ' tools/spectral/ipa/metrics/outputs/warning-violations.json) fi # Check if warning ticket already exists echo "Check if a jira ticket already exists." -EXISTING_TICKET=$(curl -H "Authorization: Bearer ${JIRA_API_TOKEN}" \ - "https://jira.mongodb.org/rest/api/2/search?jql=project=CLOUDP AND summary~'Warning-level IPA violations' AND status!=Done" \ +JQL_QUERY="project=CLOUDP AND summary~'Warning-level IPA violations' AND status NOT IN (Done, Resolved, Closed)" +EXISTING_TICKET=$(curl -G -H "Authorization: Bearer ${JIRA_API_TOKEN}" \ + --data-urlencode "jql=${JQL_QUERY}" \ + "https://jira.mongodb.org/rest/api/2/search" \ | jq -r '.issues[0].key // empty') if [ -n "${EXISTING_TICKET}" ]; then @@ -39,45 +44,70 @@ ${VIOLATION_DETAILS} Total violations: ${WARNING_COUNT}" -echo "Jira ticket does not exists. Creating..." -# Create new Jira ticket -TICKET_RESPONSE=$(curl -X POST -H "Authorization: Bearer ${JIRA_API_TOKEN}" \ - -H "Content-Type: application/json" \ - -d "{ - \"fields\": { - \"project\": {\"key\": \"CLOUDP\"}, - \"summary\": \"Warning-level IPA violations found\", - \"description\": \"${DESCRIPTION}\", - \"issuetype\": {\"name\": \"Task\"}, - \"assignee\": {\"id\": \"${TEAM_ID}\"} +echo "Jira ticket does not exist. Creating..." +# Create new Jira ticket with properly escaped JSON (matching create_jira_ticket.sh format) +TICKET_PAYLOAD=$(jq -n \ + --arg summary "Warning-level IPA violations found" \ + --arg description "$DESCRIPTION" \ + --arg teamId "$TEAM_ID" \ + '{ + fields: { + project: {id: "10984"}, + summary: $summary, + description: $description, + issuetype: {id: "12"}, + customfield_12751: [{id: $teamId}], + components: [{id: "35986"}] } - }" \ + }') + +echo "Jira ticket payload:" +echo "${TICKET_PAYLOAD}" + +TICKET_RESPONSE=$(echo "${TICKET_PAYLOAD}" | curl -X POST -H "Authorization: Bearer ${JIRA_API_TOKEN}" \ + -H "Content-Type: application/json" \ + -d @- \ "https://jira.mongodb.org/rest/api/2/issue/") -TICKET_KEY=$(echo "${TICKET_RESPONSE}" | jq -r '.key') -if [ "${TICKET_KEY}" != "null" ]; then +echo "Jira API response:" +echo "${TICKET_RESPONSE}" + +TICKET_KEY=$(echo "${TICKET_RESPONSE}" | jq -r '.key // empty') +if [ -n "${TICKET_KEY}" ] && [ "${TICKET_KEY}" != "null" ]; then echo "Created Jira ticket: ${TICKET_KEY}." - # Create summary for Slack - echo "Creating Slack Summary with VIOLATION_DETAILS: ${VIOLATION_DETAILS}..." - SLACK_SUMMARY="" - if [ -n "${VIOLATION_DETAILS}" ]; then - SLACK_SUMMARY=$(echo "${VIOLATION_DETAILS}" | head -3) - if [ "$(echo "${VIOLATION_DETAILS}" | wc -l)" -gt 3 ]; then - SLACK_SUMMARY="${SLACK_SUMMARY}\n... and more" - fi - fi echo "Send Slack notification..." - # Send Slack notification with violation summary + # Send Slack notification with link to Jira ticket for details SLACK_MESSAGE="Warning-level IPA violations found (${WARNING_COUNT} violations) (${SLACK_ONCALL_USER}). -Jira ticket: https://jira.mongodb.org/browse/${TICKET_KEY}" - - curl -X POST -H "Authorization: Bearer ${SLACK_BEARER_TOKEN}" \ +See Jira ticket for details: https://jira.mongodb.org/browse/${TICKET_KEY}" + + SLACK_RESPONSE=$(curl -X POST -H "Authorization: Bearer ${SLACK_BEARER_TOKEN}" \ -H "Content-type: application/json" \ --data "{\"channel\":\"${SLACK_CHANNEL_ID}\",\"text\":\"${SLACK_MESSAGE}\"}" \ - https://slack.com/api/chat.postMessage + https://slack.com/api/chat.postMessage) + + echo "Slack API response: ${SLACK_RESPONSE}" + + SLACK_OK=$(echo "${SLACK_RESPONSE}" | jq -r '.ok') + if [ "${SLACK_OK}" != "true" ]; then + SLACK_ERROR=$(echo "${SLACK_RESPONSE}" | jq -r '.error') + echo "Warning: Failed to send Slack notification. Error: ${SLACK_ERROR}" + + if [ "${SLACK_ERROR}" == "not_in_channel" ]; then + echo "The Slack bot is not a member of channel ${SLACK_CHANNEL_ID}." + echo "Please invite the bot to the channel or update SLACK_CHANNEL_ID." + fi + + # Don't fail the script - Jira ticket was created successfully + echo "Continuing despite Slack notification failure..." + else + echo "Slack notification sent successfully." + fi else echo "Failed to create Jira ticket" + echo "Response: ${TICKET_RESPONSE}" + ERROR_MESSAGES=$(echo "${TICKET_RESPONSE}" | jq -r '.errorMessages[]? // .errors? // "No error details available"' 2>/dev/null || echo "Could not parse error response") + echo "Error details: ${ERROR_MESSAGES}" exit 1 fi diff --git a/.github/workflows/release-IPA-metrics.yml b/.github/workflows/release-IPA-metrics.yml index 68f940837c..b55cc06992 100644 --- a/.github/workflows/release-IPA-metrics.yml +++ b/.github/workflows/release-IPA-metrics.yml @@ -65,7 +65,7 @@ jobs: working-directory: ${{ github.workspace }} - name: Upload OAS files as artifacts - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f with: name: oas-files path: | @@ -81,6 +81,13 @@ jobs: node runMetricCollection.js "${{ github.workspace }}/v2-filtered.json" echo "WARNING_COUNT=$(cat ../outputs/warning-count.txt)" >> "$GITHUB_ENV" + - name: Upload Warning Violations as Artifact + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f + with: + name: warning-violations + path: tools/spectral/ipa/metrics/outputs/warning-violations.json + retention-days: 1 + - name: aws configure uses: aws-actions/configure-aws-credentials@v5 with: diff --git a/tools/spectral/ipa/__tests__/metrics/metricCollection.test.js b/tools/spectral/ipa/__tests__/metrics/metricCollection.test.js index 37ffdc1af7..6e67c17b4d 100644 --- a/tools/spectral/ipa/__tests__/metrics/metricCollection.test.js +++ b/tools/spectral/ipa/__tests__/metrics/metricCollection.test.js @@ -45,6 +45,7 @@ describe('tools/spectral/ipa/metrics/metricCollection.js runMetricCollectionJob' const violations = [ { code: 'xgen-IPA-104-valid-operation-id-warn', + component_id: 'paths./api/atlas/v2/federationSettings/{federationSettingsId}/connectedOrgConfigs/{orgId}.get', }, ]; expect(results.warnings.violations).toEqual(violations); diff --git a/tools/spectral/ipa/metrics/metricCollection.js b/tools/spectral/ipa/metrics/metricCollection.js index 0a8466453b..158836c71e 100644 --- a/tools/spectral/ipa/metrics/metricCollection.js +++ b/tools/spectral/ipa/metrics/metricCollection.js @@ -38,6 +38,7 @@ export async function runMetricCollectionJob( const processedWarnings = warningViolations.map((violation) => ({ code: violation.ipa_rule, + component_id: violation.component_id, })); console.log(`Found ${warningViolations.length} warning-level violations`);