Production-ready Flask app with complete GitHub Actions CI/CD pipeline using self-hosted runner!
- π 6-Stage CI/CD Pipeline: Build β Test β Quality β Reports β Notify β Deploy
- π₯οΈ Self-Hosted Runner: Direct Docker deployment to production VM
- π§ͺ Multi-Python Testing: Python 3.9, 3.10, 3.11 matrix
- π 85% Code Coverage requirement with HTML dashboards
- π‘οΈ Security Scanning: Bandit + Secret Detection
- π Zero-Downtime Deployments with health checks & rollback
- π¨ Production Reports: Interactive coverage dashboards
Backend: Flask (Python 3.9+)
CI/CD: GitHub Actions + Self-Hosted Runner
Container: Docker + GHCR
Testing: pytest + pytest-cov (85% coverage)
Linting: flake8 + pylint
Security: Bandit + detect-secrets
Deployment: Direct Docker (no SSH!)
git clone https://github.com/aatirFound42/python-cicd-app.git
cd python-cicd-app
pip install -r requirements.txt# Development
flask run
# Production mode
FLASK_ENV=production flask run --host=0.0.0.0 --port=5000# Build
docker build -t python-cicd-app .
# Run
docker run -p 8000:5000 python-cicd-appAccess: http://localhost:8000
| Stage | Runner | Purpose |
|---|---|---|
| Build | ubuntu-latest |
Docker image β GHCR |
| Test | ubuntu-latest |
pytest matrix 3.9-3.11 |
| Quality | ubuntu-latest |
85% coverage gate |
| Reports | ubuntu-latest |
HTML dashboards |
| Deploy | self-hosted |
π Production VM |
develop β Tests β Quality Gates β Coverage Reports
β (main + approve)
main β Build β Deploy to VM:8000 β Health Check β
Ubuntu 20.04+ / Docker 20+
GitHub Runner v2.330.0
Port 8000 open
# On production VM
sudo apt install docker.io
sudo useradd -m -G docker runner
sudo su - runner
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.330.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.330.0/actions-runner-linux-x64-2.330.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.330.0.tar.gz
./config.sh --url https://github.com/aatirFound42/python-cicd-app --token YOUR_TOKEN
./run.sh # Keep running!Repo β Settings β Environments β production:
CONTAINER_NAME=python-cicd-app-prod
CONTAINER_PORT_HOST=8000
β
85% Code Coverage (3 Python versions)
β
Linting: flake8 + pylint
β
Security: Bandit scan
β
Secrets: detect-secrets
β
Multi-stage testing
β
Health check deployment
VM Local: http://localhost:8000
Network: http://YOUR_VM_IP:8000
Internet: http://PUBLIC_IP:8000 (port forward 8000)
python-cicd-app/
βββ app/ # Flask application
β βββ __init__.py
β βββ routes.py
βββ tests/ # pytest tests
βββ requirements.txt # Python dependencies
βββ Dockerfile # Production Docker image
βββ .github/
β βββ workflows/
β βββ python-cicd.yml # Complete pipeline
βββ docker-compose.yml # Local development
βββ README.md # This file!
# Install test deps
pip install -r requirements.txt pytest pytest-cov
# Run tests + coverage
pytest tests/ --cov=app --cov-report=html
# View coverage
open htmlcov/index.html1. git checkout -b feature/xyz
2. code β commit β push
3. Tests run automatically (develop)
4. Merge develop β main (production deploy)
5. VM auto-deploys: docker pull β docker run
After pipeline runs:
Actions β Artifacts β all-coverage-reports
β Interactive HTML dashboards for 3 Python versions
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
HEALTHCHECK --interval=30s CMD curl -f http://localhost:5000/health
CMD ["gunicorn", "app:app", "-b", "0.0.0.0:5000"]β
Self-hosted = FREE unlimited minutes
β
No SSH complexity
β
Automatic rollbacks
β
Multi-environment testing
β
Production dashboards
β
Zero-downtime deploys
β
Scalable to teams
- Fork repository
- Create feature branch (
git checkout -b feature/xyz) - Commit changes (
git commit -m "Add feature") - Push (
git push origin feature/xyz) - Open Pull Request
All PRs run full CI/CD pipeline automatically!
MIT License - Free to use & modify!
β Star this repo if you found the self-hosted CI/CD setup helpful!