tpmjs/.github/workflows/sync-enrich.yml
Thomas Davis 198f9f7d1e fix: separate sync discovery from enrichment and harden Railway executor
Sync system was timing out because discovery endpoints (keyword, changes)
also ran schema extraction (~10-15s per tool). Now discovery is fast
(npm metadata + DB writes only) and a new /api/sync/enrich endpoint
handles schema extraction in time-budgeted chunks.

Railway executor was crashing without restarting due to unhandled promise
rejections, no restart policy, and no health checks. Added crash
protection, graceful shutdown, cache size limits, railway.toml with
ALWAYS restart policy, and upgraded Deno from 1.39 to 2.1.9.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 04:49:54 +10:00

114 lines
4.9 KiB
YAML

name: Sync Tool Enrichment
on:
schedule:
# Run every 2 minutes
- cron: '*/2 * * * *'
workflow_dispatch:
jobs:
sync-enrich:
runs-on: ubuntu-latest
steps:
- name: Trigger enrichment sync
id: sync
run: |
# Call the sync API and capture response
response=$(curl -X POST "${{ secrets.VERCEL_PRODUCTION_URL }}/api/sync/enrich" \
-H "Authorization: Bearer ${{ secrets.CRON_SECRET }}" \
-H "Content-Type: application/json" \
-f -s -S)
echo "Response: $response"
# Extract data using jq
enriched=$(echo "$response" | jq -r '.data.enriched')
discovered=$(echo "$response" | jq -r '.data.discovered')
skipped=$(echo "$response" | jq -r '.data.skipped')
errors=$(echo "$response" | jq -r '.data.errors')
durationMs=$(echo "$response" | jq -r '.data.durationMs')
# Extract and display error messages
errorMessages=$(echo "$response" | jq -r '.data.errorMessages[]?' 2>/dev/null || echo "")
if [ -n "$errorMessages" ]; then
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "⚠️ ENRICHMENT ERRORS ($errors total):"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$response" | jq -r '.data.errorMessages[]?' | while IFS= read -r error; do
echo " • $error"
done
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
fi
# Set outputs for Discord notification
echo "enriched=$enriched" >> $GITHUB_OUTPUT
echo "discovered=$discovered" >> $GITHUB_OUTPUT
echo "skipped=$skipped" >> $GITHUB_OUTPUT
echo "errors=$errors" >> $GITHUB_OUTPUT
echo "durationMs=$durationMs" >> $GITHUB_OUTPUT
# Store error messages for Discord (first 3, truncated)
if [ "$errors" -gt 0 ]; then
errorSummary=$(echo "$response" | jq -r '.data.errorMessages[0:3]? | join("\n• ")' 2>/dev/null || echo "")
if [ -n "$errorSummary" ]; then
echo "• $errorSummary" > /tmp/error_summary.txt
fi
fi
# Determine status emoji
if [ "$errors" -gt 0 ]; then
echo "status_emoji=⚠️" >> $GITHUB_OUTPUT
echo "status_color=16776960" >> $GITHUB_OUTPUT # Yellow
else
echo "status_emoji=✅" >> $GITHUB_OUTPUT
echo "status_color=5763719" >> $GITHUB_OUTPUT # Green
fi
- name: Send Discord notification
if: always()
run: |
# Format duration
duration_sec=$(echo "scale=2; ${{ steps.sync.outputs.durationMs }} / 1000" | bc)
# Build Discord payload using jq for proper JSON escaping
error_text=""
if [ -f /tmp/error_summary.txt ] && [ ${{ steps.sync.outputs.errors }} -gt 0 ]; then
error_text=$(cat /tmp/error_summary.txt | head -c 800)
fi
# Build fields array dynamically
base_fields='[
{ "name": "🔧 Enriched", "value": "${{ steps.sync.outputs.enriched }}", "inline": true },
{ "name": "🔍 Discovered", "value": "${{ steps.sync.outputs.discovered }}", "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 }} Tool Enrichment Sync" \
--argjson color ${{ steps.sync.outputs.status_color }} \
--argjson baseFields "$base_fields" \
--arg error_text "$error_text" \
--arg timestamp "$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" \
'
{
embeds: [{
title: $title,
color: $color,
fields: (
$baseFields +
(if $error_text != "" then [{ name: "🔍 Error Details", value: ("```\n" + $error_text + "\n```"), inline: false }] else [] end)
),
timestamp: $timestamp
}]
}')
# Send to Discord
curl -X POST "${{ secrets.DISCORD_WEBHOOK }}" \
-H "Content-Type: application/json" \
-d "$payload"