Skip to content

PM — Suggestions #158

PM — Suggestions

PM — Suggestions #158

name: PM — Suggestions
on:
issues:
types:
- opened # Every new issue, regardless of labels or format
- reopened
- labeled # Re-process when devrel adds 'approved' to external issues
schedule:
- cron: '47 */6 * * *' # Fallback sweep every 6h
workflow_dispatch:
concurrency:
group: pm-suggestions
cancel-in-progress: false
jobs:
run:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure git
run: |
git config user.name "examples-bot"
git config user.email "noreply@deepgram.com"
# ── Permission gate ──────────────────────────────────────────────────
# Write access = act immediately.
# No write access = hold for devrel approval; don't run PM agent.
# Schedule/dispatch runs bypass the check (no user context).
- name: Check write permission
id: permission
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
EVENT="${{ github.event_name }}"
USERNAME="${{ github.event.issue.user.login }}"
# Schedule and dispatch runs always proceed
if [[ "$EVENT" == "schedule" || "$EVENT" == "workflow_dispatch" ]]; then
echo "gate=pass" >> $GITHUB_OUTPUT
echo "reason=scheduled" >> $GITHUB_OUTPUT
exit 0
fi
# If the 'approved' label was just added, treat as approved regardless of opener
LABEL="${{ github.event.label.name }}"
if [[ "$EVENT" == "issues" && "$LABEL" == "approved" ]]; then
echo "gate=pass" >> $GITHUB_OUTPUT
echo "reason=devrel-approved" >> $GITHUB_OUTPUT
exit 0
fi
# Check if the issue opener already has the 'approved' label (re-opened etc.)
HAS_APPROVED=$(gh issue view ${{ github.event.issue.number }} \
--repo ${{ github.repository }} \
--json labels --jq '[.labels[].name] | contains(["approved"])' 2>/dev/null || echo "false")
if [[ "$HAS_APPROVED" == "true" ]]; then
echo "gate=pass" >> $GITHUB_OUTPUT
echo "reason=already-approved" >> $GITHUB_OUTPUT
exit 0
fi
# Skip bots
if [[ "$USERNAME" == *"[bot]"* ]]; then
echo "gate=skip" >> $GITHUB_OUTPUT
echo "reason=bot" >> $GITHUB_OUTPUT
exit 0
fi
# Check write permission on this repo
IS_ORG_MEMBER=false
if gh api "orgs/deepgram/members/${USERNAME}" -i 2>/dev/null | head -1 | grep -q "204"; then
IS_ORG_MEMBER=true
fi
PERM=$(gh api "repos/${{ github.repository }}/collaborators/${USERNAME}/permission" \
--jq '.permission' 2>/dev/null || echo "none")
if [[ "$IS_ORG_MEMBER" == "true" || "$PERM" == "write" || "$PERM" == "maintain" || "$PERM" == "admin" ]]; then
echo "gate=pass" >> $GITHUB_OUTPUT
echo "reason=deepgram-member-or-collaborator" >> $GITHUB_OUTPUT
else
echo "gate=hold" >> $GITHUB_OUTPUT
echo "reason=not-deepgram-member" >> $GITHUB_OUTPUT
echo "username=$USERNAME" >> $GITHUB_OUTPUT
fi
# ── Hold: tag devrel for external suggestions ──────────────────────
- name: Hold for devrel approval
if: steps.permission.outputs.gate == 'hold'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
USERNAME="${{ steps.permission.outputs.username }}"
ISSUE="${{ github.event.issue.number }}"
# Only post once — skip if already held
ALREADY=$(gh issue view "$ISSUE" --repo ${{ github.repository }} \
--json labels --jq '[.labels[].name] | contains(["needs:approval"])' 2>/dev/null || echo "false")
if [[ "$ALREADY" == "true" ]]; then
echo "Already on hold — skipping duplicate comment"
exit 0
fi
gh issue edit "$ISSUE" --repo ${{ github.repository }} \
--add-label "needs:approval" 2>/dev/null || true
BODY="@deepgram/devrel — new suggestion from @${USERNAME} (no write access). Add the \`approved\` label to process it, or close to decline."
gh issue comment "$ISSUE" --repo ${{ github.repository }} --body "$BODY"
# ── Pass: run PM agent ────────────────────────────────────────────
- name: Route issue
if: steps.permission.outputs.gate == 'pass'
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
mode: agent
model: claude-opus-4-6
allowed_tools: "Bash,Read,Glob,Grep,WebSearch,WebFetch"
timeout_minutes: 15
direct_prompt: |
Read and execute instructions/pm-suggestions.md.
Context:
- Event: ${{ github.event_name }}
- Issue number (if triggered by issue): ${{ github.event.issue.number }}
- Repository: ${{ github.repository }}
- Trigger reason: ${{ steps.permission.outputs.reason }}
env:
KAPA_API_KEY: ${{ secrets.KAPA_API_KEY }}
KAPA_PROJECT_ID: ${{ vars.KAPA_PROJECT_ID }}