Skip to content

CI/CD Pipeline

CI/CD Pipeline #145

Workflow file for this run

name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
# Run daily at 2 AM UTC
- cron: '0 2 * * *'
# Cancel in-progress runs for the same PR/branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PYTHON_VERSION: '3.13'
UV_VERSION: '0.5.20'
jobs:
# ==========================================================================
# Code Quality Checks
# ==========================================================================
code-quality:
name: Code Quality (Ruff, MyPy)
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python ${{ env.PYTHON_VERSION }}
run: uv python install ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
uv venv && uv pip install -r requirements-dev.txt
- name: Run Ruff linter
run: |
uv run ruff check . --output-format=github
- name: Run Ruff formatter check
run: |
uv run ruff format --check .
- name: Run MyPy type checking
run: |
uv run mypy . --ignore-missing-imports --show-error-codes
continue-on-error: true
# ==========================================================================
# Security Scanning
# ==========================================================================
security:
name: Security Scanning
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ env.UV_VERSION }}
- name: Set up Python ${{ env.PYTHON_VERSION }}
run: uv python install ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
uv venv && uv pip install -r requirements-dev.txt
- name: Run Bandit security scanner
continue-on-error: true
run: |
uv run bandit -r . -f json -o bandit-report.json || true
uv run bandit -r . -f txt || true
- name: Upload Bandit results
uses: actions/upload-artifact@v4
if: always()
with:
name: bandit-security-report
path: bandit-report.json
- name: Run Safety vulnerability check
run: |
uv run safety check --json > safety-report.json || true
uv run safety check
continue-on-error: true
- name: Run pip-audit
run: |
uv run pip-audit --format json > pip-audit-report.json || true
uv run pip-audit
continue-on-error: true
- name: GitLeaks secret scanning
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trufflehog secret scanning
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --debug --only-verified
# ==========================================================================
# Testing Matrix (Python versions & OS)
# ==========================================================================
test:
name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
cache-dependency-glob: "requirements*.txt"
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install dependencies
run: |
uv venv
uv pip install -r requirements.txt -r requirements-dev.txt
uv pip install -e .
- name: Run tests with coverage
run: |
uv run pytest tests/ \
--cov=. \
--cov-report=xml \
--cov-report=html \
--cov-report=term-missing \
--junitxml=pytest-report.xml \
-v
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
if: matrix.os == 'ubuntu-latest' && matrix.python-version == env.PYTHON_VERSION
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
continue-on-error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-${{ matrix.os }}-py${{ matrix.python-version }}
path: |
pytest-report.xml
htmlcov/
coverage.xml
# ==========================================================================
# Docker Build & Test
# ==========================================================================
docker:
name: Docker Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v6
with:
context: .
push: false
tags: offensive-toolkit:test
cache-from: type=gha
cache-to: type=gha,mode=max
load: true
- name: Test Docker image
run: |
docker run --rm offensive-toolkit:test python -c "from offensive_toolkit import reconnaissance; print('Import test: OK')"
docker run --rm offensive-toolkit:test python -c "from offensive_toolkit import web_security; print('Import test: OK')"
docker run --rm offensive-toolkit:test python -c "from offensive_toolkit import utils; print('Import test: OK')"
# ==========================================================================
# Documentation Build
# ==========================================================================
docs:
name: Documentation Build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ env.UV_VERSION }}
- name: Set up Python ${{ env.PYTHON_VERSION }}
run: uv python install ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
uv venv && uv pip install -r requirements-dev.txt
- name: Build documentation
run: |
# Sphinx documentation build (when docs/conf.py exists)
if [ -f "docs/conf.py" ]; then
uv run sphinx-build -W -b html docs docs/_build/html
else
echo "No Sphinx documentation found, skipping"
fi
- name: Upload documentation
uses: actions/upload-artifact@v4
if: always()
with:
name: documentation
path: docs/_build/html
# ==========================================================================
# Dependency Audit
# ==========================================================================
dependencies:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install UV
uses: astral-sh/setup-uv@v4
with:
version: ${{ env.UV_VERSION }}
- name: Set up Python ${{ env.PYTHON_VERSION }}
run: uv python install ${{ env.PYTHON_VERSION }}
- name: Install dependencies
run: |
uv venv && uv pip install -r requirements.txt -r requirements-dev.txt
- name: Check for dependency updates
run: |
uv run pip list --outdated
- name: Generate dependency tree
run: |
pip install uv run pipdeptree
uv run pipdeptree > dependency-tree.txt
- name: Upload dependency tree
uses: actions/upload-artifact@v4
with:
name: dependency-tree
path: dependency-tree.txt
# ==========================================================================
# Summary Status Check
# ==========================================================================
ci-success:
name: CI Success
runs-on: ubuntu-latest
needs: [code-quality, security, test, docker, docs, dependencies]
if: always()
steps:
- name: Check job status
run: |
if [ "${{ needs.code-quality.result }}" != "success" ] || \
[ "${{ needs.test.result }}" != "success" ] || \
[ "${{ needs.docker.result }}" != "success" ]; then
echo "CI pipeline failed"
exit 1
fi
echo "CI pipeline passed successfully"