name: Test Suite
on:
push:
branches: [ main, develop ]
tags: [ 'v*.*.*' ]
pull_request:
branches: [ main ]
jobs:
test-deckbuilder:
name: Test Deckbuilder Engine
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt', '**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Validate test environment
run: |
python -c "import src.deckbuilder.core.engine; print('Engine import successful')"
- name: Run deckbuilder unit tests
run: |
python -m pytest tests/deckbuilder/unit/ -v --tb=short
- name: Run deckbuilder integration tests
run: |
python -m pytest tests/deckbuilder/integration/ -v --tb=short
- name: Generate coverage report
run: |
python -m pytest tests/deckbuilder/ --cov=src/deckbuilder --cov-report=xml --cov-report=term-missing
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: deckbuilder
name: deckbuilder-coverage
fail_ci_if_error: false
test-mcp-server:
name: Test MCP Server
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Run MCP server tests
run: |
python -m pytest tests/mcp_server/ -v --tb=short
- name: Generate coverage report
run: |
python -m pytest tests/mcp_server/ --cov=src/mcp_server --cov-report=xml --cov-report=term-missing
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
file: ./coverage.xml
flags: mcp-server
name: mcp-server-coverage
fail_ci_if_error: false
test-integration:
name: Full Integration Tests
runs-on: ubuntu-latest
needs: [test-deckbuilder, test-mcp-server]
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Run full test suite
run: |
python -m pytest tests/ -v --cov=src --cov-report=xml --cov-report=html --tb=short --ignore=tests/test_mcp_template_discovery.py --ignore=tests/test_pattern_loader.py --ignore=tests/test_template_metadata.py --ignore=tests/test_template_recommendation.py
- name: Upload test artifacts
uses: actions/upload-artifact@v4
with:
name: test-reports
path: |
htmlcov/
coverage.xml
- name: Check coverage threshold
run: |
python -m pytest tests/ --cov=src --cov-fail-under=30 -k "not test_image_integration" --ignore=tests/test_mcp_template_discovery.py --ignore=tests/test_pattern_loader.py --ignore=tests/test_template_metadata.py --ignore=tests/test_template_recommendation.py
test-structured-frontmatter:
name: Test Structured Frontmatter Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
- name: Test structured frontmatter examples
run: |
# Skip CLI execution tests in CI, just validate patterns and coverage
echo "π Validating structured frontmatter patterns in CI environment"
python -c "
from pathlib import Path
import sys
sys.path.insert(0, str(Path('.').absolute()))
# Import pattern validation
from src.deckbuilder.templates.pattern_schema import PatternSchemaValidator
# Validate all patterns
patterns_dir = Path('src/deckbuilder/structured_frontmatter_patterns')
validator = PatternSchemaValidator()
results = validator.validate_all_patterns(patterns_dir)
if not results:
print('β
All structured frontmatter patterns are valid')
else:
print('β Found pattern validation errors:')
for filename, errors in results.items():
print(f' {filename}: {errors}')
sys.exit(1)
"
echo "β
Structured frontmatter pattern validation complete"
- name: Validate example file coverage
run: |
python -c "
from pathlib import Path
import json
# Check that we have examples for key layouts
test_files_dir = Path('src/deckbuilder/structured_frontmatter_patterns/test_files')
print(f'Checking example files in: {test_files_dir}')
key_examples = [
'example_title_slide.json',
'example_title_and_content.json',
'example_four_columns.json',
'example_table_only.json',
'example_comparison.json'
]
found_examples = 0
for example_file in key_examples:
file_path = test_files_dir / example_file
if file_path.exists():
print(f' β
Found: {example_file}')
found_examples += 1
# Validate JSON structure
try:
with open(file_path) as f:
data = json.load(f)
if 'slides' in data and len(data['slides']) > 0:
print(f' π Valid JSON with {len(data[\"slides\"])} slides')
else:
print(f' β οΈ Invalid structure in {example_file}')
except Exception as e:
print(f' β JSON error in {example_file}: {e}')
else:
print(f' β Missing: {example_file}')
print(f'Found {found_examples}/{len(key_examples)} key example files')
assert found_examples >= 4, f'Expected at least 4 key examples, found {found_examples}'
print('β
Example file validation complete')
"
- name: Validate master example files are current
run: |
python scripts/generate_master_examples.py
echo 'β
Master example files validated'
code-quality:
name: Code Quality Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .[dev]
pip install black flake8 mypy
- name: Run black code formatting check
run: |
black --check --line-length 200 src/ tests/
- name: Run flake8 linting
run: |
flake8 src/ tests/ --max-line-length=200 --ignore=E203,W503,E501,E304,W292 --exclude=tests/mcp_server/unit/test_content_optimization.py,tests/mcp_server/unit/test_content_analysis.py,src/deckbuilder/cli.py
- name: Run type checking with mypy
run: |
mypy src/ --ignore-missing-imports --show-error-codes || true # Allow to fail for now
- name: Validate CI workflow
run: |
echo "β
All code quality checks completed"
validate-package-build:
name: Validate Package Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-build-${{ hashFiles('**/requirements.txt', '**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-build-
${{ runner.os }}-pip-
- name: Install build tools
run: |
python -m pip install --upgrade pip
pip install build twine check-manifest
- name: Install package dependencies
run: |
pip install -e .[dev]
- name: Validate MANIFEST.in (will create if needed)
run: |
# Create MANIFEST.in if it doesn't exist for validation
if [ ! -f MANIFEST.in ]; then
echo "include README.md" > MANIFEST.in
echo "include LICENSE" >> MANIFEST.in
echo "recursive-include src *.py *.json" >> MANIFEST.in
echo "recursive-include src/placekitten/images *.png *.jpg *.jpeg" >> MANIFEST.in
echo "global-exclude *.pyc" >> MANIFEST.in
echo "global-exclude __pycache__" >> MANIFEST.in
fi
check-manifest || echo "MANIFEST.in validation completed with warnings"
- name: Build package
run: |
python -m build
ls -la dist/
- name: Check package integrity
run: |
twine check dist/*
- name: Test package installation in clean environment
run: |
# Create clean virtual environment
python -m venv test_env
source test_env/bin/activate
# Install built package
pip install dist/*.whl
# Test CLI functionality
deckbuilder --help
deckbuilder config --help
deckbuilder template || echo "Template command tested (expected to show no templates in clean env)"
# Test Python import (using installed package structure)
python -c "from deckbuilder.core.engine import Deckbuilder; print('β
Engine import successful')"
python -c "from placekitten import PlaceKitten; print('β
PlaceKitten import successful')"
# Test MCP server import (requires environment variables)
DECK_TEMPLATE_FOLDER=/tmp DECK_OUTPUT_FOLDER=/tmp python -c "from mcp_server.main import main; print('β
MCP server import successful')"
- name: Test CLI commands with sample data
run: |
source test_env/bin/activate
# Create sample markdown for testing
cat > sample_test.md << 'EOF'
---
layout: Title Slide
title: CLI Test Presentation
subtitle: Generated during build validation
---
EOF
# Test presentation creation (should work even without templates in clean env)
deckbuilder create sample_test.md --output "build_test" || echo "CLI creation tested (may fail without templates)"
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts-${{ github.sha }}
path: |
dist/
*.whl
*.tar.gz
retention-days: 7
- name: Clean up test environment
run: |
rm -rf test_env
rm -f sample_test.md
rm -f build_test.*.pptx || true
- name: Build validation summary
run: |
echo "β
Package build validation completed successfully!"
echo "π¦ Built packages:"
ls -la dist/
echo "π Package contents validated"
echo "π» CLI commands tested"
echo "π Ready for publishing pipeline"