feat: add skipped packages list to Discord notifications

API Changes:
- Track skipped package names in keyword sync endpoint
- Include skippedPackages array in API response

Workflow Changes:
- Extract skipped package names from sync response
- Display skipped packages in Discord notification as comma-separated list
- Only show "📋 Skipped Packages" field when packages are skipped
- Dynamic field construction using jq

Example Discord output:
📋 Skipped Packages
package-name-1, package-name-2, package-name-3

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ajax Davis 2025-12-03 08:57:30 +10:00
parent 484190720a
commit 0b30c62ff9
2 changed files with 54 additions and 58 deletions

View file

@ -57,6 +57,14 @@ jobs:
fi fi
fi fi
# Store skipped packages for Discord
if [ "$skipped" -gt 0 ]; then
skippedList=$(echo "$response" | jq -r '.data.skippedPackages[]?' 2>/dev/null | paste -sd ", " - || echo "")
if [ -n "$skippedList" ]; then
echo "$skippedList" > /tmp/skipped_packages.txt
fi
fi
# Determine status emoji # Determine status emoji
if [ "$errors" -gt 0 ]; then if [ "$errors" -gt 0 ]; then
echo "status_emoji=⚠️" >> $GITHUB_OUTPUT echo "status_emoji=⚠️" >> $GITHUB_OUTPUT
@ -73,67 +81,50 @@ jobs:
duration_sec=$(echo "scale=2; ${{ steps.sync.outputs.durationMs }} / 1000" | bc) duration_sec=$(echo "scale=2; ${{ steps.sync.outputs.durationMs }} / 1000" | bc)
# Build Discord payload using jq for proper JSON escaping # Build Discord payload using jq for proper JSON escaping
if [ -f /tmp/error_summary.txt ] && [ ${{ steps.sync.outputs.errors }} -gt 0 ]; then # Read optional data
# Read and truncate error text error_text=""
error_text=$(cat /tmp/error_summary.txt | head -c 800) skipped_text=""
# Create payload with error details using jq if [ -f /tmp/error_summary.txt ] && [ ${{ steps.sync.outputs.errors }} -gt 0 ]; then
payload=$(jq -n \ error_text=$(cat /tmp/error_summary.txt | head -c 800)
--arg title "${{ steps.sync.outputs.status_emoji }} NPM Keyword Search Sync" \
--argjson color ${{ steps.sync.outputs.status_color }} \
--arg packages "${{ steps.sync.outputs.packagesFound }}" \
--arg processed "${{ steps.sync.outputs.processed }}" \
--arg skipped "${{ steps.sync.outputs.skipped }}" \
--arg errors "${{ steps.sync.outputs.errors }}" \
--arg duration "${duration_sec}s" \
--arg url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--arg error_text "$error_text" \
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \
'{
embeds: [{
title: $title,
color: $color,
fields: [
{ name: "📦 Packages Found", value: $packages, inline: true },
{ name: "✨ Processed", value: $processed, inline: true },
{ name: "⏭️ Skipped", value: $skipped, inline: true },
{ name: "❌ Errors", value: $errors, inline: true },
{ name: "⏱️ Duration", value: $duration, inline: true },
{ name: "🔗 Run", value: ("[View Logs](" + $url + ")"), inline: true },
{ name: "🔍 Error Details", value: ("```\n" + $error_text + "\n```"), inline: false }
],
timestamp: $timestamp
}]
}')
else
# Create payload without error details
payload=$(jq -n \
--arg title "${{ steps.sync.outputs.status_emoji }} NPM Keyword Search Sync" \
--argjson color ${{ steps.sync.outputs.status_color }} \
--arg packages "${{ steps.sync.outputs.packagesFound }}" \
--arg processed "${{ steps.sync.outputs.processed }}" \
--arg skipped "${{ steps.sync.outputs.skipped }}" \
--arg errors "${{ steps.sync.outputs.errors }}" \
--arg duration "${duration_sec}s" \
--arg url "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \
'{
embeds: [{
title: $title,
color: $color,
fields: [
{ name: "📦 Packages Found", value: $packages, inline: true },
{ name: "✨ Processed", value: $processed, inline: true },
{ name: "⏭️ Skipped", value: $skipped, inline: true },
{ name: "❌ Errors", value: $errors, inline: true },
{ name: "⏱️ Duration", value: $duration, inline: true },
{ name: "🔗 Run", value: ("[View Logs](" + $url + ")"), inline: true }
],
timestamp: $timestamp
}]
}')
fi fi
if [ -f /tmp/skipped_packages.txt ] && [ ${{ steps.sync.outputs.skipped }} -gt 0 ]; then
skipped_text=$(cat /tmp/skipped_packages.txt)
fi
# Build fields array dynamically
base_fields='[
{ "name": "📦 Packages Found", "value": "${{ steps.sync.outputs.packagesFound }}", "inline": true },
{ "name": "✨ Processed", "value": "${{ steps.sync.outputs.processed }}", "inline": true },
{ "name": "⏭️ Skipped", "value": "${{ steps.sync.outputs.skipped }}", "inline": true },
{ "name": "❌ Errors", "value": "${{ steps.sync.outputs.errors }}", "inline": true },
{ "name": "⏱️ Duration", "value": "'"${duration_sec}s"'", "inline": true },
{ "name": "🔗 Run", "value": "[View Logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": true }
]'
# Create payload with dynamic fields
payload=$(jq -n \
--arg title "${{ steps.sync.outputs.status_emoji }} NPM Keyword Search Sync" \
--argjson color ${{ steps.sync.outputs.status_color }} \
--argjson baseFields "$base_fields" \
--arg error_text "$error_text" \
--arg skipped_text "$skipped_text" \
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \
'
{
embeds: [{
title: $title,
color: $color,
fields: (
$baseFields +
(if $skipped_text != "" then [{ name: "📋 Skipped Packages", value: $skipped_text, inline: false }] else [] end) +
(if $error_text != "" then [{ name: "🔍 Error Details", value: ("```\n" + $error_text + "\n```"), inline: false }] else [] end)
),
timestamp: $timestamp
}]
}')
# Send to Discord # Send to Discord
curl -X POST "${{ secrets.DISCORD_WEBHOOK }}" \ curl -X POST "${{ secrets.DISCORD_WEBHOOK }}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \

View file

@ -30,6 +30,7 @@ export async function POST(request: NextRequest) {
let skipped = 0; let skipped = 0;
let errors = 0; let errors = 0;
const errorMessages: string[] = []; const errorMessages: string[] = [];
const skippedPackages: string[] = [];
try { try {
// Search for packages with 'tpmjs-tool' keyword // Search for packages with 'tpmjs-tool' keyword
@ -47,12 +48,14 @@ export async function POST(request: NextRequest) {
// Skip if package not found // Skip if package not found
if (!pkg) { if (!pkg) {
skipped++; skipped++;
skippedPackages.push(result.package.name);
continue; continue;
} }
// Check if package has tpmjs field // Check if package has tpmjs field
if (!pkg.tpmjs) { if (!pkg.tpmjs) {
skipped++; skipped++;
skippedPackages.push(pkg.name);
continue; continue;
} }
@ -60,6 +63,7 @@ export async function POST(request: NextRequest) {
const validation = validateTpmjsField(pkg.tpmjs); const validation = validateTpmjsField(pkg.tpmjs);
if (!validation.valid || !validation.data) { if (!validation.valid || !validation.data) {
skipped++; skipped++;
skippedPackages.push(pkg.name);
continue; continue;
} }
@ -179,6 +183,7 @@ export async function POST(request: NextRequest) {
packagesFound: searchResults.length, packagesFound: searchResults.length,
durationMs: Date.now() - startTime, durationMs: Date.now() - startTime,
errorMessages: errorMessages.slice(0, 5), // Include first 5 error messages errorMessages: errorMessages.slice(0, 5), // Include first 5 error messages
skippedPackages: skippedPackages, // Include all skipped package names
}, },
}); });
} catch (error) { } catch (error) {