diff --git a/.github/workflows/dependabot-alert-to-feishu.yml b/.github/workflows/dependabot-alert-to-feishu.yml new file mode 100644 index 00000000000..182b54e8aca --- /dev/null +++ b/.github/workflows/dependabot-alert-to-feishu.yml @@ -0,0 +1,99 @@ +name: Dependabot Alert to Feishu + +on: + repository_vulnerability_alert: + types: + - create + - reopen + schedule: + - cron: "0 * * * *" + workflow_dispatch: + +permissions: + contents: read + security-events: read + +jobs: + notify-feishu: + runs-on: ubuntu-latest + steps: + - name: Validate webhook secret + env: + FEISHU_WEBHOOK: ${{ secrets.FEISHU_WEBHOOK }} + run: | + set -euo pipefail + if [ -z "${FEISHU_WEBHOOK:-}" ]; then + echo "FEISHU_WEBHOOK secret is not configured." + exit 1 + fi + + - name: Notify Feishu from event or API polling + env: + FEISHU_WEBHOOK: ${{ secrets.FEISHU_WEBHOOK }} + GITHUB_TOKEN: ${{ github.token }} + EVENT_JSON: ${{ toJson(github.event) }} + EVENT_NAME: ${{ github.event_name }} + REPOSITORY: ${{ github.repository }} + EVENT_ACTION: ${{ github.event.action }} + WORKFLOW_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + set -euo pipefail + + send_feishu() { + local source="$1" + local action="$2" + local severity="$3" + local package_name="$4" + local summary="$5" + local alert_url="$6" + + local message payload + message="$(printf '%s\n' \ + '[Dependabot Alert]' \ + "Repository: ${REPOSITORY}" \ + "Source: ${source}" \ + "Action: ${action}" \ + "Severity: ${severity}" \ + "Package: ${package_name}" \ + "Summary: ${summary}" \ + "Alert: ${alert_url}" \ + "Run: ${WORKFLOW_URL}")" + + payload="$(jq -n --arg text "$message" '{msg_type: "text", content: {text: $text}}')" + curl -sS -f -X POST "$FEISHU_WEBHOOK" \ + -H "Content-Type: application/json" \ + -d "$payload" + } + + if [ "$EVENT_NAME" = "repository_vulnerability_alert" ]; then + severity="$(echo "$EVENT_JSON" | jq -r '.alert.security_advisory.severity // "unknown"')" + package_name="$(echo "$EVENT_JSON" | jq -r '.alert.dependency.package.name // "unknown"')" + summary="$(echo "$EVENT_JSON" | jq -r '.alert.security_advisory.summary // "N/A"')" + alert_url="$(echo "$EVENT_JSON" | jq -r '.alert.html_url // ""')" + action="${EVENT_ACTION:-create}" + + send_feishu "event" "$action" "$severity" "$package_name" "$summary" "$alert_url" + exit 0 + fi + + api_url="https://api.github.com/repos/${REPOSITORY}/dependabot/alerts?state=open&per_page=100" + alerts_json="$(curl -sS -f -L \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${GITHUB_TOKEN}" \ + -H "X-GitHub-Api-Version: 2026-03-10" \ + "$api_url")" + + alert_count="$(echo "$alerts_json" | jq 'length')" + if [ "$alert_count" -eq 0 ]; then + echo "No open dependabot alerts." + exit 0 + fi + + echo "$alerts_json" | jq -c '.[]' | while IFS= read -r alert; do + severity="$(echo "$alert" | jq -r '.security_advisory.severity // "unknown"')" + package_name="$(echo "$alert" | jq -r '.dependency.package.name // "unknown"')" + summary="$(echo "$alert" | jq -r '.security_advisory.summary // "N/A"')" + alert_url="$(echo "$alert" | jq -r '.html_url // ""')" + + send_feishu "poll" "open" "$severity" "$package_name" "$summary" "$alert_url" + done