Skip to content

Fix tutorial and add automated validation #6

Fix tutorial and add automated validation

Fix tutorial and add automated validation #6

name: Validate Tutorial
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
validate-tutorial:
runs-on: ubuntu-latest
defaults:
run:
working-directory: examples/tenant_tutorial
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: root
POSTGRES_DB: tenant_tutorial
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"
- name: Change to tutorial directory
run: pwd # Just to verify we're in the right directory
- name: Create virtual environment and install dependencies
run: |
uv venv
uv pip sync requirements.txt
- name: Verify database connection
run: |
echo "SELECT 1" | uv run python manage.py dbshell
- name: Run initial migrations
run: |
uv run python manage.py migrate_schemas --shared
- name: Create public tenant
run: |
uv run python manage.py create_client public localhost "Tutorial Public Tenant" --description "Public tenant for tutorial validation"
- name: Create sample tenants
run: |
uv run python manage.py create_client tenant1 tenant1.example.com "Tenant 1 - Test Company" --description "First test tenant for validation"
uv run python manage.py create_client tenant2 tenant2.example.com "Tenant 2 - Another Company" --description "Second test tenant for validation"
- name: Verify tenants were created
run: |
uv run python manage.py list_tenants
# Verify we have exactly 3 tenants (public + 2 test tenants)
tenant_count=$(uv run python manage.py list_tenants | grep -E '^(public|tenant1|tenant2)' | wc -l)
if [ "$tenant_count" != "3" ]; then
echo "Expected 3 tenants, found $tenant_count"
exit 1
fi
echo "All tenants created successfully"
- name: Start Django development server
run: |
uv run gunicorn -D -p django_server.pid -b 0.0.0.0:8000 tenant_tutorial.wsgi:application
# Wait for server to start
sleep 10
# Check if server is running
if ! kill -0 $(cat django_server.pid) 2>/dev/null; then
echo "Server failed to start"
exit 1
fi
- name: Test public tenant endpoint
run: |
response=$(curl -s -w "%{http_code}" -H "Host: localhost" http://localhost:8000/ -o /tmp/public_response.html)
echo "Public tenant response code: $response"
if [ "$response" != "200" ]; then
echo "Public tenant test failed with response code: $response"
echo "Response content:"
cat /tmp/public_response.html
exit 1
fi
# Check that the response contains expected tutorial content
if ! grep -q "Welcome to the Tenant Tutorial" /tmp/public_response.html; then
echo "Public tenant response doesn't contain expected tutorial content"
cat /tmp/public_response.html
exit 1
fi
echo "Public tenant test passed"
- name: Test first tenant endpoint
run: |
response=$(curl -s -w "%{http_code}" -H "Host: tenant1.example.com" http://localhost:8000/ -o /tmp/tenant1_response.html)
echo "Tenant 1 response code: $response"
if [ "$response" != "200" ]; then
echo "Tenant 1 test failed with response code: $response"
echo "Response content:"
cat /tmp/tenant1_response.html
exit 1
fi
# Check that the response contains tenant-specific content
if ! grep -q "Tenant 1 - Test Company" /tmp/tenant1_response.html; then
echo "Tenant 1 response doesn't contain expected tenant name"
cat /tmp/tenant1_response.html
exit 1
fi
echo "Tenant 1 test passed"
- name: Test second tenant endpoint
run: |
response=$(curl -s -w "%{http_code}" -H "Host: tenant2.example.com" http://localhost:8000/ -o /tmp/tenant2_response.html)
echo "Tenant 2 response code: $response"
if [ "$response" != "200" ]; then
echo "Tenant 2 test failed with response code: $response"
echo "Response content:"
cat /tmp/tenant2_response.html
exit 1
fi
# Check that the response contains tenant-specific content
if ! grep -q "Tenant 2 - Another Company" /tmp/tenant2_response.html; then
echo "Tenant 2 response doesn't contain expected tenant name"
cat /tmp/tenant2_response.html
exit 1
fi
echo "Tenant 2 test passed"
- name: Test tenant data isolation
run: |
# Add users to tenant1
uv run python manage.py tenant_command shell --schema=tenant1 << 'EOF'
from django.contrib.auth.models import User
User.objects.create_user('tenant1user', '[email protected]', 'password')
print(f"Tenant1 users count: {User.objects.count()}")
EOF
# Check that tenant2 doesn't have these users
uv run python manage.py tenant_command shell --schema=tenant2 << 'EOF'
from django.contrib.auth.models import User
count = User.objects.count()
print(f"Tenant2 users count: {count}")
if count != 0:
print("ERROR: Data isolation failed - tenant2 can see tenant1 users")
exit(1)
print("Data isolation test passed")
EOF
- name: Stop Django server
if: always()
run: |
if [ -f django_server.pid ]; then
kill $(cat django_server.pid) || true
rm django_server.pid
fi
- name: Upload response files on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: response-files
path: /tmp/*_response.html
retention-days: 1