Engineer #197
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Engineer | |
| # Builds new examples from the queue, runs tests, and opens the PR. | |
| # The engineer does its own Kapa research — no separate researcher step needed. | |
| # Only opens a PR when tests pass (or documents what failed after one fix attempt). | |
| on: | |
| issues: | |
| types: [labeled] # Fires when action:generate or action:research is applied | |
| schedule: | |
| - cron: '27 */4 * * *' # Fallback sweep every 4h (catches missed label events) | |
| workflow_dispatch: | |
| inputs: | |
| issue_number: | |
| description: 'Queue issue number to build (optional)' | |
| required: false | |
| jobs: | |
| run: | |
| if: > | |
| github.event_name == 'schedule' || | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'issues' && | |
| (contains(github.event.issue.labels.*.name, 'action:generate') || | |
| contains(github.event.issue.labels.*.name, 'action:research'))) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: write | |
| issues: write | |
| statuses: 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" | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: latest | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| - name: Install Bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Install Deno | |
| uses: denoland/setup-deno@v2 | |
| with: | |
| deno-version: v2.x | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.22' | |
| - name: Check actor is a team member | |
| id: auth | |
| if: github.event_name == 'issues' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| ACTOR="${{ github.actor }}" | |
| if [[ "$ACTOR" == *"[bot]"* ]] || [[ "$ACTOR" == "github-actions" ]]; then | |
| echo "allowed=true" >> $GITHUB_OUTPUT; exit 0 | |
| fi | |
| IS_ORG_MEMBER=false | |
| if gh api "orgs/deepgram/members/${ACTOR}" -i 2>/dev/null | head -1 | grep -q "204"; then | |
| IS_ORG_MEMBER=true | |
| fi | |
| PERM=$(gh api "repos/${{ github.repository }}/collaborators/${ACTOR}/permission" \ | |
| --jq '.permission' 2>/dev/null || echo "none") | |
| if [[ "$IS_ORG_MEMBER" == "true" || "$PERM" == "write" || "$PERM" == "maintain" || "$PERM" == "admin" ]]; then | |
| echo "allowed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "allowed=false" >> $GITHUB_OUTPUT | |
| echo "Actor $ACTOR not a Deepgram org member or repo collaborator — silently exiting" | |
| fi | |
| - name: Get date | |
| id: date | |
| run: echo "date=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT | |
| - name: Fetch latest Deepgram SDK versions | |
| id: sdk | |
| run: | | |
| latest() { curl -sf "https://api.github.com/repos/deepgram/$1/releases/latest" | jq -r '.tag_name // "unknown"'; } | |
| echo "python=$(latest deepgram-python-sdk)" >> $GITHUB_OUTPUT | |
| echo "js=$(latest deepgram-js-sdk)" >> $GITHUB_OUTPUT | |
| echo "go=$(latest deepgram-go-sdk)" >> $GITHUB_OUTPUT | |
| echo "java=$(latest deepgram-java-sdk)" >> $GITHUB_OUTPUT | |
| echo "rust=$(latest deepgram-rust-sdk)" >> $GITHUB_OUTPUT | |
| echo "dotnet=$(latest deepgram-dotnet-sdk)" >> $GITHUB_OUTPUT | |
| echo "cli=$(latest cli)" >> $GITHUB_OUTPUT | |
| cat $GITHUB_OUTPUT | grep -E "^(python|js|go|java|rust|dotnet|cli)=" | |
| - name: Check back pressure | |
| id: backpressure | |
| if: steps.auth.outputs.allowed != 'false' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| READY=$(gh pr list --repo ${{ github.repository }} --state open \ | |
| --label "status:review-passed" \ | |
| --json number --jq 'length' 2>/dev/null || echo "0") | |
| echo "PRs ready to merge: $READY" | |
| if [ "$READY" -ge 5 ]; then | |
| echo "blocked=true" >> $GITHUB_OUTPUT | |
| echo "⏸ Back pressure: $READY PRs waiting for merge — skipping" | |
| else | |
| echo "blocked=false" >> $GITHUB_OUTPUT | |
| echo "✓ Pipeline has capacity ($READY/5 slots used)" | |
| fi | |
| - name: Build, test, and open PR | |
| if: steps.auth.outputs.allowed != 'false' && steps.backpressure.outputs.blocked != 'true' | |
| 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,Write,Edit,Glob,Grep,WebSearch,WebFetch" | |
| timeout_minutes: 60 | |
| direct_prompt: | | |
| Read and execute instructions/engineer.md. | |
| Context: | |
| - Today's date: ${{ steps.date.outputs.date }} | |
| - Repository: ${{ github.repository }} | |
| - Trigger: ${{ github.event_name }} | |
| - Issue number (if triggered by issue): ${{ github.event.issue.number }} | |
| - Manual issue override: ${{ inputs.issue_number }} | |
| REQUIRED — use EXACTLY these Deepgram SDK versions, no older: | |
| - Python: deepgram-sdk==${{ steps.sdk.outputs.python }} (requirements.txt) | |
| - JavaScript: @deepgram/sdk@${{ steps.sdk.outputs.js }} (package.json) | |
| - Go: ${{ steps.sdk.outputs.go }} (go.mod) | |
| - Java: ${{ steps.sdk.outputs.java }} (pom.xml/build.gradle) | |
| - Rust: ${{ steps.sdk.outputs.rust }} (Cargo.toml) | |
| - .NET: ${{ steps.sdk.outputs.dotnet }} (*.csproj) | |
| - CLI: ${{ steps.sdk.outputs.cli }} | |
| Pin Python with == not >=. Pin JS with the exact version (no ^ or ~). | |
| env: | |
| KAPA_API_KEY: ${{ secrets.KAPA_API_KEY }} | |
| KAPA_PROJECT_ID: ${{ vars.KAPA_PROJECT_ID }} | |
| DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }} | |
| TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }} | |
| TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }} | |
| TWILIO_PHONE_NUMBER: ${{ secrets.TWILIO_PHONE_NUMBER }} | |
| LIVEKIT_URL: ${{ secrets.LIVEKIT_URL }} | |
| LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }} | |
| LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }} | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }} | |
| DISCORD_CLIENT_ID: ${{ secrets.DISCORD_CLIENT_ID }} | |
| VONAGE_APPLICATION_ID: ${{ secrets.VONAGE_APPLICATION_ID }} | |
| VONAGE_PRIVATE_KEY: ${{ secrets.VONAGE_PRIVATE_KEY }} | |
| DAILY_API_KEY: ${{ secrets.DAILY_API_KEY }} | |
| PIPECAT_API_KEY: ${{ secrets.PIPECAT_API_KEY }} | |
| SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} | |
| SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} | |
| TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} | |
| ZOOM_ACCOUNT_ID: ${{ secrets.ZOOM_ACCOUNT_ID }} | |
| ZOOM_CLIENT_ID: ${{ secrets.ZOOM_CLIENT_ID }} | |
| ZOOM_CLIENT_SECRET: ${{ secrets.ZOOM_CLIENT_SECRET }} | |
| ZOOM_WEBHOOK_SECRET_TOKEN: ${{ secrets.ZOOM_WEBHOOK_SECRET_TOKEN }} |