Tech Notes: SWLA CI/CD Pipeline

The SWLA Records platform is a Flask application backed by MySQL on GoDaddy, deployed to Render.com with a GitHub Actions CI/CD pipeline. This post documents the deployment architecture and the pipeline setup — useful reference for anyone running a similar stack.

Stack overview

Backend
Flask + SQLAlchemy + PyMySQL
Frontend
Vanilla JS + Jinja2 + CSS
Database
MySQL on GoDaddy (swla_dev / swla_prod)
Hosting
Render.com (Web Service)
CI/CD
GitHub Actions
Repo
blackrageous/swla_repos

How the pipeline works

Every push to the main branch triggers a GitHub Actions workflow that runs tests and — if they pass — signals Render.com to pull the latest code and redeploy. Render handles the build, dependency installation, and service restart automatically. The two database environments (swla_dev and swla_prod) are kept separate via environment variables injected at runtime, never committed to the repo.

GitHub Actions workflow

# .github/workflows/deploy.yml name: Deploy to Render on: push: branches: – main jobs: deploy: runs-on: ubuntu-latest steps: – name: Checkout code uses: actions/checkout@v3 – name: Set up Python uses: actions/setup-python@v4 with: python-version: ‘3.11’ – name: Install dependencies run: pip install -r requirements.txt – name: Trigger Render deploy run: | curl -X POST \ -H “Authorization: Bearer ${{ secrets.RENDER_API_KEY }}” \ “https://api.render.com/v1/services/${{ secrets.RENDER_SERVICE_ID }}/deploys”
Key point: The Render API key and service ID are stored as GitHub repository secrets (Settings → Secrets and variables → Actions) — never hardcoded. The same pattern applies to DB_HOST, DB_USER, DB_PASSWORD, and DB_PORT, which Render injects as environment variables at runtime.

Environment variable management

The Flask app reads its database connection from environment variables using a .env file locally and Render’s environment variable dashboard in production. The --env flag on the import and linking scripts selects between swla_dev and swla_prod at runtime, making it safe to test destructive operations (like a full re-link run) in dev before touching prod.

# Example: run linker against dev only python scripts/link_hebert_census.py –env dev –race B MU # Push to prod only after dev results are satisfactory python scripts/link_hebert_census.py –env prod –race B MU

Render.com cold starts

On Render’s free tier, web services spin down after 15 minutes of inactivity and take 10–30 seconds to wake on the next request. For a research tool with intermittent traffic this is acceptable. The startup screen (“Service waking up…”) is shown to users while the container initializes. Upgrading to a paid Render instance eliminates cold starts if response time becomes a priority.


Python Flask GitHub Actions CI/CD Render.com MySQL SQLAlchemy