FAQ Automation #3
  
    
      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: FAQ Automation | |
| on: | |
| issues: | |
| types: [opened] | |
| permissions: | |
| contents: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| process-faq-proposal: | |
| if: contains(github.event.issue.labels.*.name, 'faq-proposal') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.13' | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| - name: Install dependencies | |
| run: | | |
| uv sync --no-dev | |
| - name: Fetch issue body | |
| id: fetch_issue | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const body = context.payload.issue.body || ''; | |
| // Save issue body to file for Python to parse | |
| const fs = require('fs'); | |
| fs.writeFileSync('/tmp/issue_body.txt', body); | |
| console.log('Fetched issue body, saved to /tmp/issue_body.txt'); | |
| - name: Process FAQ with AI | |
| id: process | |
| env: | |
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | |
| run: | | |
| # Run FAQ automation CLI with full issue body | |
| uv run python -m faq_automation.cli \ | |
| --issue-body "$(cat /tmp/issue_body.txt)" \ | |
| --issue-number ${{ github.event.issue.number }} \ | |
| --model "gpt-5-nano" \ | |
| --output-dir /tmp | |
| # Write decision output to GitHub Actions | |
| uv run scripts/write_faq_decision_output.py | |
| - name: Handle NEW or UPDATE action | |
| if: fromJson(steps.process.outputs.decision).action != 'DUPLICATE' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const decision = ${{ steps.process.outputs.decision }}; | |
| const action = decision.action; | |
| const issueNumber = decision.issue_number; | |
| const prBody = decision.pr_body; | |
| const filePath = decision.file_path; | |
| // Create branch name | |
| const branchName = `faq-bot/issue-${issueNumber}`; | |
| // Configure git | |
| await exec.exec('git', ['config', 'user.name', 'FAQ Bot']); | |
| await exec.exec('git', ['config', 'user.email', '[email protected]']); | |
| // Fetch and checkout main, then create new branch from it | |
| await exec.exec('git', ['fetch', 'origin', 'main']); | |
| await exec.exec('git', ['checkout', 'main']); | |
| await exec.exec('git', ['checkout', '-b', branchName]); | |
| // Add modified files | |
| await exec.exec('git', ['add', filePath]); | |
| // Commit changes | |
| const commitMsg = `${action}: ${decision.decision.question.substring(0, 72)}`; | |
| await exec.exec('git', ['commit', '-m', commitMsg]); | |
| // Push branch | |
| await exec.exec('git', ['push', 'origin', branchName]); | |
| // Create pull request | |
| const { data: pr } = await github.rest.pulls.create({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| title: `[FAQ Bot] ${action}: ${decision.decision.question.substring(0, 72)}`, | |
| head: branchName, | |
| base: 'main', | |
| body: `${prBody}\n\nCloses #${issueNumber}` | |
| }); | |
| // Comment on issue with PR link | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body: `✅ FAQ ${action} proposal created in PR #${pr.number}\n\nPlease review and approve the changes.` | |
| }); | |
| - name: Handle DUPLICATE action | |
| if: fromJson(steps.process.outputs.decision).action == 'DUPLICATE' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const decision = ${{ steps.process.outputs.decision }}; | |
| const comment = decision.comment; | |
| const issueNumber = decision.issue_number; | |
| // Post comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body: comment | |
| }); | |
| // Close issue | |
| await github.rest.issues.update({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| state: 'closed', | |
| state_reason: 'completed' | |
| }); | |
| - name: Handle errors | |
| if: failure() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const issueNumber = context.payload.issue.number; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: issueNumber, | |
| body: `❌ FAQ Bot encountered an error processing this proposal.\n\nPlease check the [workflow run](${context.payload.repository.html_url}/actions/runs/${context.runId}) for details.\n\nA maintainer will review this manually.` | |
| }); |