-
Notifications
You must be signed in to change notification settings - Fork 9
Add FAQ automation system with GitHub Actions integration #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
alexeygrigorev
merged 39 commits into
DataTalksClub:main
from
frederick-douglas-pearce:feature/faq-automation-clean
Oct 27, 2025
Merged
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
bdbadfa
Add FAQ automation system with GitHub Actions integration
frederick-douglas-pearce 2e223aa
Fix minsearch version requirement (0.0.7 instead of 0.4.1)
frederick-douglas-pearce 786d850
Configure setuptools to only package faq_automation
frederick-douglas-pearce 2f5f40e
Change default model to gpt-5-nano for structured output support
frederick-douglas-pearce c882962
Remove test artifacts and add *.egg-info/ to gitignore
frederick-douglas-pearce 2502ad7
Add *.egg-info/ to gitignore
frederick-douglas-pearce daea8fa
Add contribution banner to course pages
frederick-douglas-pearce 789404f
Increase contribution banner font size to match questions
frederick-douglas-pearce eab1597
Update issue template with dropdown for course selection
frederick-douglas-pearce c52a3a9
Add manual trigger for testing FAQ automation workflow
frederick-douglas-pearce d38e9c1
Fix issue number handling for manual workflow triggers
frederick-douglas-pearce a010417
Fix: Create FAQ bot branches from main instead of current branch
frederick-douglas-pearce e7f7faa
docs: Update Development section with correct uv commands and API keyβ¦
frederick-douglas-pearce efbad4d
fix: Correct uv commands in Makefile and improve issue body parsing
frederick-douglas-pearce 69f4f97
docs: Update README - remove Quick Start and correct LLM to GPT-5
frederick-douglas-pearce 05e3ec2
docs: Update issue links to DataTalksClub/faq repository
frederick-douglas-pearce b0a5f32
docs: Remove GitHub Discussions reference from Support section
frederick-douglas-pearce adafd4c
docs: Fix escaped backticks in CONTRIBUTING.md example code blocks
frederick-douglas-pearce 797d741
docs: Fix nested code blocks using 4 backticks for outer block
frederick-douglas-pearce a5566c5
docs: Update testing documentation links for consistency
frederick-douglas-pearce df1aa9f
docs: Remove outer code block from example to render link correctly
frederick-douglas-pearce b652fc2
docs: Add FAQ automation tests to tests/README.md
frederick-douglas-pearce ca8de38
refactor: Organize FAQ automation tests into classes
frederick-douglas-pearce e7f6212
docs: Add FAQ automation examples to test method examples
frederick-douglas-pearce 00f2782
docs: Update test commands to match Makefile and remove --extra dev
frederick-douglas-pearce 1032a77
Fix OpenAI API syntax to match notebook implementation
frederick-douglas-pearce 574af38
Replace JS parsing logic with Python in FAQ automation workflow
frederick-douglas-pearce ce8925a
Replace bash scripting with Python for GitHub Actions outputs
frederick-douglas-pearce c605fc6
Update workflow to use modern uv sync command
frederick-douglas-pearce 7966260
Simplify FAQ automation workflow by removing --course argument
frederick-douglas-pearce 08d614a
Fix workflow to use uv run for Python commands
frederick-douglas-pearce e98b56b
Remove dead code: parse_issue_body() and its tests
frederick-douglas-pearce b1728e7
Add answer content example to FAQ file format section
frederick-douglas-pearce 1341bef
Add course field to FAQ example in contributing guide
frederick-douglas-pearce c6ff515
Update test documentation to reflect full test suite scope
frederick-douglas-pearce ad44dc7
Add comprehensive integration tests for FAQ automation workflow
frederick-douglas-pearce f203777
Add auto-close for FAQ issues when PR is merged
frederick-douglas-pearce d9e1e82
docs: Document auto-close behavior for FAQ issues when PRs merge
frederick-douglas-pearce 56a99c3
refactor: Remove manual workflow trigger to simplify FAQ automation
frederick-douglas-pearce File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| name: FAQ Proposal | ||
| description: Propose a new FAQ entry or update to existing FAQ | ||
| title: "[FAQ] " | ||
| labels: ["faq-proposal"] | ||
| body: | ||
| - type: markdown | ||
| attributes: | ||
| value: | | ||
| ## FAQ Proposal | ||
|
|
||
| Thank you for helping improve our FAQ! Please provide a clear question and answer below. | ||
|
|
||
| Our FAQ bot will automatically analyze your proposal and determine if it should: | ||
| - Create a new FAQ entry | ||
| - Update an existing FAQ entry | ||
| - Mark as duplicate of an existing FAQ | ||
|
|
||
| - type: dropdown | ||
| id: course | ||
| attributes: | ||
| label: Course | ||
| description: Which course is this FAQ for? | ||
| options: | ||
| - machine-learning-zoomcamp | ||
| - data-engineering-zoomcamp | ||
| - llm-zoomcamp | ||
| - mlops-zoomcamp | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: textarea | ||
| id: question | ||
| attributes: | ||
| label: Question | ||
| description: What is the FAQ question? | ||
| placeholder: "How do I install the required dependencies?" | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: textarea | ||
| id: answer | ||
| attributes: | ||
| label: Answer | ||
| description: What is the answer to this question? | ||
| placeholder: | | ||
| To install the required dependencies, run: | ||
| ```bash | ||
| uv pip install -r requirements.txt | ||
| ``` | ||
| validations: | ||
| required: true | ||
|
|
||
| - type: checkboxes | ||
| id: checklist | ||
| attributes: | ||
| label: Checklist | ||
| description: Please confirm the following | ||
| options: | ||
| - label: I have searched existing FAQs and this question is not already answered | ||
| required: true | ||
| - label: The answer provides accurate, helpful information | ||
| required: true | ||
| - label: I have included any relevant code examples or links | ||
| required: false |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| 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: | ||
frederick-douglas-pearce marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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.` | ||
| }); | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,6 @@ | |
| _site | ||
| __pycache__ | ||
| .envrc | ||
| .ipynb_checkpoints/ | ||
| .ipynb_checkpoints/ | ||
| CLAUDE.md | ||
| *.egg-info/ | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| # Contributing to DataTalks.Club FAQ | ||
|
|
||
| Thank you for your interest in contributing to the DataTalks.Club FAQ! This guide will help you understand how to propose new FAQ entries or updates. | ||
|
|
||
| ## Proposing a New FAQ Entry | ||
|
|
||
| We have an automated system that helps maintain the FAQ repository. Here's how to propose a new FAQ entry: | ||
|
|
||
| ### 1. Create a New Issue | ||
|
|
||
| 1. Go to the [FAQ Proposal form](https://github.com/DataTalksClub/faq/issues/new?template=faq-proposal.yml) | ||
| 2. Fill out the form: | ||
| - **Course**: Which course this FAQ is for (e.g., `machine-learning-zoomcamp`) | ||
| - **Question**: The FAQ question | ||
| - **Answer**: A clear, helpful answer with examples if applicable | ||
| - Check the validation boxes | ||
|
|
||
| ### 2. Automated Processing | ||
|
|
||
| Once you submit your issue, our FAQ Bot will automatically: | ||
|
|
||
| 1. **Analyze your proposal** using AI to compare it with existing FAQs | ||
| 2. **Make a decision**: | ||
| - **NEW**: Create a new FAQ entry if the question isn't covered | ||
| - **UPDATE**: Update an existing FAQ if your proposal adds valuable context | ||
| - **DUPLICATE**: Mark as duplicate if the question is already fully answered | ||
|
|
||
| ### 3. What Happens Next | ||
|
|
||
| #### For NEW or UPDATE Decisions | ||
|
|
||
| - A Pull Request will be automatically created with the proposed changes | ||
| - The PR will include: | ||
| - The new or modified FAQ file(s) | ||
| - Explanation of why this action was chosen | ||
| - Section placement and reasoning | ||
| - A maintainer will review the PR | ||
| - Once approved and merged, your FAQ contribution will be live! | ||
| - The originating issue will be automatically closed when the PR is merged | ||
|
|
||
| #### For DUPLICATE Decisions | ||
|
|
||
| - The bot will comment on your issue with: | ||
| - Explanation of why it's considered a duplicate | ||
| - Link to the existing FAQ that covers your question | ||
| - Link to the source file | ||
| - The issue will be automatically closed | ||
| - If you believe this is incorrect, you can reopen and mention a maintainer | ||
|
|
||
| ## Writing Good FAQ Entries | ||
|
|
||
| ### Question Guidelines | ||
|
|
||
| - Be specific and clear | ||
| - Use the actual words students might search for | ||
| - Start with question words (How, What, When, Why, etc.) | ||
| - Examples: | ||
| - β "How do I install Python dependencies using uv?" | ||
| - β "Dependencies" | ||
|
|
||
| ### Answer Guidelines | ||
|
|
||
| - Start with a direct answer | ||
| - Include code examples when relevant | ||
| - Add links to documentation or resources | ||
| - Keep it concise but complete | ||
| - Use markdown formatting for readability | ||
|
|
||
| **Example:** | ||
|
|
||
| ### Course | ||
| machine-learning-zoomcamp | ||
|
|
||
| ### Question | ||
| How do I run the tests for this project? | ||
|
|
||
| ### Answer | ||
| To run all tests, use: | ||
|
|
||
| ```bash | ||
| make test | ||
| ``` | ||
|
|
||
| For unit tests only: | ||
|
|
||
| ```bash | ||
| make test-unit | ||
| ``` | ||
|
|
||
| For integration tests only: | ||
|
|
||
| ```bash | ||
| make test-int | ||
| ``` | ||
|
|
||
| See the [testing documentation](tests/README.md) for more details. | ||
|
|
||
| ## Manual Contributions | ||
|
|
||
| If you prefer to contribute directly via Pull Request: | ||
|
|
||
| 1. Fork the repository | ||
| 2. Create a new branch: `git checkout -b faq/your-topic` | ||
| 3. Add your FAQ file in the appropriate location: | ||
| - `_questions/{course}/{section}/{NNN}_{id}_{slug}.md` | ||
| 4. Follow the frontmatter format: | ||
|
|
||
| ```markdown | ||
| --- | ||
| id: abc123 | ||
| question: 'Your question here?' | ||
| sort_order: 10 | ||
| --- | ||
|
|
||
| Your answer content here. | ||
| ``` | ||
|
|
||
| 5. Update `_questions/{course}/_metadata.yaml` if adding a new section | ||
| 6. Run tests: `make test` | ||
| 7. Create a Pull Request | ||
|
|
||
| ## FAQ File Structure | ||
|
|
||
| FAQ files are organized as: | ||
|
|
||
| ``` | ||
| _questions/ | ||
| βββ machine-learning-zoomcamp/ | ||
| β βββ _metadata.yaml # Course configuration | ||
| β βββ general/ | ||
| β β βββ 001_abc123_when-does-course-start.md | ||
| β β βββ 002_def456_what-are-prerequisites.md | ||
| β βββ module-1/ | ||
| β βββ 001_xyz789_install-docker.md | ||
| β βββ 002_uvw456_docker-errors.md | ||
| βββ data-engineering-zoomcamp/ | ||
| βββ ... | ||
| ``` | ||
|
|
||
| ### Frontmatter Fields | ||
|
|
||
| - **id** (required): Unique 10-character identifier | ||
| - **question** (required): The FAQ question | ||
| - **sort_order** (required): Integer for ordering within section | ||
| - **images** (optional): Array of image objects for embedded images | ||
|
|
||
| ### Markdown Content | ||
|
|
||
| - Write the answer in markdown | ||
| - Use code blocks with language specifications | ||
| - Include links where helpful | ||
| - Keep formatting clean and readable | ||
|
|
||
| ## Questions or Issues? | ||
|
|
||
| If you have questions about contributing or encounter issues with the FAQ Bot: | ||
|
|
||
| 1. Check existing issues for similar questions | ||
| 2. Create a new issue with the "question" or "bug" label | ||
| 3. Tag a maintainer if urgent | ||
|
|
||
| Thank you for helping improve the DataTalks.Club FAQ! π |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.