name: CI/CD Pipeline
on:
push:
branches: [ main, develop ]
tags: [ 'v*' ]
pull_request:
branches: [ main, develop ]
schedule:
# Run security scans weekly on Sundays at 2 AM UTC
- cron: '0 2 * * 0'
workflow_dispatch:
inputs:
run_integration:
description: 'Run integration tests'
required: false
default: false
type: boolean
run_cross_platform:
description: 'Run cross-platform tests'
required: false
default: false
type: boolean
jobs:
# Fast unit tests and code quality - always runs
test-and-quality:
name: Tests & Quality
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Lint with ruff
run: |
uv run ruff check src tests
uv run ruff format --check src tests
- name: Type check with mypy
run: |
uv run mypy src --ignore-missing-imports
- name: Run unit tests with coverage
run: |
uv run pytest -v -m "not integration" \
--cov=src \
--cov-report=xml \
--cov-report=html \
--cov-report=term-missing \
--cov-fail-under=40 \
--tb=short
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
file: ./coverage.xml
flags: unittests
fail_ci_if_error: false
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: |
htmlcov/
.coverage
coverage.xml
# Integration tests - runs on manual trigger or scheduled
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: test-and-quality
if: |
github.event.inputs.run_integration == 'true' ||
github.event_name == 'schedule' ||
contains(github.event.head_commit.message, '[integration]')
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Install Docker Compose
run: |
sudo apt-get update
sudo apt-get install -y docker-compose
- name: Run integration tests
run: |
uv run pytest tests/integration/ tests/test_ansible.py tests/test_full_stack_integration.py \
-v -m integration \
--tb=short
continue-on-error: true
# Cross-platform tests - runs on manual trigger or release
cross-platform:
name: Cross-Platform (${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: test-and-quality
if: |
github.event.inputs.run_cross_platform == 'true' ||
startsWith(github.ref, 'refs/tags/') ||
contains(github.event.head_commit.message, '[cross-platform]')
strategy:
fail-fast: false
matrix:
os: [windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Run core tests
run: |
uv run pytest tests/test_config.py tests/test_error_handling.py tests/test_database.py \
-v --tb=short
# Security scans - runs weekly and on releases
security:
name: Security Scan
runs-on: ubuntu-latest
needs: test-and-quality
if: |
github.event_name == 'schedule' ||
startsWith(github.ref, 'refs/tags/') ||
contains(github.event.head_commit.message, '[security]')
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --all-extras
- name: Run security scan with bandit
run: |
uv run bandit -r src -f json -o bandit-report.json || true
- name: Check dependencies with safety
run: |
uv run safety check --json || true
- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: bandit-report.json
# GitHub release - only on tags
release:
name: GitHub Release
runs-on: ubuntu-latest
needs: [test-and-quality]
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v4
- name: Create Release
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}