Skip to content

Latest commit

 

History

History
877 lines (661 loc) · 21.6 KB

File metadata and controls

877 lines (661 loc) · 21.6 KB

CI/CD Pipeline Guide

Overview

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

Stage 1: BUILD

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


Stage 2: TEST

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/ -v

Stage 3: COVERAGE

What 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 lines

Stage 4: LINT

What it does:

  • Creates .pylintrc config (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 lines

Stage 5: SECURITY

What 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 secrets

Stage 6: DEPLOY

Only 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.md with commit details
  • Uploads as artifact (kept 90 days)

Output:

📦 Creating deployment package...
✅ services/
✅ requirements.txt
✅ Deployment package created

Run Checks Locally

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/

Fixing Failures

❌ Build Fails

Error: Could not find package 'pandas'

Fix: Add to requirements.txt, push again


❌ Tests Fail

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 Warning

⚠️ 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

⚠️ Lint Warning

⚠️ 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 characters

GitHub Status

All 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)

Artifacts Downloaded

After pipeline runs, download from GitHub Actions → Artifacts:

  • test-report - HTML test results
  • coverage-html-report - Coverage visualization
  • pylint-report - Lint analysis
  • bandit-security-report - Security scan JSON
  • deployment-package-XX - Full deployment ZIP (developer branch only)

Key Features

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


What is CI/CD?

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.


Pipeline Technology

  • Platform: GitHub Actions
  • Trigger: Automatic on every git push or Pull Request
  • Runtime: Ubuntu 22.04 (GitHub-hosted runners)
  • Average Duration: 2-3 minutes
  • Language: Python 3.12

How It Works

Pipeline Trigger

Developer writes code → git add → git commit → git push
                                                    ↓
                                    GitHub detects push event
                                                    ↓
                                    CI/CD Pipeline starts automatically

Execution Flow

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.


The 6 Pipeline Stages

Stage 1: 🔧 BUILD - Environment Setup

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

Stage 2: 🧪 TEST - Automated Testing

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

Stage 3: 📊 COVERAGE - Code Coverage Analysis

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

Stage 4: 🔍 LINT - Code Quality Check

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

Stage 5: 🔒 SECURITY - Vulnerability Scanning

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}")

Stage 6: 🚀 DEPLOY - Deployment Readiness

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

Quality Gates Summary

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.


Visual Pipeline Flow

┌──────────────────────────────────────────────────┐
│  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 │
                               └──────────────────────┘

What Developers See

On GitHub Pull Request Page

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

Notifications

  • Email: Sent on pipeline failure
  • GitHub UI: Red ❌ or Green ✅ on PR
  • Status Badge: Updates on README

Running Pipeline Checks Locally

Before pushing code, run these commands locally to catch issues early:

1. Run Tests

pytest tests/ -v

2. Check Coverage

pytest tests/ --cov=services --cov=pages --cov-report=term-missing

3. Run Linter

pylint services/*.py --exit-zero

4. Run Security Scan

bandit -r services/

5. Run All Checks

# Run everything at once
pytest tests/ -v --cov=services --cov-report=term
pylint services/*.py
bandit -r services/

Troubleshooting Pipeline Failures

❌ Build Stage Fails

Symptom: "ERROR: Could not find a version that satisfies the requirement..."

Solution:

  1. Check requirements.txt for typos
  2. Verify package names are correct
  3. Add missing dependencies
  4. Push updated requirements.txt

❌ Test Stage Fails

Symptom: "FAILED tests/unit/test_cart_service.py::test_add_to_cart"

Solution:

  1. Read the error message in pipeline logs
  2. Run test locally: pytest tests/unit/test_cart_service.py::test_add_to_cart -v
  3. Fix the failing test or code
  4. Verify: pytest tests/ -v
  5. Push the fix

❌ Coverage Stage Fails

Symptom: "Coverage is 65.0% (threshold: 75%)"

Solution:

  1. Run coverage locally: pytest --cov=services --cov-report=term-missing
  2. Look for uncovered line numbers
  3. Write tests for those lines
  4. Verify coverage improved: pytest --cov=services
  5. Push new tests

❌ Lint Stage Fails

Symptom: "Pylint score is 6.5 (threshold: 7.5)"

Solution:

  1. Run pylint: pylint services/*.py
  2. Fix all reported issues:
    • Add module docstrings
    • Remove trailing whitespace
    • Shorten long lines
    • Remove unused imports
  3. Verify score: pylint services/*.py
  4. Push fixes

❌ Security Stage Fails

Symptom: "Bandit found 2 High severity issues"

Solution:

  1. Run bandit: bandit -r services/
  2. Review security issues
  3. Fix vulnerabilities:
    • Use parameterized queries
    • Remove hardcoded secrets
    • Validate inputs
  4. Verify: bandit -r services/
  5. Push fixes

Best Practices

✅ Before Pushing Code

  1. Run tests locally: pytest tests/ -v
  2. Check coverage: pytest --cov=services
  3. Run linter: pylint services/*.py
  4. Fix all issues before pushing
  5. Commit with clear message: git commit -m "feat: add stock alerts"
  6. Push: git push origin your-branch

✅ Writing Quality Code

  1. Write tests first (Test-Driven Development)
  2. Add docstrings to all functions
  3. Keep functions small (< 50 lines)
  4. Use meaningful variable names
  5. Follow PEP 8 style guide
  6. Avoid code duplication

✅ Handling Failures

  1. Don't panic - pipelines fail sometimes
  2. Read error messages carefully
  3. Fix one issue at a time
  4. Test locally before re-pushing
  5. Ask for help if stuck

Pipeline Configuration File

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"

Benefits of Our CI/CD Pipeline

  1. Automatic Quality Control: No broken code gets merged
  2. Early Bug Detection: Find issues before code review
  3. Consistent Standards: Everyone follows same quality bar
  4. Fast Feedback: Know in 2-3 minutes if code has issues
  5. Documentation: Pipeline shows what "good code" means
  6. Team Confidence: Trust that merged code works
  7. Time Savings: Less time debugging production issues

Success Metrics

Current Project Stats

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

Frequently Asked Questions

Q: How long does the pipeline take?

A: Typically 2-3 minutes from push to completion.

Q: Can I skip the pipeline?

A: No. All code must pass the pipeline to be merged.

Q: What if the pipeline fails?

A: Fix the issues locally, commit, and push again. The pipeline will re-run automatically.

Q: Can I run the pipeline locally?

A: You can run all the checks locally (tests, coverage, lint, security) but the full pipeline only runs on GitHub.

Q: Why did my push trigger the pipeline twice?

A: The pipeline runs on both push events and pull request events. This is normal.

Q: How do I see pipeline logs?

A: Go to your PR → Click "Checks" tab → Click on failed stage → View logs.


Summary

The CI/CD pipeline is your automated quality assistant. It:

  1. ✅ Runs automatically on every push
  2. ✅ Tests your code thoroughly
  3. ✅ Checks code quality and coverage
  4. ✅ Scans for security issues
  5. ✅ Gives fast feedback
  6. ✅ 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