website/.forgejo/workflows/pr-pricing-validation.yml

297 lines
11 KiB
YAML
Raw Normal View History

2025-06-20 10:46:11 +02:00
name: PR Pricing Validation
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- "hub/services/models/pricing.py"
- "hub/services/tests/test_pricing*.py"
- "hub/services/views/**"
- "hub/services/forms.py"
- "hub/services/admin/**"
jobs:
pricing-validation:
name: Validate Pricing Changes
runs-on: ubuntu-latest
steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.13"
- name: Install uv
uses: astral-sh/setup-uv@v3
with:
enable-cache: true
cache-dependency-glob: "uv.lock"
- name: Install dependencies
run: |
uv sync --extra dev
- name: Check for pricing model migrations
run: |
echo "::group::Checking for required database migrations"
# Check if pricing models were changed
if git diff --name-only origin/main...HEAD | grep -q "hub/services/models/pricing.py"; then
echo "📝 Pricing models were modified, checking for migrations..."
# Check if there are new migration files
if git diff --name-only origin/main...HEAD | grep -q "hub/services/migrations/"; then
echo "✅ Found migration files in the PR"
git diff --name-only origin/main...HEAD | grep "hub/services/migrations/" | head -5
else
echo "⚠️ Pricing models were changed but no migrations found"
echo "Please run: uv run --extra dev manage.py makemigrations"
echo "This will be treated as a warning, not a failure"
fi
else
echo " No pricing model changes detected"
fi
echo "::endgroup::"
- name: Run pricing tests with coverage
env:
DJANGO_SETTINGS_MODULE: hub.settings
run: |
echo "::group::Running pricing tests with coverage tracking"
# Run tests with coverage
uv run coverage run --source='hub/services/models/pricing,hub/services/views' \
manage.py test \
hub.services.tests.test_pricing \
hub.services.tests.test_pricing_edge_cases \
hub.services.tests.test_pricing_integration \
--verbosity=2
# Generate coverage report
uv run coverage report --show-missing --fail-under=85
# Generate HTML coverage report
uv run coverage html
echo "::endgroup::"
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: pr-pricing-coverage
path: htmlcov/
retention-days: 7
- name: Detect pricing calculation changes
run: |
echo "::group::Analyzing pricing calculation changes"
# Check if critical pricing methods were modified
CRITICAL_METHODS=(
"calculate_discount"
"calculate_final_price"
"get_price"
"get_unit_rate"
"get_base_fee"
)
echo "🔍 Checking for changes to critical pricing methods..."
changed_methods=()
for method in "${CRITICAL_METHODS[@]}"; do
if git diff origin/main...HEAD -- hub/services/models/pricing.py | grep -q "def $method"; then
changed_methods+=("$method")
echo "⚠️ Critical method '$method' was modified"
fi
done
if [ ${#changed_methods[@]} -gt 0 ]; then
echo ""
echo "🚨 CRITICAL PRICING METHODS CHANGED:"
printf ' - %s\n' "${changed_methods[@]}"
echo ""
echo "📋 Extra validation required:"
echo " 1. All pricing tests must pass"
echo " 2. Manual testing of price calculations recommended"
echo " 3. Consider adding regression tests for specific scenarios"
echo ""
echo "This will not fail the build but requires careful review."
else
echo "✅ No critical pricing methods were modified"
fi
echo "::endgroup::"
- name: Validate test additions
run: |
echo "::group::Validating test additions for pricing changes"
# Check if new pricing features have corresponding tests
python3 << 'EOF'
import subprocess
import re
def get_git_diff():
result = subprocess.run(
['git', 'diff', 'origin/main...HEAD', '--', 'hub/services/models/pricing.py'],
capture_output=True, text=True
)
return result.stdout
def get_test_diff():
result = subprocess.run(
['git', 'diff', 'origin/main...HEAD', '--', 'hub/services/tests/test_pricing*.py'],
capture_output=True, text=True
)
return result.stdout
pricing_diff = get_git_diff()
test_diff = get_test_diff()
# Look for new methods in pricing models
new_methods = re.findall(r'^\+\s*def\s+(\w+)', pricing_diff, re.MULTILINE)
new_classes = re.findall(r'^\+class\s+(\w+)', pricing_diff, re.MULTILINE)
# Look for new test methods
new_test_methods = re.findall(r'^\+\s*def\s+(test_\w+)', test_diff, re.MULTILINE)
print("📊 Analysis of pricing changes:")
if new_classes:
print(f" New classes: {', '.join(new_classes)}")
if new_methods:
print(f" New methods: {', '.join(new_methods)}")
if new_test_methods:
print(f" New test methods: {', '.join(new_test_methods)}")
if (new_classes or new_methods) and not new_test_methods:
print("⚠️ New pricing functionality detected but no new tests found")
print(" Consider adding tests for new features")
elif new_test_methods:
print("✅ New tests found alongside pricing changes")
else:
print(" No new pricing functionality detected")
EOF
echo "::endgroup::"
- name: Run backward compatibility check
env:
DJANGO_SETTINGS_MODULE: hub.settings
run: |
echo "::group::Checking backward compatibility of pricing changes"
# Create a simple backward compatibility test
cat << 'EOF' > check_compatibility.py
import os
import django
from decimal import Decimal
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hub.settings')
django.setup()
from hub.services.models.base import Currency, Term
from hub.services.models.providers import CloudProvider
from hub.services.models.services import Service
from hub.services.models.pricing import VSHNAppCatPrice, VSHNAppCatBaseFee, VSHNAppCatUnitRate
print("🔄 Testing backward compatibility of pricing API...")
try:
# Test basic model creation (should work with existing API)
provider = CloudProvider.objects.create(
name="BC Test", slug="bc-test", description="Test", website="https://test.com"
)
service = Service.objects.create(
name="BC Service", slug="bc-service", description="Test", features="Test"
)
price_config = VSHNAppCatPrice.objects.create(
service=service,
variable_unit=VSHNAppCatPrice.VariableUnit.RAM,
term=Term.MTH
)
VSHNAppCatBaseFee.objects.create(
vshn_appcat_price_config=price_config,
currency=Currency.CHF,
amount=Decimal('50.00')
)
VSHNAppCatUnitRate.objects.create(
vshn_appcat_price_config=price_config,
currency=Currency.CHF,
service_level=VSHNAppCatPrice.ServiceLevel.GUARANTEED,
amount=Decimal('5.0000')
)
# Test basic price calculation
result = price_config.calculate_final_price(Currency.CHF, 'GA', 4)
if result and 'total_price' in result:
print(f"✅ Basic price calculation works: {result['total_price']} CHF")
else:
print("❌ Price calculation API may have changed")
exit(1)
# Test price retrieval methods
base_fee = price_config.get_base_fee(Currency.CHF)
unit_rate = price_config.get_unit_rate(Currency.CHF, 'GA')
if base_fee and unit_rate:
print("✅ Price retrieval methods work correctly")
else:
print("❌ Price retrieval API may have changed")
exit(1)
print("🎉 Backward compatibility check passed!")
except Exception as e:
print(f"❌ Backward compatibility issue detected: {e}")
exit(1)
EOF
uv run python check_compatibility.py
echo "::endgroup::"
- name: Generate pricing test summary
if: always()
run: |
echo "::group::Pricing Test Summary"
echo "## 🧮 Pricing Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Count test files and methods
total_test_files=$(find hub/services/tests -name "test_pricing*.py" | wc -l)
total_test_methods=$(grep -r "def test_" hub/services/tests/test_pricing*.py | wc -l)
echo "- **Test Files**: $total_test_files pricing-specific test files" >> $GITHUB_STEP_SUMMARY
echo "- **Test Methods**: $total_test_methods individual test methods" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Check if any pricing files were changed
if git diff --name-only origin/main...HEAD | grep -q "pricing"; then
echo "### 📝 Pricing-Related Changes Detected" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The following pricing-related files were modified:" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
git diff --name-only origin/main...HEAD | grep "pricing" | sed 's/^/- /' >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ All pricing tests have been executed to validate these changes." >> $GITHUB_STEP_SUMMARY
else
echo "### No Pricing Changes" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No pricing-related files were modified in this PR." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Pricing validation completed at $(date)*" >> $GITHUB_STEP_SUMMARY
echo "::endgroup::"