Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 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
108 changes: 108 additions & 0 deletions .github/scripts/handle_warning_violations.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/bin/bash
set -eou pipefail

WARNING_COUNT=$1
TEAM_ID=$2
JIRA_API_TOKEN=$3
SLACK_BEARER_TOKEN=$4
SLACK_CHANNEL_ID=$5
ONCALL_USER=$6
DRY_RUN=${7:-false} # Optional 7th parameter for dry run

if [ "$WARNING_COUNT" -eq 0 ]; then
echo "No warning violations found, skipping ticket creation"
exit 0
fi

# Read violation details if available
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")
' tools/spectral/ipa/metrics/outputs/warning-violations.json)
fi

if [ "$DRY_RUN" = "true" ]; then
echo "=== DRY RUN MODE ==="
echo "Would create Jira ticket with:"
echo "Summary: Warning-level IPA violations found"
echo "Description:"
echo "Warning-level violations were found during IPA validation. Please review and add exceptions if valid, or address false positives.
Violation Summary:
$VIOLATION_DETAILS
Total violations: $WARNING_COUNT"
echo ""
echo "Would send Slack message:"
SLACK_SUMMARY=$(echo "$VIOLATION_DETAILS" | head -3)
if [ "$(echo "$VIOLATION_DETAILS" | wc -l)" -gt 3 ]; then
SLACK_SUMMARY="$SLACK_SUMMARY\n... and more"
fi
echo "Warning-level IPA violations found ($WARNING_COUNT violations) ($ONCALL_USER).
Jira ticket: [DRY RUN - no ticket created]"
exit 0
fi

# Check if warning ticket already exists
EXISTING_TICKET=$(curl -s -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" \
| jq -r '.issues[0].key // empty')

if [ -n "$EXISTING_TICKET" ]; then
echo "Warning ticket already exists: $EXISTING_TICKET"
exit 0
fi

# Create detailed description
DESCRIPTION="Warning-level violations were found during IPA validation. Please review and add exceptions if valid, or address false positives.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe we can link to the IPA wiki with the rollout process?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added! Let me know how it sounds

Violation Summary:
$VIOLATION_DETAILS
Total violations: $WARNING_COUNT"

# Create new Jira ticket
TICKET_RESPONSE=$(curl -s -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\"}
}
}" \
"https://jira.mongodb.org/rest/api/2/issue/")

TICKET_KEY=$(echo "$TICKET_RESPONSE" | jq -r '.key')

if [ "$TICKET_KEY" != "null" ]; then
echo "Created Jira ticket: $TICKET_KEY"

# Create summary for Slack
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

# Send Slack notification with violation summary
SLACK_MESSAGE="Warning-level IPA violations found ($WARNING_COUNT violations) ($ONCALL_USER).
Jira ticket: https://jira.mongodb.org/browse/$TICKET_KEY"

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
else
echo "Failed to create Jira ticket"
exit 1
fi
23 changes: 22 additions & 1 deletion .github/workflows/release-IPA-metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@ jobs:
working-directory: ${{ github.workspace }}

- name: Run Metric Collection Job
id: metric-collection
working-directory: tools/spectral/ipa/metrics/scripts
run: node runMetricCollection.js "${{ github.workspace }}/v2.json"
run: |
node runMetricCollection.js "${{ github.workspace }}/v2.json"
if [ -f "../outputs/warning-count.txt" ]; then
warning_count=$(cat "../outputs/warning-count.txt")
echo "warning_count=${warning_count}" >> "$GITHUB_OUTPUT"
else
echo "warning_count=0" >> "$GITHUB_OUTPUT"
fi

- name: aws configure
uses: aws-actions/configure-aws-credentials@v4
Expand All @@ -54,6 +62,19 @@ jobs:
working-directory: tools/spectral/ipa/metrics/scripts
run: node dataDump.js

- name: Handle Warning Violations
if: ${{ steps.metric-collection.outputs.warning_count > 0 }}
env:
WARNING_COUNT: ${{ steps.metric-collection.outputs.warning_count }}
TEAM_ID: ${{ vars.JIRA_TEAM_ID_APIX_PLATFORM }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
SLACK_BEARER_TOKEN: ${{ secrets.SLACK_BEARER_TOKEN }}
SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID_APIX_PLATFORM_DEV }}
SLACK_ONCALL_USER: ${{ secrets.SLACK_APIX_PLATFORM_ONCALL_USER }}
run: |
chmod +x .github/scripts/handle_warning_violations.sh
.github/scripts/handle_warning_violations.sh "$WARNING_COUNT" "$TEAM_ID" "$JIRA_API_TOKEN" "$SLACK_BEARER_TOKEN" "$SLACK_CHANNEL_ID" "$SLACK_ONCALL_USER"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Q: Do we need the chmod +x?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We might not need it, because I will already commit the execute permission. Let me remove and try that way

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Removed


