CI/CD Pipeline #145
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
| 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" |