S5 Client Cleanup Implementation Plan (Revised)¶
Date: 2025-11-23 Status: Implementation Plan (Revised) Author: Claude Code Complexity: Medium-high complexity migration with architectural benefits Risk Level: Medium
Executive Summary¶
This document provides a detailed implementation plan for converting the S5 Slidefactory repository from a monolithic codebase to a thin client that depends on the slidefactory-core package. This completes the repository separation strategy outlined in the November 2025 migration guides.
Important: S5 is Azure-only deployment. Docker setup has moved to eddy-slidefactory (Hetzner). S5 local development uses start.sh and start-worker.sh connected to Azure preview environment.
Current State: - S5 repository contains duplicate core code (app/, cli/, alembic/, tests/) - Core package exists at ../slidefactory-core with version 1.0.8 - S5 uses monolith-style imports (app.*) - No clear separation between core functionality and S5-specific branding/deployment - Contains Docker Compose setup (should be in eddy-slidefactory)
Target State: - S5 repository contains only branding, configuration, and Azure deployment files - S5 depends on slidefactory-core==1.0.8 via pyproject.toml - Core functionality provided by installed package - Clear separation of concerns: core logic vs. Azure client deployment - No Docker Compose (moved to eddy-slidefactory)
Benefits: - Single source of truth for core functionality - Easier maintenance and updates - Clear deployment boundaries - Consistent with repository separation architecture - Reduced code duplication
Assessment Summary¶
Current Repository State¶
✅ Verified: - Core package (slidefactory-core) exists at ../slidefactory-core with version 1.0.8 - Core has all application code under src/slidefactory/ with proper package structure - Core uses proper imports (slidefactory.app.*) - S5 branding files identified in static/img/branding/ and scattered locations
❌ Issues: - S5 repo still has duplicate code in app/, cli/, alembic/, static/, templates/ - S5 repo has old setup.py for CLI (should use core's package) - S5 repo has migration docs that belong in core or archive - S5 uses old monolith imports (app.*) - S5 repo has Docker Compose setup (belongs in eddy-slidefactory)
Key Differences¶
| Aspect | Core Package | S5 Current | S5 Target |
|---|---|---|---|
| Import Style | slidefactory.app.* | app.* | Use core package |
| Package Structure | src/slidefactory/ | app/ at root | No app code |
| Version | 1.0.8 | N/A | Depends on core |
| CLI | slidefactory command | Local setup.py | Use core's CLI |
| Distribution | Python package | Monolith | Thin client |
| Local Dev | N/A | Docker Compose | Azure preview connection |
| Deployment | N/A | Azure Container Apps | Azure Container Apps |
S5 Deployment Model¶
Azure-Only Architecture¶
S5 uses Azure Container Apps for both preview and production:
Preview Environment: - Push to preview branch → GitHub Actions → Azure Container Apps (preview) - Local development connects to preview environment (database, Redis, storage)
Production Environment: - Push to main branch → GitHub Actions → Azure Container Apps (production) - Only repository owner merges preview → main
Local Development: - No local Docker Compose - start.sh runs web server against Azure preview database - start-worker.sh runs Celery worker against Azure preview Redis/database - Configuration via .env pointing to Azure resources
Docker: - Docker Compose setup moved to eddy-slidefactory (Hetzner deployment) - S5 only uses Dockerfile for Azure Container Apps image build
Repository Structure Changes¶
Files to KEEP in S5 Repo¶
Configuration: - .env, .env.azure.* - S5 Azure environment configuration - .env.s5 - S5 environment template for Azure - .gitignore, .gitattributes - Git configuration - .github/workflows/ - Azure deployment workflows (updated)
S5-Specific Assets: - s5_branding/ - S5 branding files (created) - docs/ - S5-specific documentation (Azure deployment, S5 resources)
Deployment: - Dockerfile - Azure Container Apps deployment (updated to use core) - scripts/ - Azure deployment scripts (updated) - start-web-azure.sh - Azure Container Apps web startup - start-worker-azure.sh - Azure Container Apps worker startup - start.sh - Local web development (connects to Azure preview) - start-worker.sh - Local worker development (connects to Azure preview)
S5-Specific Azure Resources (Optional): - azure/ - Infrastructure as code, Gotenberg setup, LibreChat setup
Project Files: - README.md - S5-specific documentation (rewritten) - pyproject.toml - S5 client package definition - .claude/ - Claude Code project instructions - Git history and configuration
Files to REMOVE from S5 Repo¶
Core Application Code: - app/ - Entire FastAPI application (now in core) - cli/ - CLI tool (now in core package) - alembic/ - Database migrations (now in core) - alembic.ini - Migration configuration (now in core)
Core Assets: - static/ - Except S5 branding (moved to s5_branding/static/) - templates/ - Except S5 overrides (moved to s5_branding/templates/)
Core Testing: - tests/ - Core tests (now in core repo) - pytest.ini - Testing configuration (now in core) - .coverage, htmlcov/ - Coverage artifacts
Core Infrastructure: - init.sql, init_test.sql - Database initialization (now in core) - packages/ - N8N nodes package (now in core) - bootstrap-database.sh - Database setup script (now in core)
Docker Setup (Moved to Eddy): - docker-compose.yml - Moved to eddy-slidefactory - .env.local - Local Docker config (not used by S5)
Old Package Files: - setup.py - Old CLI setup (replaced by pyproject.toml) - s5_slidefactory_cli.egg-info/ - Old package metadata - requirements.txt, requirements-dev.txt - Replaced by pyproject.toml
Build Artifacts: - site/ - MkDocs build output (docs now in core) - mkdocs.yml - Documentation config (now in core) - test_workflow_engines.py - Core test file
Migration Documentation: - docs/reports/technical/2025-11-18_repository_separation_*.md - Archive these - docs/reports/technical/2025-11-20_core_*.md - Archive these - docs/reports/technical/2025-11-20_eddy_*.md - Archive these
New S5 Repository Structure¶
s5-slidefactory/
├── pyproject.toml # S5 package with core dependency
├── README.md # S5 Azure deployment documentation
├── .env.s5 # S5 Azure environment template
├── .env, .env.azure.* # S5 Azure configurations
├── s5_branding/ # S5-specific branding
│ ├── __init__.py
│ ├── static/
│ │ ├── css/
│ │ │ └── s5-custom.css
│ │ └── img/
│ │ ├── sportfive_logo.png
│ │ ├── sportfive_large.png
│ │ ├── sportfive_small.png
│ │ ├── bannerlogo.png
│ │ ├── sf_logo_*.png
│ │ └── favicon.ico
│ └── templates/ # S5-specific overrides (if needed)
├── .github/
│ └── workflows/
│ ├── preview.yml # Azure preview deployment
│ └── production.yml # Azure production deployment
├── scripts/
│ ├── start-web-azure.sh # Azure Container Apps web startup
│ └── start-worker-azure.sh # Azure Container Apps worker startup
├── azure/ # Optional: S5-specific Azure resources
│ ├── gotenberg/ # Gotenberg PDF service setup
│ └── librechat/ # LibreChat AI chatbot setup
├── Dockerfile # Azure Container Apps image
├── start.sh # Local web dev (Azure preview)
├── start-worker.sh # Local worker dev (Azure preview)
├── docs/
│ ├── azure_deployment.md # Azure deployment guide
│ ├── s5_resources.md # S5-specific Azure resources
│ ├── archive/
│ │ └── migration/ # Archived migration docs
│ └── reports/technical/ # S5-specific technical reports
├── .claude/
│ └── CLAUDE.md # Updated project instructions
└── .gitignore
Implementation Plan - CLI Commands¶
PHASE 1: BACKUP & PREPARATION¶
# 1. Create backup of current state
git checkout -b backup-before-s5-cleanup-$(date +%Y%m%d)
git push origin backup-before-s5-cleanup-$(date +%Y%m%d)
# 2. Verify core package is available
ls -la ../slidefactory-core/src/slidefactory/
cat ../slidefactory-core/pyproject.toml | grep version
# 3. Create working branch for cleanup
git checkout preview
git pull origin preview
git checkout -b feature/s5-client-cleanup
PHASE 2: CREATE S5 BRANDING STRUCTURE¶
# 4. Create S5 branding directory structure
mkdir -p s5_branding/static/img
mkdir -p s5_branding/static/css
mkdir -p s5_branding/templates
# 5. Move S5-specific images to branding folder
mv static/img/branding/* s5_branding/static/img/
mv static/img/sf_logo_*.png s5_branding/static/img/
mv static/img/sportfive* s5_branding/static/img/
# 6. Create S5 custom CSS (if needed)
touch s5_branding/static/css/s5-custom.css
# 7. Create __init__.py for S5 branding package
cat > s5_branding/__init__.py << 'EOF'
"""S5 SportFive branding package for Slidefactory."""
__version__ = "1.0.0"
EOF
PHASE 3: CREATE S5 CLIENT CONFIGURATION¶
# 8. Create S5-specific pyproject.toml
cat > pyproject.toml << 'EOF'
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "s5-slidefactory"
version = "1.0.0"
description = "S5 SportFive Slidefactory - Azure Deployment Client"
requires-python = ">=3.11"
# Note: slidefactory-core installed separately from local path
# See installation instructions below
dependencies = []
[project.optional-dependencies]
azure = [
"azure-storage-blob>=12.19.0",
"azure-identity>=1.15.0",
"msal>=1.26.0",
]
[tool.setuptools]
packages = ["s5_branding"]
EOF
# 9. Install slidefactory-core
# Option A: From local sibling repository (recommended for development)
pip install -e ../slidefactory-core
# Option B: Using GitHub CLI (easiest for non-dev setup)
# gh auth login # Login once
# gh release download v1.0.8 --repo cgast/slidefactory-core --pattern "*.whl"
# pip install slidefactory_core-1.0.8-py3-none-any.whl
# rm slidefactory_core-1.0.8-py3-none-any.whl
# Option C: Using curl with GitHub PAT
# export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# curl -L \
# -H "Authorization: token ${GITHUB_TOKEN}" \
# -H "Accept: application/octet-stream" \
# https://api.github.com/repos/cgast/slidefactory-core/releases/download/v1.0.8/slidefactory_core-1.0.8-py3-none-any.whl \
# -o slidefactory_core.whl && \
# pip install slidefactory_core.whl && \
# rm slidefactory_core.whl
# 10. Create S5-specific .env.s5 template (Azure configuration)
cat > .env.s5 << 'EOF'
# S5 SportFive Branding
CLIENT_NAME="SportFive Slidefactory"
CLIENT_LOGO="/s5_branding/static/img/sportfive_logo.png"
CLIENT_LOGO_LARGE="/s5_branding/static/img/sportfive_large.png"
CLIENT_PRIMARY_COLOR="#ee0000"
# S5 Deployment
DEPLOYMENT_PLATFORM="azure"
SERVER_URL="https://slidefactory.sportfive.com"
# Storage (Azure Blob Storage)
STORAGE_PROVIDER="azure"
AZURE_STORAGE_ACCOUNT_NAME="${AZURE_STORAGE_ACCOUNT_NAME}"
AZURE_STORAGE_ACCOUNT_KEY="${AZURE_STORAGE_ACCOUNT_KEY}"
# Auth (Azure AD)
AZURE_TENANT_ID="${AZURE_TENANT_ID}"
AZURE_CLIENT_ID="${AZURE_CLIENT_ID}"
AZURE_CLIENT_SECRET="${AZURE_CLIENT_SECRET}"
AZURE_REDIRECT_URI="${AZURE_REDIRECT_URI}"
# Database (Azure PostgreSQL)
DATABASE_URL="${DATABASE_URL}"
# Redis (Azure Cache for Redis)
REDIS_HOST="${REDIS_HOST}"
REDIS_PORT="${REDIS_PORT}"
REDIS_PASSWORD="${REDIS_PASSWORD}"
REDIS_SSL=true
# AI (Azure OpenAI / OpenAI)
OPENAI_API_KEY="${OPENAI_API_KEY}"
AZURE_OPENAI_API_KEY="${AZURE_OPENAI_API_KEY}"
AZURE_OPENAI_ENDPOINT="${AZURE_OPENAI_ENDPOINT}"
# S5-Specific Services (Optional)
GOTENBERG_URL="${GOTENBERG_URL}" # S5 Gotenberg instance on Azure
LIBRECHAT_URL="${LIBRECHAT_URL}" # S5 LibreChat instance on Azure
EOF
# 11. Update Dockerfile for Azure Container Apps
cat > Dockerfile << 'EOF'
FROM python:3.11-slim
WORKDIR /code
# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
curl \
postgresql-client \
&& rm -rf /var/lib/apt/lists/*
# Install slidefactory-core from GitHub release
# Note: Use GitHub PAT for private repo access
ARG GITHUB_TOKEN
ARG CORE_VERSION=1.0.8
RUN curl -L \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/octet-stream" \
https://api.github.com/repos/cgast/slidefactory-core/releases/download/v${CORE_VERSION}/slidefactory_core-${CORE_VERSION}-py3-none-any.whl \
-o /tmp/slidefactory_core.whl && \
pip install --no-cache-dir /tmp/slidefactory_core.whl && \
rm /tmp/slidefactory_core.whl
# Copy S5 package files
COPY pyproject.toml /code/
COPY s5_branding/ /code/s5_branding/
# Install S5 package with Azure dependencies
RUN pip install --no-cache-dir -e ".[azure]"
# Copy S5 Azure deployment scripts
COPY scripts/ /code/scripts/
RUN chmod +x /code/scripts/*.sh
# Expose S5 branding as static files
RUN ln -s /code/s5_branding/static /code/static/s5_branding
# Expose port
EXPOSE 8000
# Use S5 Azure startup script
CMD ["/code/scripts/start-web-azure.sh"]
EOF
PHASE 4: UPDATE SCRIPTS FOR CORE PACKAGE¶
# 11. Update start-web-azure.sh (Azure Container Apps)
cat > scripts/start-web-azure.sh << 'EOF'
#!/bin/bash
set -e
echo "Starting S5 Slidefactory Web (Azure Container Apps deployment)..."
# Run migrations (from core package)
echo "Running database migrations..."
alembic upgrade head
# Initialize system if needed (from core package CLI)
echo "Initializing system..."
slidefactory init check || slidefactory init all
# Start uvicorn (core package's FastAPI app)
echo "Starting web server..."
exec uvicorn slidefactory.app.main:app --host 0.0.0.0 --port 8000
EOF
chmod +x scripts/start-web-azure.sh
# 12. Update start-worker-azure.sh (Azure Container Apps)
cat > scripts/start-worker-azure.sh << 'EOF'
#!/bin/bash
set -e
echo "Starting S5 Slidefactory Worker (Azure Container Apps deployment)..."
# Start Celery worker (from core package)
exec celery -A slidefactory.app.celery_app worker --loglevel=info --concurrency=2
EOF
chmod +x scripts/start-worker-azure.sh
# 13. Create start.sh for local development (connects to Azure preview)
cat > start.sh << 'EOF'
#!/bin/bash
# S5 Slidefactory local development web startup
# Connects to Azure preview environment (database, Redis, storage)
set -e
echo "Starting S5 Slidefactory web (local development)..."
echo "Connecting to Azure preview environment..."
# Note: Requires .env configured with Azure preview credentials
# - Database: Azure PostgreSQL preview instance
# - Redis: Azure Cache for Redis preview instance
# - Storage: Azure Blob Storage preview container
# Start uvicorn with reload (core package)
exec uvicorn slidefactory.app.main:app --host 0.0.0.0 --port 8080 --reload
EOF
chmod +x start.sh
# 14. Create start-worker.sh for local worker development
cat > start-worker.sh << 'EOF'
#!/bin/bash
# S5 Slidefactory local development worker startup
# Connects to Azure preview environment (Redis, database)
set -e
echo "Starting S5 Slidefactory worker (local development)..."
echo "Connecting to Azure preview environment..."
# Note: Requires .env configured with Azure preview credentials
# - Redis: Azure Cache for Redis preview instance (Celery broker)
# - Database: Azure PostgreSQL preview instance
# Start Celery worker with autoreload (core package)
exec celery -A slidefactory.app.celery_app worker --loglevel=info --concurrency=2 --autoreload
EOF
chmod +x start-worker.sh
PHASE 5: UPDATE DOCUMENTATION¶
# 15. Create S5-specific README
cat > README.md << 'EOF'
# S5 SportFive Slidefactory
SportFive-branded deployment of Slidefactory on Azure Container Apps.
## Overview
This repository contains the SportFive-specific configuration, branding, and Azure deployment setup for Slidefactory.
**Core Engine:** [slidefactory-core](https://github.com/cgast/slidefactory-core) v1.0.8
**Deployment:** Azure Container Apps (preview and production environments)
## Architecture
S5 is an **Azure-only deployment client**:
- Uses `slidefactory-core` package for all core functionality
- Contains only S5 branding, configuration, and Azure deployment files
- No local Docker setup (Docker moved to `eddy-slidefactory` for Hetzner)
## Local Development
S5 local development connects to **Azure preview environment** (no local services):
```bash
# Install slidefactory-core
# Option A: From local sibling repository (if you have the source)
pip install -e ../slidefactory-core
# Option B: Using GitHub CLI (easiest, recommended)
gh auth login # Login once
gh release download v1.0.8 --repo cgast/slidefactory-core --pattern "*.whl"
pip install slidefactory_core-1.0.8-py3-none-any.whl
rm slidefactory_core-1.0.8-py3-none-any.whl
# Option C: Using curl with GitHub PAT
# export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# curl -L \
# -H "Authorization: token ${GITHUB_TOKEN}" \
# -H "Accept: application/octet-stream" \
# https://api.github.com/repos/cgast/slidefactory-core/releases/download/v1.0.8/slidefactory_core-1.0.8-py3-none-any.whl \
# -o slidefactory_core.whl && \
# pip install slidefactory_core.whl && \
# rm slidefactory_core.whl
# Install S5 client with Azure dependencies
pip install -e ".[azure]"
# Configure environment for Azure preview
cp .env.azure.preview .env
# Edit .env with your Azure preview credentials:
# - DATABASE_URL: Azure PostgreSQL preview
# - REDIS_HOST/PORT/PASSWORD: Azure Cache for Redis preview
# - AZURE_STORAGE_*: Azure Blob Storage preview
# - AZURE_TENANT_ID/CLIENT_ID/etc.: Azure AD credentials
# Start web server (connects to Azure preview)
./start.sh
# In separate terminal, start worker
./start-worker.sh
Access: http://localhost:8080
Azure Deployment¶
Automatic deployment via GitHub Actions:
Preview Environment: - Push to preview branch → GitHub Actions → Azure Container Apps (preview) - Preview URL: https://slidefactory-preview.sportfive.com
Production Environment: - Push to main branch → GitHub Actions → Azure Container Apps (production) - Production URL: https://slidefactory.sportfive.com - Only repository owner merges preview → main
S5 Branding¶
S5 branding assets in s5_branding/static/: - Logo: SportFive red logo - Colors: Red (#ee0000) primary - Custom CSS: s5_branding/static/css/s5-custom.css
Branding is automatically included in Azure Container Apps deployment via Dockerfile.
S5-Specific Azure Resources¶
Beyond core Slidefactory infrastructure, S5 deployment includes:
Additional Services: - Gotenberg: PDF rendering service for presentation generation - LibreChat (optional): AI chatbot interface - Azure OpenAI: S5-specific AI endpoints
Configuration: See azure/ directory for infrastructure setup and deployment scripts.
Configuration¶
See .env.s5 for S5 Azure configuration template.
Azure Resources: - Container Apps: Web and Worker services - Storage: Azure Blob Storage - Database: Azure Database for PostgreSQL with pgvector - Redis: Azure Cache for Redis - Optional: Gotenberg, LibreChat
CLI Commands¶
All CLI commands are provided by the core package:
+++bash
System initialization¶
slidefactory init all
User management¶
slidefactory user list slidefactory user create-local user@example.com --name "John Doe"
API keys¶
slidefactory api-key create "My Key" --user-id 1
Presentations¶
slidefactory presentation generate --template-id 123 +++
Support¶
- S5-specific issues: Create issue in this repository
- Core platform issues: slidefactory-core issues
License¶
Proprietary - SportFive internal use only EOF
16. Archive migration docs¶
mkdir -p docs/archive/migration mv docs/reports/technical/2025-11-18_repository_separation_.md docs/archive/migration/ 2>/dev/null || true mv docs/reports/technical/2025-11-20_core_.md docs/archive/migration/ 2>/dev/null || true mv docs/reports/technical/2025-11-20_eddy_*.md docs/archive/migration/ 2>/dev/null || true
### PHASE 6: REMOVE CORE CODE AND DOCKER SETUP
```bash
# 17. Remove core application code
rm -rf app/
rm -rf cli/
rm -rf alembic/
rm -f alembic.ini
# 18. Remove core static/templates
rm -rf static/css/
rm -rf static/js/
rm -rf static/vendor/
rm -rf static/img/ # S5 images already moved to s5_branding/
rm -rf templates/
# 19. Remove core test infrastructure
rm -rf tests/
rm -f pytest.ini
# 20. Remove core database files
rm -f init.sql
rm -f init_test.sql
# 21. Remove old package setup
rm -f setup.py
rm -rf s5_slidefactory_cli.egg-info/
# 22. Remove core requirements files
rm -f requirements.txt
rm -f requirements-dev.txt
# 23. Remove core package directory (N8N nodes)
rm -rf packages/
# 24. Remove core-specific files
rm -f test_workflow_engines.py
rm -f bootstrap-database.sh
# 25. Clean up old build artifacts
rm -rf htmlcov/
rm -f .coverage
rm -rf site/ # MkDocs build output (docs now in core)
rm -f mkdocs.yml
# 26. Remove Docker Compose setup (moved to eddy-slidefactory)
rm -f docker-compose.yml
rm -f .env.local
PHASE 7: UPDATE GITHUB ACTIONS¶
# 27. Update preview.yml workflow for Azure deployment
cat > .github/workflows/preview.yml << 'EOF'
name: Deploy S5 to Azure Preview
on:
push:
branches: [preview]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Login to Azure Container Registry
run: |
az acr login --name s5slidefactory
- name: Build and push Docker image
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT_SLIDEFACTORY_CORE }}
run: |
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.8 \
-t s5slidefactory.azurecr.io/slidefactory:preview-${{ github.sha }} .
docker push s5slidefactory.azurecr.io/slidefactory:preview-${{ github.sha }}
- name: Deploy to Azure Container Apps
run: |
az containerapp update \
--name slidefactory-web-preview \
--resource-group rg-slidefactory-preview \
--image s5slidefactory.azurecr.io/slidefactory:preview-${{ github.sha }}
EOF
# 28. Update production.yml workflow for Azure deployment
cat > .github/workflows/production.yml << 'EOF'
name: Deploy S5 to Azure Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS_PROD }}
- name: Login to Azure Container Registry
run: |
az acr login --name s5slidefactory
- name: Build and push Docker image
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT_SLIDEFACTORY_CORE }}
run: |
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.8 \
-t s5slidefactory.azurecr.io/slidefactory:prod-${{ github.sha }} .
docker push s5slidefactory.azurecr.io/slidefactory:prod-${{ github.sha }}
- name: Deploy to Azure Container Apps
run: |
az containerapp update \
--name slidefactory-web-prod \
--resource-group rg-slidefactory-prod \
--image s5slidefactory.azurecr.io/slidefactory:prod-${{ github.sha }}
EOF
PHASE 8: COMMIT CHANGES¶
# 29. Review changes
git status
git diff --stat
# 30. Stage S5-specific files
git add s5_branding/
git add pyproject.toml
git add .env.s5
git add Dockerfile
git add scripts/
git add start.sh
git add start-worker.sh
git add README.md
git add .github/workflows/
git add docs/
# 31. Stage removals
git add -u # Stage all deletions
# 32. Review staged changes
git status
# 33. Commit changes
git commit -m "refactor: Convert S5 to Azure-only thin client using slidefactory-core
- Remove core application code (app/, cli/, alembic/, tests/)
- Remove Docker Compose setup (moved to eddy-slidefactory)
- Create s5_branding/ with SportFive assets
- Create pyproject.toml with slidefactory-core==1.0.8 dependency
- Update Dockerfile for Azure Container Apps deployment
- Update scripts for Azure Container Apps (start-web-azure.sh, start-worker-azure.sh)
- Create local dev scripts (start.sh, start-worker.sh) for Azure preview connection
- Archive migration documentation
- Update README for S5 Azure-only deployment
S5 is now an Azure-only deployment client. Docker setup moved to eddy-slidefactory.
Local development connects to Azure preview environment.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>"
PHASE 9: VERIFICATION¶
# 34. Install slidefactory-core
# Option A: From local sibling repository (if you have the source)
pip install -e ../slidefactory-core
# Option B: From GitHub release using curl (if you don't have the source)
# export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
# curl -L \
# -H "Authorization: token ${GITHUB_TOKEN}" \
# -H "Accept: application/octet-stream" \
# https://api.github.com/repos/cgast/slidefactory-core/releases/download/v1.0.8/slidefactory_core-1.0.8-py3-none-any.whl \
# -o slidefactory_core-1.0.8-py3-none-any.whl
# pip install slidefactory_core-1.0.8-py3-none-any.whl
# rm slidefactory_core-1.0.8-py3-none-any.whl
# Option C: From GitHub release using gh CLI (easiest if you have gh installed)
# gh auth login # Login once, then:
# gh release download v1.0.8 --repo cgast/slidefactory-core --pattern "*.whl"
# pip install slidefactory_core-1.0.8-py3-none-any.whl
# rm slidefactory_core-1.0.8-py3-none-any.whl
# 35. Install S5 package in development mode
pip install -e ".[azure]"
# 36. Verify core package is installed
pip list | grep slidefactory
# Should show:
# slidefactory-core 1.0.8
# s5-slidefactory 1.0.0
# 37. Verify CLI is available
which slidefactory
slidefactory --help
# 38. Test imports work
python -c "from slidefactory.app.main import app; print('✅ Core package imports successfully')"
# 39. Build Docker image for Azure locally (requires GITHUB_TOKEN)
# Note: For private repo access, you need to provide GitHub PAT
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.8 \
-t s5-slidefactory:test .
# 40. Test Docker container
docker run --rm s5-slidefactory:test slidefactory --version
# 41. Test local development startup (requires Azure preview .env)
# ./start.sh
# (Ctrl+C to stop)
PHASE 10: PUSH TO REMOTE¶
# 42. Push feature branch
git push origin feature/s5-client-cleanup
# 43. Create PR to preview branch (NOT main)
# Do this via GitHub UI or gh CLI:
gh pr create --base preview --title "Convert S5 to Azure-only thin client using slidefactory-core" \
--body "Completes repository separation by removing core code and using slidefactory-core package.
Changes:
- Remove core application code
- Remove Docker Compose (moved to eddy-slidefactory)
- Create s5_branding/ package
- Update for Azure-only deployment
- Local dev connects to Azure preview environment
Note: Requires GITHUB_TOKEN secret configured in GitHub Actions for private slidefactory-core access."
# After PR review and merge to preview:
# 44. Test preview deployment
# Monitor Azure Container Apps preview environment
# 45. If preview works, merge preview → main (repo owner only)
# This triggers production deployment
OPTIONAL: CLEANUP¶
# 46. After successful deployment, archive old branches
git branch -D backup-before-s5-cleanup-YYYYMMDD # Delete local backup
# Keep remote backup for safety
Risk Assessment & Mitigation¶
Complexity Assessment¶
Complexity: Medium-high Risk Level: Medium
Reasons for Medium-High Complexity: 1. Major architectural change (monolith → package dependency) 2. Affects deployment pipeline and CI/CD 3. Changes import paths and startup scripts throughout 4. Requires coordination with Azure deployment configuration 5. Multiple file movements and deletions 6. Testing requires Azure preview environment access 7. Removes Docker Compose (moved to different repo)
Reasons for Medium Risk: 1. Core package is already tested and stable (v1.0.8) 2. Clear rollback strategy available (backup branch) 3. Preview environment allows testing before production 4. Non-destructive changes (backups created) 5. Similar pattern already working in core repo 6. Docker removal is clean separation (moved to eddy-slidefactory)
Risk Mitigation Strategies¶
1. Backup Strategy - Create backup branch before any changes - Push backup to remote immediately - Keep backup for at least 30 days after successful deployment
2. Staged Rollout - Test locally with Azure preview connection - Deploy to Azure preview environment - Monitor for 24-48 hours before production - Only merge to main after preview validation
3. Testing Strategy - Verify package installation locally - Test CLI commands work - Test Docker build completes - Test local development with Azure preview - Verify Azure Container Apps deployment succeeds
4. Rollback Plan
# If something breaks:
git checkout preview
git reset --hard origin/preview # Restore to last working state
# Or restore from backup branch:
git checkout backup-before-s5-cleanup-YYYYMMDD
git checkout -b preview-restored
git push origin preview-restored --force
Pre-deployment Checklist¶
Before executing this plan, verify:
- Core package v1.0.8 is stable and tested in core repo
- Core package is accessible (installed locally via
../slidefactory-core) - S5 branding assets are identified and backed up
- Azure secrets and credentials are documented
- Azure preview environment is accessible for local dev
- Preview environment is available for testing deployment
- Backup branch has been created and pushed to remote
- Team has been notified of upcoming changes
- Rollback procedure has been reviewed
-
.envconfigured with Azure preview credentials for local testing - GitHub PAT created with 'repo' scope for slidefactory-core access
- GitHub secret
GH_PAT_SLIDEFACTORY_COREconfigured in repo settings
Post-deployment Validation¶
After deployment, verify:
- Azure preview deployment starts successfully
- Web application is accessible at preview URL
- CLI commands work in Azure environment
- Database migrations run correctly
- Static files (S5 branding) are served correctly
- User authentication works (Azure AD)
- Presentation generation works
- Worker processes start and process tasks
- Logs show no import errors or package issues
- Local development works with Azure preview connection
Benefits Realized¶
For Core Maintainer¶
- Single Source of Truth: One codebase for all core functionality
- Version Control: Clients upgrade on their schedule
- Clear Ownership: Core changes go to core repo only
- Easier Testing: Test core once, all clients benefit
- Documentation: Core docs separate from client docs
- Reduced Duplication: No need to maintain multiple copies of core code
For S5 Deployment¶
- Isolated Issues: S5-specific issues tracked separately
- Custom Branding: Complete control over S5 look and feel
- Independent Deployments: Deploy on S5's schedule
- Stable Versions: Pin to tested core versions, upgrade when ready
- Clear Support: Know where to report issues (core vs. S5)
- Simplified Repository: Only deployment and branding code
- Azure-Only Focus: No Docker maintenance, focused on Azure
Technical Benefits¶
- Separation of Concerns: Core logic vs. Azure deployment configuration
- Testability: Core tests don't need Azure setup
- Reusability: Easy to create new clients (Eddy uses Docker, S5 uses Azure)
- Scalability: Core improvements benefit all clients automatically
- Security: Client-specific secrets stay in client repos
- Maintainability: Changes are localized and easier to reason about
- Clear Deployment Models: S5 (Azure), Eddy (Docker/Hetzner), etc.
Version Management Strategy¶
Core Package Updates¶
When core package releases a new version:
-
Core team creates new release in core repo:
-
S5 team decides when to upgrade:
cd s5-slidefactory # Update Dockerfile CORE_VERSION # Edit Dockerfile, change: ARG CORE_VERSION=1.0.8 → ARG CORE_VERSION=1.1.0 # Update local development cd ../slidefactory-core git pull git checkout v1.1.0 cd ../s5-slidefactory pip install -e ../slidefactory-core --force-reinstall # Test locally against Azure preview ./start.sh # Commit and deploy to preview git commit -am "chore: upgrade slidefactory-core to v1.1.0" git push origin preview # Monitor preview deployment, then merge to main when stable
Version Pinning Policy¶
- S5 pins exact versions in Dockerfile via
CORE_VERSIONbuild arg (e.g.,1.0.8) - Version is set in Dockerfile:
ARG CORE_VERSION=1.0.8 - GitHub Actions can override:
--build-arg CORE_VERSION=1.1.0 - Prevents unexpected breakage from core updates
- S5 controls upgrade timing
- Allows testing before production deployment
Breaking Changes¶
Core package follows semantic versioning: - MAJOR (x.0.0): Breaking changes - S5 must review and test - MINOR (1.x.0): New features - S5 can upgrade with low risk - PATCH (1.0.x): Bug fixes - S5 should upgrade ASAP
Deployment Model Comparison¶
S5 (Azure-only)¶
Local Development: - start.sh + start-worker.sh - Connects to Azure preview environment - No local database/Redis/storage
Deployment: - GitHub Actions → Azure Container Apps - Preview and production environments
Dockerfile: - Used only for Azure Container Apps image build - Not used for local development
Eddy (Docker/Hetzner)¶
Local Development: - docker-compose up - Local services (postgres, redis, minio) - Self-contained development
Deployment: - Docker Compose on Hetzner - Single production environment
Dockerfile: - Used for both local development and production - Docker Compose manages services
Future Considerations¶
Adding More Clients¶
This pattern makes it easy to add new clients with different deployment models:
S5 Pattern (Azure):
mkdir s5-slidefactory
cd s5-slidefactory
# Create pyproject.toml with core dependency + Azure dependencies
# Create branding package
# Create Azure deployment workflows
# Local dev connects to Azure preview
Eddy Pattern (Docker/Hetzner):
mkdir eddy-slidefactory
cd eddy-slidefactory
# Create pyproject.toml with core dependency
# Create branding package
# Create docker-compose.yml
# Local dev uses Docker Compose
Core Package Distribution¶
Current: Local installation from ../slidefactory-core
Future options: 1. GitHub Packages: Private package registry 2. PyPI: Public package (if open-sourced) 3. Self-hosted PyPI: Internal package server
Documentation Strategy¶
- Core docs: In core repo, published via MkDocs
- S5 docs: In S5 repo, Azure deployment-specific
- Eddy docs: In Eddy repo, Docker deployment-specific
Troubleshooting Guide¶
Issue: Package not found during installation¶
# Solution: Install core from local path
pip install -e ../slidefactory-core
# Or if using package registry:
pip install slidefactory-core==1.0.8 --index-url <registry-url>
Issue: Import errors after cleanup¶
# Check if core package is installed
pip list | grep slidefactory
# Reinstall if needed
pip install -e ".[azure]" --force-reinstall
Issue: Static files (branding) not found¶
# Verify symlink in Dockerfile
docker run --rm s5-slidefactory:test ls -la /code/static/s5_branding
# Check branding package structure
ls -la s5_branding/static/
Issue: CLI commands not working¶
# Check which slidefactory is being used
which slidefactory
# Should point to core package's CLI, not local script
# /path/to/.venv/bin/slidefactory (correct)
# ./slidefactory (incorrect - old script)
Issue: Local development cannot connect to Azure¶
# Verify .env has Azure preview credentials
cat .env | grep DATABASE_URL
cat .env | grep REDIS_HOST
cat .env | grep AZURE_STORAGE
# Test database connection
psql "${DATABASE_URL}"
# Test Redis connection
redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -a ${REDIS_PASSWORD} ping
Issue: Azure Container Apps deployment fails¶
# Check GitHub Actions logs
# Verify secrets are configured in GitHub repo settings:
# - AZURE_CREDENTIALS (for preview)
# - AZURE_CREDENTIALS_PROD (for production)
# - GH_PAT_SLIDEFACTORY_CORE (GitHub PAT for accessing private slidefactory-core repo)
# Test Docker build locally with GitHub token
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.8 \
-t s5-slidefactory:test .
docker run --rm s5-slidefactory:test slidefactory --version
Issue: Docker build fails to download slidefactory-core wheel¶
# Ensure GITHUB_TOKEN is provided and has repo access
# The token needs 'repo' scope for private repository access
# Create GitHub Personal Access Token:
# 1. Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
# 2. Generate new token with 'repo' scope
# 3. Add as secret GH_PAT_SLIDEFACTORY_CORE in GitHub repo settings
# Verify the wheel exists in GitHub releases:
# https://github.com/cgast/slidefactory-core/releases/tag/v1.0.8
# File should be: slidefactory_core-1.0.8-py3-none-any.whl
# For local builds, export token:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.8 \
-t s5-slidefactory:test .
# Test with different version:
docker build \
--build-arg GITHUB_TOKEN=$GITHUB_TOKEN \
--build-arg CORE_VERSION=1.0.9 \
-t s5-slidefactory:test .
Helper Script: Install Core from GitHub¶
For easier installation without the sibling repository, create this helper script:
# Create scripts/install-core-from-github.sh
cat > scripts/install-core-from-github.sh << 'EOF'
#!/bin/bash
# Install slidefactory-core from GitHub release
set -e
CORE_VERSION=${1:-1.0.8}
echo "Installing slidefactory-core v${CORE_VERSION} from GitHub releases..."
# Try gh CLI first (easiest, handles auth automatically)
if command -v gh &> /dev/null; then
echo "Using GitHub CLI (gh)..."
gh release download v${CORE_VERSION} \
--repo cgast/slidefactory-core \
--pattern "*.whl" \
--dir /tmp
pip install /tmp/slidefactory_core-${CORE_VERSION}-py3-none-any.whl
rm /tmp/slidefactory_core-${CORE_VERSION}-py3-none-any.whl
# Fall back to curl with GITHUB_TOKEN
elif [ -n "$GITHUB_TOKEN" ]; then
echo "Using curl with GITHUB_TOKEN..."
curl -L \
-H "Authorization: token ${GITHUB_TOKEN}" \
-H "Accept: application/octet-stream" \
https://api.github.com/repos/cgast/slidefactory-core/releases/download/v${CORE_VERSION}/slidefactory_core-${CORE_VERSION}-py3-none-any.whl \
-o /tmp/slidefactory_core.whl
pip install /tmp/slidefactory_core.whl
rm /tmp/slidefactory_core.whl
else
echo "Error: Neither 'gh' CLI nor GITHUB_TOKEN found"
echo ""
echo "Option 1: Install GitHub CLI and authenticate:"
echo " brew install gh # or apt-get install gh"
echo " gh auth login"
echo " ./scripts/install-core-from-github.sh"
echo ""
echo "Option 2: Use GitHub Personal Access Token:"
echo " export GITHUB_TOKEN=ghp_xxxxx"
echo " ./scripts/install-core-from-github.sh"
exit 1
fi
echo "✅ slidefactory-core v${CORE_VERSION} installed successfully"
slidefactory --version
EOF
chmod +x scripts/install-core-from-github.sh
Usage:
# Option 1: With GitHub CLI (recommended)
gh auth login # One-time setup
./scripts/install-core-from-github.sh # Install v1.0.8
./scripts/install-core-from-github.sh 1.0.9 # Install specific version
# Option 2: With GitHub PAT
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxx
./scripts/install-core-from-github.sh # Install v1.0.8
./scripts/install-core-from-github.sh 1.0.9 # Install specific version
Success Criteria¶
This migration is considered successful when:
- ✅ S5 repo contains only branding, config, and Azure deployment files
- ✅ Core package (v1.0.8) is installed and importable
- ✅
slidefactoryCLI command works and uses core package - ✅ Local development works with
./start.sh(connects to Azure preview) - ✅ Local worker works with
./start-worker.sh(connects to Azure preview) - ✅ Docker build completes successfully (for Azure Container Apps)
- ✅ Docker container starts and serves application
- ✅ Azure preview deployment succeeds
- ✅ S5 branding appears correctly in deployed application
- ✅ All core functionality (presentations, users, API keys) works
- ✅ No import errors or package-related errors in logs
- ✅ Docker Compose removed (confirmed moved to eddy-slidefactory)
Appendix A: File Inventory¶
Files Removed (Core Code)¶
app/(18 subdirectories, ~200 files)cli/(5 files)alembic/(4 directories, ~30 files)static/(4 subdirectories, ~50 files)templates/(14 subdirectories, ~40 files)tests/(11 subdirectories, ~80 files)docker-compose.yml(moved to eddy-slidefactory).env.local(Docker config, not used by S5)- Supporting files: ~20 files
Total removal: ~440 files
Files Created (S5 Client)¶
s5_branding/(3 subdirectories)pyproject.toml.env.s5start-worker.sh- Updated:
Dockerfile,README.md - Updated scripts: 2 files (start-web-azure.sh, start-worker-azure.sh)
- Updated:
start.sh(Azure preview connection) - New documentation: This report
Total additions: ~15 files + branding assets
Net Change¶
- Before: ~500 files (monolith + Docker)
- After: ~60 files (thin Azure client)
- Reduction: ~88% fewer files in S5 repo
Appendix B: Related Documentation¶
- Repository Separation Quick Reference
- Repository Separation Implementation Guide
- Core Migration Phase 1 Complete
- Core Package Documentation Setup
These documents have been archived to docs/archive/migration/ as they pertain to the migration process rather than ongoing S5 operations.
Appendix C: S5 vs Eddy Comparison¶
| Aspect | S5 (This Repo) | Eddy |
|---|---|---|
| Deployment | Azure Container Apps | Docker on Hetzner |
| Local Dev | Connect to Azure preview | Docker Compose |
| Services | All on Azure | All in Docker |
| Dockerfile | Azure Container Apps only | Local + production |
| docker-compose.yml | ❌ Removed | ✅ Main setup |
| start.sh | Connect to Azure | ❌ Not needed |
| Configuration | .env.azure.* | .env.local |
Document Status: Ready for Implementation Next Steps: Review revised plan, obtain approval, execute Phase 1 (backup) Questions/Issues: Contact maintainer or create issue in S5 repository
Revision History: - 2025-11-22: Initial plan created - 2025-11-23: Revised to align with S5 Azure-only deployment model - Removed Docker Compose setup (moved to eddy-slidefactory) - Updated local development to connect to Azure preview - Added start-worker.sh for local worker development - Clarified S5 vs Eddy deployment models - Updated all scripts and documentation - Updated package installation: slidefactory-core is private, not on PyPI - Local development: pip install -e ../slidefactory-core - Docker/Azure: Download wheel from GitHub releases (v1.0.8) - Uses curl with GitHub PAT to download private release asset - Added GitHub secret requirement: GH_PAT_SLIDEFACTORY_CORE - Added build arg: CORE_VERSION (default: 1.0.8)