failure-handler:
name: Failure Handler
needs: [ release-IPA-metrics ]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"violations": [],
"violations": [
{
"componentId": "paths./api/atlas/v2/federationSettings/{federationSettingsId}/connectedOrgConfigs/{orgId}.get",
"ruleName": "xgen-IPA-104-valid-operation-id"
}],
"adoptions": [
{
"componentId": "paths./api/atlas/v2",
Expand Down
1,762 changes: 1,761 additions & 1 deletion tools/spectral/ipa/__tests__/metrics/data/expected-metric-results.json

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions tools/spectral/ipa/__tests__/metrics/metricCollection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ describe('tools/spectral/ipa/metrics/metricCollection.js runMetricCollectionJob'
const results = await runMetricCollectionJob(testConfig, spectral);

expect(results).not.toBe(undefined);
expect(results.length).toEqual(expectedResults.length);

results.forEach((entry, index) => {
expect(results.metrics.length).toEqual(expectedResults.length);
results.metrics.forEach((entry, index) => {
const expectedEntry = getEntry(expectedResults, entry['component_id'], entry['ipa_rule']);
expect(entry['component_id']).toEqual(expectedEntry['component_id']);
expect(entry['adoption_status']).toEqual(expectedEntry['adoption_status']);
Expand All @@ -41,6 +40,14 @@ describe('tools/spectral/ipa/metrics/metricCollection.js runMetricCollectionJob'
expect(entry['owner_team']).toEqual(expectedEntry['owner_team']);
expect(entry['severity_level']).toEqual(expectedEntry['severity_level']);
});

expect(results.warnings.count).toEqual(1);
const violations = [
{
code: 'xgen-IPA-104-valid-operation-id',
},
];
expect(results.warnings.violations).toEqual(violations);
});
});

Expand Down
18 changes: 17 additions & 1 deletion tools/spectral/ipa/metrics/metricCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,24 @@ export async function runMetricCollectionJob(
console.log('Merging results...');
const mergedResults = merge(ownershipData, collectorResults, ruleSeverityMap);

const warningViolations = mergedResults.filter(
(result) => result.severity_level === 'warn' && result.adoption_status === 'violated'
);

const processedWarnings = warningViolations.map((violation) => ({
code: violation.ipa_rule,
}));

console.log(`Found ${warningViolations.length} warning-level violations`);

console.log('Metric collection job complete.');
return mergedResults;
return {
metrics: mergedResults,
warnings: {
count: warningViolations.length,
violations: processedWarnings,
},
};
} catch (error) {
console.error('Error during metric collection:', error.message);
throw error;
Expand Down
9 changes: 8 additions & 1 deletion tools/spectral/ipa/metrics/scripts/runMetricCollection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'node:fs';
import path from 'path';
import { spawnSync } from 'child_process';
import spectral from '@stoplight/spectral-core';
import { Compression, Table, writeParquet, WriterPropertiesBuilder } from 'parquet-wasm';
Expand Down Expand Up @@ -53,12 +54,18 @@ runMetricCollectionJob(
)
.then((results) => {
console.log('Writing results');
const table = tableFromJSON(results);
const table = tableFromJSON(results.metrics);
const wasmTable = Table.fromIPCStream(tableToIPC(table, 'stream'));
const parquetUint8Array = writeParquet(
wasmTable,
new WriterPropertiesBuilder().setCompression(Compression.GZIP).build()
);
fs.writeFileSync(config.defaultMetricCollectionResultsFilePath, parquetUint8Array);
fs.writeFileSync(path.join(config.defaultOutputsDir, 'warning-count.txt'), results.warnings.count.toString());

fs.writeFileSync(
path.join(config.defaultOutputsDir, 'warning-violations.json'),
JSON.stringify(results.warnings.violations, null, 2)
);
})
.catch((error) => console.error(error.message));
Loading