Our pipeline runs automatically on every push to developer or feature/** branches. It executes 6 stages sequentially - if any stage fails, the pipeline stops.
git push → BUILD → TEST → COVERAGE → LINT → SECURITY → DEPLOY
Quality Gates:
- Coverage: ≥75%
- Pylint: ≥7.5/10
What it does:
- Sets up Python 3.12
- Installs pytest, pylint, bandit
- Installs project dependencies from
requirements.txt - Caches packages for faster future runs
Fails if: Missing packages or version conflicts
What it does:
- Searches for test files in
tests/unit/,tests/integration/,tests/system/ - Runs all tests with pytest
- Generates HTML test report
- Times out after 5 minutes
Output:
🔍 Discovering test files...
Unit Tests: 14
Integration Tests: 7
System Tests: 6
Total Tests: 47
🚀 Running Complete Test Suite...
tests/unit/test_import_service.py ..............
tests/unit/test_stock_service.py ....................
====== 47 passed ======
Fails if: Any test fails
Fix locally:
pytest tests/ -vWhat it does:
- Runs pytest with coverage tracking on
services/,pages/,src/,app/ - Generates HTML, XML, and JSON reports
- Checks if coverage ≥75%
Output:
📊 Coverage: 90.10% (Threshold: 75%)
✅ Coverage threshold met!
Warning if: Coverage < 75% (doesn't fail, just warns)
Fix locally:
pytest --cov=services --cov-report=term-missing
# Write tests for uncovered linesWhat it does:
- Creates
.pylintrcconfig (ignores tests, max line 120 chars) - Finds Python files in
services/,pages/,src/,app/ - Runs pylint on each directory
- Calculates average score
Output:
📝 Running pylint...
✅ Found 5 Python files in services/
📊 Pylint Score: 10.0/10.0
✅ Lint quality gate passed!
Warning if: Score < 7.5 (doesn't fail, just warns)
Fix locally:
pylint services/*.py
# Fix: Add docstrings, remove whitespace, shorten linesWhat it does:
- Runs Bandit security scanner
- Scans
services/,pages/,src/,app/ - Skips low-priority checks (B101, B601)
- Generates JSON report
Output:
🔒 Running Bandit security scan...
High: 0, Medium: 2, Low: 5
✅ No high severity issues
Doesn't fail - only reports issues
Fix locally:
bandit -r services/
# Use parameterized queries, no hardcoded secretsOnly runs on: Push to developer branch (not feature branches)
What it does:
- Downloads all test/coverage/lint/security reports
- Packages source code + reports into ZIP
- Creates
DEPLOYMENT_INFO.mdwith commit details - Uploads as artifact (kept 90 days)
Output:
📦 Creating deployment package...
✅ services/
✅ requirements.txt
✅ Deployment package created
Before pushing:
# 1. Tests
pytest tests/ -v
# 2. Coverage
pytest --cov=services --cov-report=term-missing
# 3. Lint
pylint services/*.py
# 4. Security
pip install bandit
bandit -r services/Error: Could not find package 'pandas'
Fix: Add to requirements.txt, push again
FAILED tests/unit/test_cart.py::test_add_item
Fix:
pytest tests/unit/test_cart.py::test_add_item -v # See error
# Fix code or test
pytest tests/ -v # Verify
git add . && git commit -m "fix: test issue" && git push⚠️ Coverage is 68.5% (threshold: 75%)
Fix:
pytest --cov=services --cov-report=term-missing
# Shows uncovered lines like: 45-48, 67
# Write tests for those lines⚠️ Pylint score is 6.2 (threshold: 7.5)
Fix:
pylint services/*.py
# Common issues:
# - Add """Module docstring.""" at top
# - Remove trailing spaces
# - Break lines > 120 charactersAll Passing:
✅ Build - Install Dependencies
✅ Test - Run Test Suites (47 passed)
✅ Coverage - Code Coverage Analysis (90.10%)
✅ Lint - Static Code Analysis (10.0/10)
✅ Security - Vulnerability Scan (0 high)
✅ Deploy - Create Deployment Package
Test Failed:
✅ Build
❌ Test (1 failed)
⏭️ Coverage (skipped)
⏭️ Lint (skipped)
⏭️ Security (skipped)
⏭️ Deploy (skipped)
After pipeline runs, download from GitHub Actions → Artifacts:
test-report- HTML test resultscoverage-html-report- Coverage visualizationpylint-report- Lint analysisbandit-security-report- Security scan JSONdeployment-package-XX- Full deployment ZIP (developer branch only)
Concurrency: Only one pipeline runs per branch at a time (cancels old runs)
Caching: Pip packages cached to speed up runs (~30% faster)
Timeout: Tests timeout after 5 minutes to prevent hanging
No Failures on Warnings: Coverage/Lint below threshold show warnings but don't fail the pipeline
Smart Detection: Automatically finds test files and source directories
Last Updated: November 13, 2025
Continuous Integration (CI): Automatically testing code every time changes are pushed to the repository.
Continuous Deployment (CD): Automatically preparing code for deployment after it passes all quality checks.
- Platform: GitHub Actions
- Trigger: Automatic on every
git pushor Pull Request - Runtime: Ubuntu 22.04 (GitHub-hosted runners)
- Average Duration: 2-3 minutes
- Language: Python 3.12
Developer writes code → git add → git commit → git push
↓
GitHub detects push event
↓
CI/CD Pipeline starts automatically
The pipeline runs 6 sequential stages. Each stage must pass before moving to the next:
1. BUILD → 2. TEST → 3. COVERAGE → 4. LINT → 5. SECURITY → 6. DEPLOY
If any stage fails, the pipeline stops immediately and notifies the developer.
What it does:
- Checks out your code from GitHub
- Sets up Python 3.12 environment
- Installs all dependencies from
requirements.txt - Installs test tools from
tests/requirements-test.txt
Success Criteria:
- All packages install without errors
Common Failures:
- Missing dependency in requirements.txt
- Version conflicts between packages
- Network issues downloading packages
How to fix:
- Check requirements.txt has all needed packages
- Ensure compatible version numbers
- Re-run the pipeline
What it does:
- Runs pytest to discover all test files
- Executes all tests in order:
- Unit tests (test individual functions)
- Integration tests (test module interactions)
- System tests (test end-to-end workflows)
- Mocks database connections (no real DB needed)
- Reports which tests passed/failed
Success Criteria:
- 100% of tests must pass
- No test errors or failures
Example Output:
============================= test session starts ==============================
collected 47 items
tests/unit/test_import_service.py .............. (14 passed)
tests/unit/test_stock_service.py .................... (20 passed)
tests/integration/test_stock_import_integration.py ....... (7 passed)
tests/system/test_stock_import_system.py ...... (6 passed)
============================== 47 passed in 12.34s =============================Common Failures:
- Logic errors in code
- Incorrect test assertions
- Missing test fixtures
- Import errors
How to fix:
- Read the error message carefully
- Fix the failing test or code
- Run tests locally:
pytest tests/ -v - Push the fix
What it does:
- Re-runs tests with coverage tracking
- Measures which lines of code are executed during tests
- Calculates percentage of code covered by tests
- Generates coverage report
Success Criteria:
- Coverage must be ≥ 75%
Example Output:
Name Stmts Miss Cover
-----------------------------------------------------
services/import_service.py 120 6 95%
services/stock_service.py 150 10 93%
services/cart_service.py 80 0 100%
-----------------------------------------------------
TOTAL 350 16 90.10%
Common Failures:
- New code added without tests
- Coverage below 75% threshold
- Untested edge cases
How to fix:
- Write tests for uncovered code
- Check coverage locally:
pytest --cov=services --cov-report=term-missing - Add tests for the missing line numbers shown
- Push the new tests
What it does:
- Runs pylint on all Python files
- Checks coding standards (PEP 8)
- Looks for style issues:
- Trailing whitespace
- Lines longer than 100 characters
- Missing docstrings
- Unused imports
- Poor code structure
- Calculates a quality score out of 10
Success Criteria:
- Pylint score must be ≥ 7.5/10
Example Issues:
services/import_service.py:45:0: C0303: Trailing whitespace (trailing-whitespace)
services/stock_service.py:120:0: C0301: Line too long (110/100) (line-too-long)
services/cart_service.py:1:0: C0114: Missing module docstring (missing-module-docstring)
Common Failures:
- Code style violations
- Missing documentation
- Poorly formatted code
- Low pylint score
How to fix:
- Run pylint locally:
pylint services/*.py - Fix all reported issues
- Add docstrings to modules/functions
- Remove trailing whitespace
- Break long lines into multiple lines
- Push the cleaned code
Quick Fixes:
- Remove trailing whitespace: Use editor "trim trailing whitespace"
- Add module docstring: Add
"""Module description."""at top of file - Shorten lines: Break into multiple lines
What it does:
- Runs Bandit security scanner
- Looks for security vulnerabilities:
- SQL injection risks
- Hardcoded passwords/secrets
- Insecure functions (eval, exec)
- Weak cryptography
- File path vulnerabilities
- Categorizes by severity (High, Medium, Low)
Success Criteria:
- No High severity vulnerabilities
Example Issues:
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection
Severity: Medium Confidence: Low
Location: services/cart_service.py:45
Common Failures:
- SQL injection vulnerabilities
- Hardcoded credentials
- Insecure random number generation
- Unsafe file operations
How to fix:
- Use parameterized SQL queries (not string concatenation)
- Store credentials in environment variables (.env file)
- Use secure random generators
- Validate file paths
- Run locally:
bandit -r services/
Best Practices:
- ✅ Good:
db.execute("SELECT * FROM products WHERE id = %s", (product_id,)) - ❌ Bad:
db.execute(f"SELECT * FROM products WHERE id = {product_id}")
What it does:
- Validates all previous stages passed
- Checks build artifacts are created
- Confirms configuration is correct
- Marks code as deployment-ready
Success Criteria:
- All previous 5 stages passed
Common Failures:
- Previous stage failed (rarely fails on its own)
- Configuration issues
How to fix:
- Ensure all previous stages pass
- Check deployment configuration
Every code push must pass these thresholds:
| Quality Gate | Threshold | Purpose |
|---|---|---|
| Tests | 100% pass rate | Ensure code works correctly |
| Coverage | ≥ 75% | Ensure adequate testing |
| Lint | ≥ 7.5/10 | Ensure code quality |
| Security | 0 High issues | Ensure code is secure |
| Build | Success | Ensure dependencies work |
All gates must pass for code to be mergeable.
┌──────────────────────────────────────────────────┐
│ Developer: git push origin feature-branch │
└────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────┐
│ GitHub Server │
│ Receives push │
└────────┬─────────┘
│
▼
┌────────────────────────────────────────────────────┐
│ CI/CD PIPELINE STARTS │
└────────────────────────────────────────────────────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ Stage 1│ │ Stage 2│ │ Stage 3│
│ BUILD │→ │ TEST │→ │COVERAGE│
│ ✅ │ │ ✅ │ │ ✅ │
└────────┘ └────────┘ └────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ Stage 4│ │ Stage 5│ │ Stage 6│
│ LINT │→ │SECURITY│→ │ DEPLOY │
│ ✅ │ │ ✅ │ │ ✅ │
└────────┘ └────────┘ └────────┘
│
▼
┌──────────────────────┐
│ ✅ ALL CHECKS PASS │
│ Code ready to merge │
└──────────────────────┘
All Checks Passing:
✅ Build — Passed in 45s
✅ Test — Passed in 1m 15s
✅ Coverage — Passed in 1m 20s (90.10%)
✅ Lint — Passed in 30s (Score: 10.0/10)
✅ Security — Passed in 25s (0 issues)
✅ Deploy — Passed in 10s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All checks have passed
Check Failing:
✅ Build — Passed in 45s
❌ Test — Failed in 1m 5s
❌ Coverage — Not run (previous stage failed)
❌ Lint — Not run (previous stage failed)
❌ Security — Not run (previous stage failed)
❌ Deploy — Not run (previous stage failed)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Some checks were not successful
- Email: Sent on pipeline failure
- GitHub UI: Red ❌ or Green ✅ on PR
- Status Badge: Updates on README
Before pushing code, run these commands locally to catch issues early:
pytest tests/ -vpytest tests/ --cov=services --cov=pages --cov-report=term-missingpylint services/*.py --exit-zerobandit -r services/# Run everything at once
pytest tests/ -v --cov=services --cov-report=term
pylint services/*.py
bandit -r services/Symptom: "ERROR: Could not find a version that satisfies the requirement..."
Solution:
- Check
requirements.txtfor typos - Verify package names are correct
- Add missing dependencies
- Push updated requirements.txt
Symptom: "FAILED tests/unit/test_cart_service.py::test_add_to_cart"
Solution:
- Read the error message in pipeline logs
- Run test locally:
pytest tests/unit/test_cart_service.py::test_add_to_cart -v - Fix the failing test or code
- Verify:
pytest tests/ -v - Push the fix
Symptom: "Coverage is 65.0% (threshold: 75%)"
Solution:
- Run coverage locally:
pytest --cov=services --cov-report=term-missing - Look for uncovered line numbers
- Write tests for those lines
- Verify coverage improved:
pytest --cov=services - Push new tests
Symptom: "Pylint score is 6.5 (threshold: 7.5)"
Solution:
- Run pylint:
pylint services/*.py - Fix all reported issues:
- Add module docstrings
- Remove trailing whitespace
- Shorten long lines
- Remove unused imports
- Verify score:
pylint services/*.py - Push fixes
Symptom: "Bandit found 2 High severity issues"
Solution:
- Run bandit:
bandit -r services/ - Review security issues
- Fix vulnerabilities:
- Use parameterized queries
- Remove hardcoded secrets
- Validate inputs
- Verify:
bandit -r services/ - Push fixes
- Run tests locally:
pytest tests/ -v - Check coverage:
pytest --cov=services - Run linter:
pylint services/*.py - Fix all issues before pushing
- Commit with clear message:
git commit -m "feat: add stock alerts" - Push:
git push origin your-branch
- Write tests first (Test-Driven Development)
- Add docstrings to all functions
- Keep functions small (< 50 lines)
- Use meaningful variable names
- Follow PEP 8 style guide
- Avoid code duplication
- Don't panic - pipelines fail sometimes
- Read error messages carefully
- Fix one issue at a time
- Test locally before re-pushing
- Ask for help if stuck
The pipeline is defined in .github/workflows/ci.yml:
name: CI/CD Pipeline
on:
push:
branches: [ main, feature/** ]
pull_request:
branches: [ main ]
jobs:
build-test-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r tests/requirements-test.txt
- name: Run tests
run: pytest tests/ -v
- name: Check coverage
run: pytest tests/ --cov=services --cov-report=term
- name: Run linter
run: pylint services/*.py --fail-under=7.5
- name: Run security scan
run: bandit -r services/
- name: Deploy check
run: echo "Deployment ready"- ✅ Automatic Quality Control: No broken code gets merged
- ✅ Early Bug Detection: Find issues before code review
- ✅ Consistent Standards: Everyone follows same quality bar
- ✅ Fast Feedback: Know in 2-3 minutes if code has issues
- ✅ Documentation: Pipeline shows what "good code" means
- ✅ Team Confidence: Trust that merged code works
- ✅ Time Savings: Less time debugging production issues
| Metric | Value |
|---|---|
| Pipeline Success Rate | ~95% |
| Average Run Time | 2m 45s |
| Tests Executed | 47 per run |
| Code Coverage | 90.10% |
| Pylint Score | 10.0/10 |
| Security Issues | 0 |
A: Typically 2-3 minutes from push to completion.
A: No. All code must pass the pipeline to be merged.
A: Fix the issues locally, commit, and push again. The pipeline will re-run automatically.
A: You can run all the checks locally (tests, coverage, lint, security) but the full pipeline only runs on GitHub.
A: The pipeline runs on both push events and pull request events. This is normal.
A: Go to your PR → Click "Checks" tab → Click on failed stage → View logs.
The CI/CD pipeline is your automated quality assistant. It:
- ✅ Runs automatically on every push
- ✅ Tests your code thoroughly
- ✅ Checks code quality and coverage
- ✅ Scans for security issues
- ✅ Gives fast feedback
- ✅ Ensures only quality code is merged
Remember: The pipeline is here to help you write better code, not to block you. Use it as a learning tool to improve your skills!
Project: PESU POS Simulator
Team: Elevate
Platform: GitHub Actions
Last Updated: November 13, 2025