🎯 AI-powered code quiz generator that blocks CI/CD pipelines until developers prove they understand their code
An automated quiz system to validate junior developers' knowledge before merging their code to production.
- Push code → Pipeline triggers automatically
- Quiz generation → A quiz is generated based on code changes (git diff)
- Pipeline blocked ⏸️ → Pipeline stops and waits for validation
- Answer the quiz → Developer answers the online MCQ
- Get the secret code → Code displayed only after answering correctly
- Validate quiz → Developer enters the secret code to unblock
- Pipeline continues ✅ → Tests and deployment can proceed
DiffQuiz works with both GitHub and GitLab. Choose your platform:
- GitHub: Use
.github/workflows/test.pipeline.yml - GitLab: Use
.gitlab-ci.yml
The generate_quiz.py Python file works with both platforms without modification.
DiffQuiz automatically generates technical quizzes based on code changes (git diff) to:
- ✅ Test actual understanding of modified code
- 🔒 Detect security risks (SQL injection, dangerous commands, etc.)
- 📚 Improve junior developers' skills
- 🛡️ Protect production from malicious or dangerous code
- Git diff analysis to generate relevant questions
- Automatic security risk detection
- Question count adapts to modification size
- Multi-language support (automatic detection)
- 📊 Real-time progress bar
- ✅ Question-by-question validation with instant feedback
- 💾 Automatic answer saving (localStorage)
- 🌙 Dark/light mode
- 🎉 Success animations
- 📋 Copy secret code button
- Answer-based secret code: Secret code is calculated from the hash of correct answers
- No secret code in initial HTML: Secret code is never present in HTML source code
- Server-side validation: Hash is calculated client-side only after answer validation
- SHA256 hash: Uses a fixed salt for CI/CD compatibility
- Exhaustive vulnerability detection
- GitHub: Automatic deployment on GitHub Pages
- GitLab: Automatic deployment on GitLab Pages
- Branch-based organization
- Public URL for each quiz
- Direct link to modified commit
- Python 3.11+
- GitHub or GitLab account with CI/CD enabled
- OpenAI API key (or Ollama server)
- Configured repository
git clone https://github.com/fxbravo/DiffQuiz.git
cd DiffQuizThe repository contains files for both GitHub and GitLab. Delete the one you don't use:
For GitHub:
- ✅ Keep
.github/workflows/test.pipeline.yml - ❌ Delete
gitlab-ci.yml
For GitLab:
- ✅ Keep
gitlab-ci.yml - ❌ Delete
.github/workflows/test.pipeline.yml
pip install -r requirements.txtDependencies include:
pydanticandpydantic-settings: Configuration and validationpytestandpytest-cov: Unit tests (optional for usage)
-
Configure secrets:
- Go to Settings → Secrets and variables → Actions
- Add
OPENAI_API_KEYsecret with your OpenAI API key
-
Configure GitHub Pages:
- Go to Settings → Pages
- Source:
gh-pagesbranch - Folder:
/ (root)
-
Configure permissions:
- Go to Settings → Actions → General
- Workflow permissions: Select "Read and write permissions"
-
Configure CI/CD variables:
- Go to Settings → CI/CD → Variables
- Add
OPENAI_API_KEYvariable with your OpenAI API key - Check "Mask variable" and "Protect variable" if needed
-
Configure GitLab Pages:
- The
pagesjob ingitlab-ci.ymldeploys automatically - URL will be:
https://[group].gitlab.io/[project]/ - Check in Settings → Pages that it's enabled
- The
┌─────────────────────────────────────────────────────────────┐
│ 1. Push code │
│ ↓ │
│ 2. Quiz generation (job: generate-quiz) │
│ • Git diff analysis │
│ • AI-powered question generation │
│ • Pages deployment │
│ ↓ │
│ 3. ⏸️ PIPELINE BLOCKED │
│ • Pipeline stops here │
│ • Quiz URL displayed in logs │
│ ↓ │
│ 4. Answer the quiz │
│ • Open quiz URL │
│ • Answer questions │
│ • Secret code calculated automatically after validation │
│ ↓ │
│ 5. Validate quiz (job: validate-quiz) │
│ • Copy displayed secret code │
│ • Enter secret code │
│ • Server-side validation (hash comparison) │
│ ↓ │
│ 6. ✅ Pipeline continues │
│ • Tests run (job: run-tests) │
│ • Deployment can continue │
└─────────────────────────────────────────────────────────────┘
- Push code: Workflow triggers automatically on each push to
main - Quiz generation: A quiz is generated based on modifications
- Quiz access: URL is displayed in workflow logs
- Answer quiz: Open URL and answer questions
- Validation: Copy secret code and validate via "Run workflow"
- Go to Actions → Test DiffQuiz Pipeline
- Click "Run workflow"
- Enter the secret code obtained after answering the quiz in
quiz_secretfield - Click "Run workflow" to validate
- Pipeline continues with tests
- Push code: Pipeline triggers automatically
- Quiz generation:
generate-quizjob generates the quiz - Quiz access: URL is displayed in job logs
- Answer quiz: Open URL and answer questions
- Validation: Copy secret code and validate via manual job
- Go to CI/CD → Pipelines
- Find the waiting pipeline (pause icon ⏸️)
- Click on "validate-quiz" job → "Play"
- In the popup, add the variable:
- Key:
QUIZ_SECRET - Value: Secret code obtained after answering the quiz
- Key:
- Click "Run job" to validate
- Pipeline continues with tests
DiffQuiz/
├── generate_quiz.py # Main quiz generation script
├── diffquiz/ # Modular Python package
│ ├── __init__.py # Package initialization
│ ├── config.py # Centralized configuration
│ ├── exceptions.py # Custom exceptions
│ ├── git_utils.py # Git utilities
│ ├── html_generator.py # HTML generation
│ ├── llm_client.py # LLM API client
│ ├── quiz_generator.py # Quiz generation
│ └── security.py # Security functions
├── tests/ # Unit tests
│ ├── __init__.py
│ ├── test_git_utils.py
│ ├── test_quiz_generator.py
│ └── test_security.py
├── .github/
│ ├── TROUBLESHOOTING_PAGES.md # GitHub Pages troubleshooting guide
│ └── workflows/
│ └── test.pipeline.yml # GitHub Actions workflow
├── gitlab-ci.yml # GitLab CI/CD workflow (template)
├── requirements.txt # Python dependencies
├── pytest.ini # pytest configuration
├── test-QCM.py # Demo file (vulnerabilities)
├── CHANGELOG.md # Version history
├── LICENSE # MIT License
└── README.md # Documentation
Important: Delete the workflow file for the platform you don't use:
- GitHub: Delete
gitlab-ci.yml - GitLab: Delete
.github/workflows/test.pipeline.yml
DiffQuiz automatically detects:
⚠️ Dangerous shell commands:rm -rf,rm -f,del /f, etc.⚠️ Destructive DB operations:DROP TABLE,DELETE FROM,TRUNCATE⚠️ SQL injections: Unprepared queries, string concatenation⚠️ XSS: Unescaped HTML output⚠️ Path traversal:../in file paths⚠️ Hardcoded secrets: Passwords, API keys in plain text⚠️ System commands:Runtime.exec(),ProcessBuilder⚠️ Insecure deserialization⚠️ Sensitive data logging⚠️ And much more...
- Toggle in top right corner
- Preference saved in browser
- Answers are saved automatically
- Resume possible after closing page
- Instant feedback after each answer
- Visual indicators (green = correct, red = incorrect)
- Explanations displayed automatically
- "Question X / Y" counter
- Visual progress bar
- Real-time updates
- Answer-based secret code: Secret code is the SHA256 hash of correct quiz answers
- No secret code in initial HTML: Secret code is never present in HTML source, even when inspecting the file
- Dynamic client-side calculation: Secret code is calculated only after correctly answering all questions
- Server-side validation: Client-side calculated hash is compared with expected hash stored in
quiz.env - Fixed salt: Uses a fixed salt (
DIFFQUIZ_SALT_2025) to ensure CI/CD workflow compatibility
- Generation: Correct answers hash is calculated server-side and stored in
quiz.env - Generated HTML: HTML contains only questions and correct answers (for validation), but not the secret code
- Client-side validation: After answering correctly, JavaScript calculates the hash and displays it as secret code
- CI/CD validation: Entered secret code is hashed and compared with expected hash in
quiz.env
- ✅ Impossible to extract secret code from HTML source
- ✅ Secret code only exists after complete answer validation
- ✅ Even when downloading HTML artifact, secret code remains inaccessible
- ✅ Server-side validation guarantees process integrity
Quizzes are organized by branch and accessible via Pages:
https://[username].github.io/[repo]/branches/[branch-name]/quiz/[run_id]/
https://[group].gitlab.io/[project]/branches/[branch-name]/quiz/[pipeline_id]/
Examples:
mainbranch:/branches/main/quiz/[id]/feature/loginbranch:/branches/feature-login/quiz/[id]/
LLM_API_KEY: OpenAI API key (required)LLM_API_URL: API URL (default: OpenAI)LLM_MODEL: Model to use (default: gpt-4o-mini)SSL_VERIFY: SSL verification (default: True)
The generation prompt can be modified in diffquiz/quiz_generator.py:
- Security risk detection
- Question types to generate
- Difficulty level
- Supported languages
- GitHub: Check that
OPENAI_API_KEYis configured in Settings → Secrets - GitLab: Check that
OPENAI_API_KEYis configured in Settings → CI/CD → Variables - Check workflow/pipeline logs for errors
- Ensure Pages is configured correctly
- GitHub: Check that GitHub Pages is enabled (Settings → Pages)
- GitLab: Check that GitLab Pages is enabled (
pagesjob must run) - Wait a few minutes for propagation
- Check URL in workflow/pipeline logs
- GitHub: Check that
gh-pagesbranch exists and Pages points to this branch - GitLab: Check that
pagesjob ran successfully - Check that deployment succeeded in logs
- GitHub: Check that
validate-quizjob hasif: github.event_name == 'workflow_dispatch' - GitLab: Check that
validate-quizjob haswhen: manualandallow_failure: false - Pipeline should stop after
generate-quizand wait for manual validation
- Check that test job depends on
validate-quizjob (vianeeds:) - Check that validation succeeded (correct secret code)
- Tests should only run if quiz is validated
DiffQuiz follows modern software development principles:
- ✅ SOLID: Modular architecture with clear responsibilities
- ✅ Clean Code: Readable, documented, and maintainable code
- ✅ KISS: Simplicity and clarity first
- ✅ DRY: No code duplication
- ✅ YAGNI: No unnecessary features
Contributions are welcome! Feel free to:
- Open an issue to report a bug
- Propose new features
- Submit a pull request
MIT License - See LICENSE file for more details.
A big thank you to Titi <3
DiffQuiz is designed to improve code quality and application security by training junior developers in an interactive and engaging way.
🎯 DiffQuiz: Answer questions before Production!