From d524c3f28f2f7e5e782688bc95367d112871d9d3 Mon Sep 17 00:00:00 2001 From: Zach Capshaw Date: Mon, 25 May 2026 15:35:28 -0600 Subject: [PATCH 1/2] Fix GitHub metrics delivery under branch protection. Open a PR instead of pushing to main, and refresh github-metrics.json for all recipes with source URLs. Co-authored-by: Cursor --- .github/workflows/enrich-github-metrics.yml | 44 +- data/github-metrics.json | 702 +++++++++++++++++++- 2 files changed, 727 insertions(+), 19 deletions(-) diff --git a/.github/workflows/enrich-github-metrics.yml b/.github/workflows/enrich-github-metrics.yml index a4332c9..cada90f 100644 --- a/.github/workflows/enrich-github-metrics.yml +++ b/.github/workflows/enrich-github-metrics.yml @@ -1,7 +1,8 @@ name: Enrich GitHub metrics -# Fetches stars/watchers for recipe source repos and commits data/github-metrics.json. -# The web app sync job merges this sidecar into public/data/recipes.json. +# Fetches stars/watchers for recipe source repos and opens a PR with +# data/github-metrics.json. Main is branch-protected, so we never push +# metrics commits directly to main. on: schedule: @@ -23,6 +24,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write steps: - uses: actions/checkout@v4 @@ -35,15 +37,33 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm run enrich-github - - name: Commit metrics if changed + - name: Open PR with metrics if changed + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - if [[ -n "$(git status --porcelain data/github-metrics.json)" ]]; then - git config user.name "speechstack-bot" - git config user.email "bot@speechstack.com" - git add data/github-metrics.json - git commit -m "chore: refresh GitHub metrics for recipes" - git push - echo "::notice::Pushed updated github-metrics.json" - else - echo "::notice::GitHub metrics unchanged" + if [[ -z "$(git status --porcelain data/github-metrics.json)" ]]; then + echo "::notice::GitHub metrics unchanged — no PR needed" + exit 0 + fi + + BRANCH="bot/github-metrics-$(date -u +%Y%m%d%H%M)" + git config user.name "speechstack-bot" + git config user.email "bot@speechstack.com" + git checkout -b "$BRANCH" + git add data/github-metrics.json + git commit -m "chore: refresh GitHub metrics for recipes" + git push -u origin "$BRANCH" + + EXISTING=$(gh pr list --head "$BRANCH" --state open --json number -q '.[0].number' || true) + if [[ -n "$EXISTING" ]]; then + echo "::notice::PR #$EXISTING already open for $BRANCH" + exit 0 fi + + gh pr create \ + --base main \ + --head "$BRANCH" \ + --title "chore: refresh GitHub metrics" \ + --body "Automated update from the **Enrich GitHub metrics** workflow. Merging updates \`data/github-metrics.json\` for Top/Trending on speechstack.com." + + echo "::notice::Opened PR for $BRANCH" diff --git a/data/github-metrics.json b/data/github-metrics.json index 9c749af..cefc8ae 100644 --- a/data/github-metrics.json +++ b/data/github-metrics.json @@ -1,14 +1,182 @@ { "version": 1, - "fetchedAt": "2026-05-25T21:13:12.076Z", + "fetchedAt": "2026-05-25T21:34:24.831Z", "recipes": { + "ai-sales-agent-for-b2b-product-outreach": { + "stars": 2, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2025-08-06T19:04:37Z", + "repo": "zatiyab/AI-Call-Salesman", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "autonomous-incident-manager-for-site-reliability-engineering": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-03-27T23:42:00Z", + "repo": "Badri-Narayanan/Autonomous-SRE", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "autonomous-sales-outbound-calling-agent": { + "stars": 1, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2025-08-23T03:54:54Z", + "repo": "yashh2417/cold_campaign_agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "barbershop-appointment-scheduling-receptionist": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-02-08T23:16:03Z", + "repo": "BigSur23/elite-cuts-voice-ai", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "basic-voice-agent-for-general-conversation": { + "stars": 21, + "watchers": 4, + "forks": 3, + "repoPushedAt": "2025-10-28T16:28:37Z", + "repo": "cartesia-ai/cartesia-livekit-voice-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "clinical-trial-recruitment-voice-agent": { + "stars": 2, + "watchers": 0, + "forks": 1, + "repoPushedAt": "2026-04-10T20:06:54Z", + "repo": "deepgram/deepgram-amazon-connect-sample-apps", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "content-filtering-voice-assistant-with-guardrails": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "conversational-ai-agent-with-streaming-stt-and-tts": { + "stars": 408, + "watchers": 4, + "forks": 118, + "repoPushedAt": "2026-01-07T16:33:08Z", + "repo": "deepgram-devs/deepgram-ai-agent-demo", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "conversational-article-discussion-assistant": { + "stars": 20, + "watchers": 5, + "forks": 3, + "repoPushedAt": "2024-08-28T22:43:09Z", + "repo": "cartesia-ai/dev-showcase", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "conversational-phone-agent-with-natural-interruptions": { + "stars": 0, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-04-16T22:18:30Z", + "repo": "plivo/python-agents-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "conversational-voice-agent-with-tool-calling": { + "stars": 1, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-25T01:27:00Z", + "repo": "deepgram/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "customer-service-agent-with-function-calling-and-order-management": { + "stars": 22, + "watchers": 2, + "forks": 23, + "repoPushedAt": "2026-03-02T21:54:54Z", + "repo": "deepgram-devs/flask-agent-function-calling-demo", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "customer-service-agent-with-function-calling": { + "stars": 3, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2025-04-24T18:43:40Z", + "repo": "deepgram/the-bobs", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "customer-support-agent-with-ticket-status-lookup": { + "stars": 248, + "watchers": 12, + "forks": 119, + "repoPushedAt": "2026-05-25T15:47:51Z", + "repo": "HumeAI/hume-api-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "customer-support-and-appointment-booking-assistant": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-07T20:02:32Z", + "repo": "twilio-samples/conversationrelay-ai-demo", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, "deepgram-dental-receptionist": { "stars": 1, "watchers": 0, "forks": 2, "repoPushedAt": "2026-03-23T17:24:21Z", "repo": "deepgram-devs/deepgram-voice-agent-inbound-telephony", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "dental-clinic-appointment-booking-agent": { + "stars": 41, + "watchers": 2, + "forks": 15, + "repoPushedAt": "2025-01-30T18:52:47Z", + "repo": "mjunaidca/appointment-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "dental-office-appointment-scheduling-agent": { + "stars": 1, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-03-23T17:24:21Z", + "repo": "deepgram-devs/deepgram-voice-agent-inbound-telephony", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "desktop-robot-assistant-with-voice-controlled-manipulation": { + "stars": 5, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-05-17T22:59:48Z", + "repo": "livekit-examples/embodied-ai-hackathon", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "doctor-appointment-scheduler-with-intake-form": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "ecommerce-refund-processing-assistant": { + "stars": 18, + "watchers": 4, + "forks": 19, + "repoPushedAt": "2025-07-08T14:58:46Z", + "repo": "pBread/twilio-agentic-voice-assistant", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "elder-care-advisor-for-adult-children": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-23T18:20:57Z", + "repo": "flaminshinjan/emoha-poc", + "fetchedAt": "2026-05-25T21:34:24.831Z" }, "elevenlabs-twilio-sales-agent": { "stars": 603, @@ -16,7 +184,159 @@ "forks": 282, "repoPushedAt": "2026-05-22T01:53:48Z", "repo": "elevenlabs/elevenlabs-examples", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "festival-group-planning-assistant": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-03-13T02:45:32Z", + "repo": "YichiZ/festival-coordinator", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "five-minute-inbound-lead-qualification-and-transfer": { + "stars": 83, + "watchers": 2, + "forks": 30, + "repoPushedAt": "2023-12-19T02:57:58Z", + "repo": "Bland-AI/Bland-AI-Cookbooks", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "flowise-ai-voice-agent-with-twilio-conversationrelay": { + "stars": 1, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-04-10T13:47:07Z", + "repo": "twilio-samples/cr-flowiseai", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "general-assistant-voice-chatbot-with-audio-streaming": { + "stars": 5, + "watchers": 4, + "forks": 0, + "repoPushedAt": "2025-04-14T05:26:16Z", + "repo": "plivo/plivo-audiostream-integration-guides", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "general-purpose-conversational-voice-agent-with-nvidia-nim": { + "stars": 86, + "watchers": 7, + "forks": 22, + "repoPushedAt": "2025-05-05T18:44:42Z", + "repo": "daily-co/nimble-pipecat", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "general-purpose-voice-agent-with-low-latency-streaming": { + "stars": 2, + "watchers": 0, + "forks": 1, + "repoPushedAt": "2025-07-31T20:36:21Z", + "repo": "gsharp-aai/voice-agent-aai-elevenlabs-openai", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "general-purpose-voice-agent-with-open-source-nvidia-models": { + "stars": 557, + "watchers": 5, + "forks": 96, + "repoPushedAt": "2026-05-25T02:40:30Z", + "repo": "pipecat-ai/nemotron-january-2026", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "healthcare-clinic-voice-receptionist": { + "stars": 2, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-04-24T06:33:17Z", + "repo": "JeevanMovva/aria-voice-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "healthcare-prescription-savings-outreach-agent": { + "stars": 1, + "watchers": 0, + "forks": 1, + "repoPushedAt": "2026-04-10T16:01:53Z", + "repo": "deepgram/deepgram-patient-connect", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "hotel-front-desk-agent-with-smart-backchannel-filtering": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-04-29T20:24:40Z", + "repo": "AssemblyAI-Solutions/livekit-interruption-filters", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "hotel-front-desk-receptionist": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-04-22T14:26:20Z", + "repo": "dlange-aai/hotel-booking-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "inbound-and-outbound-phone-bot-with-daily-and-plivo": { + "stars": 0, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-04-16T22:18:30Z", + "repo": "plivo/python-agents-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "inbound-phone-order-status-agent": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-19T15:50:37Z", + "repo": "kelsey-aai/twilio-voice-agent-assemblyai", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "insurance-lead-follow-up-agent": { + "stars": 3, + "watchers": 0, + "forks": 3, + "repoPushedAt": "2026-03-23T17:21:49Z", + "repo": "deepgram-devs/deepgram-voice-agent-outbound-telephony", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "interactive-choose-your-own-adventure-storytelling": { + "stars": 289, + "watchers": 4, + "forks": 109, + "repoPushedAt": "2026-05-22T17:15:40Z", + "repo": "pipecat-ai/pipecat-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "interactive-voice-game-for-discovering-secret-crushes": { + "stars": 3, + "watchers": 1, + "forks": 1, + "repoPushedAt": "2026-02-23T20:07:23Z", + "repo": "daily-co/pipecat-crush-quest", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "ivr-phone-tree-with-llm-function-calling": { + "stars": 0, + "watchers": 7, + "forks": 1, + "repoPushedAt": "2025-09-10T13:35:47Z", + "repo": "daily-demos/daily-bots-phone-tree", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "kubernetes-sre-voice-agent-with-mcp-tools": { + "stars": 68, + "watchers": 8, + "forks": 17, + "repoPushedAt": "2025-10-15T00:04:49Z", + "repo": "den-vasyliev/voice-mcp-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "langchain-agent-voice-demo-with-vocode-core": { + "stars": 3749, + "watchers": 49, + "forks": 656, + "repoPushedAt": "2024-11-15T22:16:58Z", + "repo": "vocodedev/vocode-core", + "fetchedAt": "2026-05-25T21:34:24.831Z" }, "livekit-drivethru-ordering": { "stars": 10681, @@ -24,7 +344,7 @@ "forks": 3168, "repoPushedAt": "2026-05-25T19:32:11Z", "repo": "livekit/agents", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" }, "livekit-warm-transfer-support": { "stars": 10681, @@ -32,7 +352,135 @@ "forks": 3168, "repoPushedAt": "2026-05-25T19:32:11Z", "repo": "livekit/agents", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "medical-assistant-for-clinical-note-taking": { + "stars": 15, + "watchers": 2, + "forks": 14, + "repoPushedAt": "2025-07-09T14:12:42Z", + "repo": "deepgram-devs/voice-agent-medical-assistant-demo", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "medical-office-receptionist-for-appointment-booking-and-triage": { + "stars": 2, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-03-13T19:54:58Z", + "repo": "RaheesAhmed/MediVoice-AI", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-agent-in-app-voice-assistant-with-web-search-knowledge-base-and-account-ac": { + "stars": 73777, + "watchers": 995, + "forks": 12479, + "repoPushedAt": "2026-05-22T21:42:38Z", + "repo": "openai/openai-cookbook", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-agent-voice-ai-workflow-with-python": { + "stars": 16, + "watchers": 1, + "forks": 6, + "repoPushedAt": "2026-05-25T08:40:12Z", + "repo": "livekit-examples/multi-agent-python", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-agent-voice-framework-for-customer-service-and-chat-supervision": { + "stars": 6877, + "watchers": 132, + "forks": 1092, + "repoPushedAt": "2026-01-07T18:38:52Z", + "repo": "openai/openai-realtime-agents", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-agent-voice-pipeline-with-transcription-and-synthesis": { + "stars": 1, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-25T01:27:00Z", + "repo": "deepgram/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-intent-call-router-with-rag-instructions": { + "stars": 7, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-01-23T05:11:14Z", + "repo": "VapiAI/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-provider-llm-proxy-for-voice-agents": { + "stars": 3, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2025-11-27T03:03:19Z", + "repo": "deepgram-devs/deepgram-voice-agent-client-llm-proxy", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-purpose-voice-agent-showcase": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-08T17:53:07Z", + "repo": "AssemblyAI-Solutions/voice-agent-api-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multi-user-browser-voice-agent-with-webrtc-transport": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-04-30T18:16:20Z", + "repo": "kelsey-aai/voice-agent-livekit", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "multimodal-voice-and-vision-assistant-for-ios": { + "stars": 85, + "watchers": 11, + "forks": 21, + "repoPushedAt": "2026-03-10T23:39:39Z", + "repo": "livekit-examples/vision-demo", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "openclaw-phone-assistant-with-semantic-turn-detection": { + "stars": 77, + "watchers": 1, + "forks": 11, + "repoPushedAt": "2026-02-09T04:54:36Z", + "repo": "deepgram/deepclaw", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "outbound-call-agent-with-voicemail-detection-and-transfer": { + "stars": 94, + "watchers": 1, + "forks": 38, + "repoPushedAt": "2026-04-10T18:03:45Z", + "repo": "livekit-examples/outbound-caller-python", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "outbound-sales-assistant-for-airpods": { + "stars": 487, + "watchers": 15, + "forks": 218, + "repoPushedAt": "2024-12-13T19:25:32Z", + "repo": "twilio-labs/call-gpt", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "phone-based-voice-agent-with-web-search": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-08T18:12:57Z", + "repo": "AssemblyAI-Solutions/voice-agent-api-twilio-example", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "phone-call-handling-voice-agent": { + "stars": 0, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-04-16T22:18:30Z", + "repo": "plivo/python-agents-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" }, "pipecat-twilio-quickstart": { "stars": 5, @@ -40,7 +488,191 @@ "forks": 5, "repoPushedAt": "2025-10-22T01:42:44Z", "repo": "pipecat-ai/pipecat-quickstart-phone-bot", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "pizza-ordering-voice-agent": { + "stars": 0, + "watchers": 0, + "forks": 1, + "repoPushedAt": "2026-05-23T13:12:00Z", + "repo": "deepgram-devs/pizza-voice-agent-workshop", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "pstn-voice-assistant-with-real-time-transcription-and-barge-in": { + "stars": 1, + "watchers": 2, + "forks": 1, + "repoPushedAt": "2025-10-16T21:14:38Z", + "repo": "tchancse/vonage-deepgram-voice-agent", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "real-time-conversational-voice-bot-with-turn-detection": { + "stars": 1, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-25T01:27:00Z", + "repo": "deepgram/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "real-time-multilingual-translation-between-customer-and-contact-center-agent": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "twilio-samples/live-translation-openai-realtime-api" + }, + "real-time-speech-transcription-frontend": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "livekit-examples/transcription-frontend-groq" + }, + "real-time-voice-agent-with-neural-turn-detection": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "kelsey-aai/voice-agent-livekit-universal-3-pro" + }, + "real-time-voice-agent-with-openai-and-twilio": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "rehan-dev/ai-call-agent" + }, + "real-time-voice-assistant-with-room-based-conversations": { + "stars": 1, + "watchers": 0, + "forks": 0, + "repoPushedAt": "2026-05-25T01:27:00Z", + "repo": "deepgram/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "real-time-web-form-filling-voice-agent": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "saas-customer-support-agent-with-assemblyai": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "sampleapp-ai/assemblyai-voice-agent-pipecat" + }, + "sales-representative-with-lead-extraction-and-company-research": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "smart-city-voice-ai-demo-for-harbour-city-operations": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "deepgram-devs/smart-city" + }, + "sms-one-time-password-verification-for-identity-confirmation": { + "stars": 7, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-01-23T05:11:14Z", + "repo": "VapiAI/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "space-trading-game-with-autonomous-ship-ai": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "pipecat-ai/gradient-bang" + }, + "spanish-dental-clinic-receptionist-agent": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "numoru-ia/voice-agent-es" + }, + "streaming-voice-agent-with-gemini-flash-and-silero-barge-in": { + "stars": 0, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-04-16T22:18:30Z", + "repo": "plivo/python-agents-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "technical-interview-practice-agent-with-real-time-feedback": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "telephony-bridge-for-real-time-voice-agents": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "steinathan/telephony-server" + }, + "telephony-integration-connector-for-conversational-ai": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "nexmo-se/elevenlabs-agent-ws-connector" + }, + "telephony-voice-agent-with-inbound-and-outbound-call-handling": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "AssemblyAI/voice-agent-api-twilio-example" + }, + "travel-companion-with-location-based-recommendations": { + "stars": 289, + "watchers": 4, + "forks": 109, + "repoPushedAt": "2026-05-22T17:15:40Z", + "repo": "pipecat-ai/pipecat-examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "two-truths-and-a-lie-interactive-game-bot": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "daily-co/pcc-gemini-twilio" + }, + "two-way-conversational-speech-assistant": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "twilio-samples/speech-assistant-openai-realtime-api-python" }, "vapi-healthcare-scheduler": { "stars": 7, @@ -48,7 +680,63 @@ "forks": 2, "repoPushedAt": "2026-01-23T05:11:14Z", "repo": "VapiAI/examples", - "fetchedAt": "2026-05-25T21:13:12.076Z" + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "voice-agent-with-visual-data-verification-for-lead-capture": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "jeffo777/input-right" + }, + "voicemail-detection-assistant-for-outbound-calls": { + "stars": 7, + "watchers": 0, + "forks": 2, + "repoPushedAt": "2026-01-23T05:11:14Z", + "repo": "VapiAI/examples", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "vonage-voice-api-websocket-connector-for-multiple-ai-engines": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "nexmo-se/voice-to-ai-engines" + }, + "weather-information-assistant-with-function-calling": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "daily-co/pcc-groq-llama" + }, + "web-research-agent-with-real-time-search-and-content-extraction": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "web-research-assistant-with-real-time-search": { + "stars": 99, + "watchers": 5, + "forks": 41, + "repoPushedAt": "2026-05-19T19:18:32Z", + "repo": "cartesia-ai/line", + "fetchedAt": "2026-05-25T21:34:24.831Z" + }, + "whatsapp-voice-conversational-agent": { + "stars": 0, + "watchers": 0, + "forks": 0, + "repoPushedAt": null, + "fetchedAt": "2026-05-25T21:34:24.831Z", + "repo": "daily-co/pcc-gemini-whatsapp" } } } From 726fc6aecfbc0329fe025363c27bc3bbb85d02cc Mon Sep 17 00:00:00 2001 From: Zach Capshaw Date: Mon, 25 May 2026 15:41:27 -0600 Subject: [PATCH 2/2] Document ruleset bypass for automation and restore direct metrics push. Explains how to keep PR requirements for contributors while allowing GitHub Actions to commit generated metrics once bypass and workflow permissions are configured. Co-authored-by: Cursor --- .github/workflows/enrich-github-metrics.yml | 44 ++++----------- docs/automation-and-branch-rules.md | 61 +++++++++++++++++++++ 2 files changed, 73 insertions(+), 32 deletions(-) create mode 100644 docs/automation-and-branch-rules.md diff --git a/.github/workflows/enrich-github-metrics.yml b/.github/workflows/enrich-github-metrics.yml index cada90f..4aa68d5 100644 --- a/.github/workflows/enrich-github-metrics.yml +++ b/.github/workflows/enrich-github-metrics.yml @@ -1,8 +1,7 @@ name: Enrich GitHub metrics -# Fetches stars/watchers for recipe source repos and opens a PR with -# data/github-metrics.json. Main is branch-protected, so we never push -# metrics commits directly to main. +# Fetches stars/watchers for recipe source repos and commits data/github-metrics.json. +# Requires "GitHub Actions" on the default-branch ruleset bypass list (see docs/automation-and-branch-rules.md). on: schedule: @@ -24,7 +23,6 @@ jobs: runs-on: ubuntu-latest permissions: contents: write - pull-requests: write steps: - uses: actions/checkout@v4 @@ -37,33 +35,15 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm run enrich-github - - name: Open PR with metrics if changed - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Commit metrics if changed run: | - if [[ -z "$(git status --porcelain data/github-metrics.json)" ]]; then - echo "::notice::GitHub metrics unchanged — no PR needed" - exit 0 - fi - - BRANCH="bot/github-metrics-$(date -u +%Y%m%d%H%M)" - git config user.name "speechstack-bot" - git config user.email "bot@speechstack.com" - git checkout -b "$BRANCH" - git add data/github-metrics.json - git commit -m "chore: refresh GitHub metrics for recipes" - git push -u origin "$BRANCH" - - EXISTING=$(gh pr list --head "$BRANCH" --state open --json number -q '.[0].number' || true) - if [[ -n "$EXISTING" ]]; then - echo "::notice::PR #$EXISTING already open for $BRANCH" - exit 0 + if [[ -n "$(git status --porcelain data/github-metrics.json)" ]]; then + git config user.name "speechstack-bot" + git config user.email "bot@speechstack.com" + git add data/github-metrics.json + git commit -m "chore: refresh GitHub metrics for recipes" + git push + echo "::notice::Pushed updated github-metrics.json" + else + echo "::notice::GitHub metrics unchanged" fi - - gh pr create \ - --base main \ - --head "$BRANCH" \ - --title "chore: refresh GitHub metrics" \ - --body "Automated update from the **Enrich GitHub metrics** workflow. Merging updates \`data/github-metrics.json\` for Top/Trending on speechstack.com." - - echo "::notice::Opened PR for $BRANCH" diff --git a/docs/automation-and-branch-rules.md b/docs/automation-and-branch-rules.md new file mode 100644 index 0000000..aee09d8 --- /dev/null +++ b/docs/automation-and-branch-rules.md @@ -0,0 +1,61 @@ +# Automation vs open-source contributions + +The `main` branch uses a repository ruleset that **requires pull requests**. That is intentional for external contributors. Internal automation should not open a daily PR for generated files. + +## Recommended ruleset configuration + +Open: **Settings → Rules → Rulesets → `rules`** +(or https://github.com/speechstack-ai/recipes/rules/16490154) + +### Keep these rules (default branch) + +| Rule | Purpose | +|------|---------| +| **Require a pull request before merging** | Fork PRs and collaborator changes go through review (0 approvals is fine). | +| **Block force pushes** (`non_fast_forward`) | Prevents rewriting `main` history. | +| **Restrict deletions** | Prevents deleting `main`. | + +### Bypass list (who can push directly to `main`) + +| Actor | Bypass mode | Why | +|-------|-------------|-----| +| **GitHub Actions** | Always allow | Lets `GITHUB_TOKEN` in `.github/workflows/*` commit generated files (`data/github-metrics.json`, etc.). | +| *(optional)* **Repository admin** | Always allow | Emergency fixes by org owners only. | + +Do **not** add **Write** or **Maintain** to the bypass list. Anyone with write access would be able to skip PRs. + +Add **GitHub Actions** from the bypass picker in the UI. The REST API uses a different integration reference and may return `422` if added manually by app id. + +### Actions settings + +**Settings → Actions → General → Workflow permissions** + +- **Read and write permissions** for `GITHUB_TOKEN` +- Enable **Allow GitHub Actions to create and approve pull requests** (helps when rules interact with PR flows) + +## What this achieves + +| Actor | Push to `main` | +|-------|----------------| +| External contributor (fork PR) | Via PR only | +| Collaborator with write | Via PR only | +| GitHub Actions workflow on `main` | Direct push allowed (bypass) | +| Admin (if listed in bypass) | Direct push allowed | + +## Repos that sync from here + +When `data/**` changes on `main`, the **Notify web** workflow dispatches `recipes-updated` to `speechstack-ai/web`. No extra step unless that workflow failed. + +Apply the same pattern on **speechstack-ai/web** if you add branch rules there: bypass **GitHub Actions** only, keep PR requirement for humans. + +## Troubleshooting `GH013` + +If enrich or sync jobs fail with *Changes must be made through a pull request*: + +1. Confirm **GitHub Actions** is on the bypass list (not empty). +2. Confirm workflow permissions are **read and write**. +3. Re-run **Enrich GitHub metrics** or **Sync recipes** from the Actions tab. + +## Optional: machine-user PAT (not recommended) + +If bypassing via GitHub Actions is unavailable, use a fine-grained PAT stored as `RECIPES_BOT_PAT` with contents write and add that user to the bypass list. Prefer GitHub Actions bypass so you do not store a long-lived PAT.