name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] release: types: [ published ] env: PYTHON_VERSION: "3.11" POETRY_VERSION: "1.7.1" jobs: code-quality: name: Code Quality Checks runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Cache pip dependencies uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-pip- - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e ".[dev]" - name: Run Ruff (Linting) run: ruff check src tests --output-format=github - name: Run Ruff (Formatting) run: ruff format src tests --check - name: Run MyPy (Type Checking) run: mypy src - name: Check imports with isort run: ruff check --select I src tests security-scan: name: Security Scanning runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e ".[dev]" pip install safety bandit - name: Run Safety (Dependency vulnerability scan) run: safety check --json --output safety-report.json continue-on-error: true - name: Run Bandit (Security linting) run: bandit -r src/ -f json -o bandit-report.json continue-on-error: true - name: Upload Security Reports uses: actions/upload-artifact@v3 if: always() with: name: security-reports path: | safety-report.json bandit-report.json test: name: Tests runs-on: ubuntu-latest strategy: matrix: python-version: ["3.11", "3.12"] services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: guardden_test POSTGRES_USER: guardden_test POSTGRES_DB: guardden_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Cache pip dependencies uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-${{ matrix.python-version }}-pip- - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e ".[dev]" - name: Set up test environment env: GUARDDEN_DISCORD_TOKEN: "test_token_12345678901234567890123456789012345" GUARDDEN_DATABASE_URL: "postgresql://guardden_test:guardden_test@localhost:5432/guardden_test" GUARDDEN_AI_PROVIDER: "none" GUARDDEN_LOG_LEVEL: "DEBUG" run: | python -c " import os os.environ['GUARDDEN_DISCORD_TOKEN'] = 'test_token_12345678901234567890123456789012345' os.environ['GUARDDEN_DATABASE_URL'] = 'postgresql://guardden_test:guardden_test@localhost:5432/guardden_test' print('Test environment configured') " - name: Run tests with coverage env: GUARDDEN_DISCORD_TOKEN: "test_token_12345678901234567890123456789012345" GUARDDEN_DATABASE_URL: "postgresql://guardden_test:guardden_test@localhost:5432/guardden_test" GUARDDEN_AI_PROVIDER: "none" GUARDDEN_LOG_LEVEL: "DEBUG" run: | pytest --cov=src/guardden --cov-report=xml --cov-report=html --cov-report=term-missing - name: Upload coverage reports uses: actions/upload-artifact@v3 if: matrix.python-version == '3.11' with: name: coverage-reports path: | coverage.xml htmlcov/ build-docker: name: Build Docker Image runs-on: ubuntu-latest needs: [code-quality, test] 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@v5 with: context: . push: false tags: guardden:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max build-args: | INSTALL_AI=false - name: Build Docker image with AI uses: docker/build-push-action@v5 with: context: . push: false tags: guardden-ai:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max build-args: | INSTALL_AI=true - name: Test Docker image run: | docker run --rm guardden:${{ github.sha }} python -m guardden --help