# Flask DevOps Reference Application This repository contains a modified Flask application used as a reference implementation for a DevOps setup for Auby & Brinch Finance. The project demonstrates how a small development team can move from manual releases to a more controlled workflow using GitLab CI/CD, Docker, automated testing, container registry and Kubernetes deployments to separate staging and production environments. ## Project Context Auby & Brinch Finance currently has a small software team with limited DevOps experience. Their internal web application is important for daily business operations, and the company plans to grow the development team. The purpose of this repository is to demonstrate a suggested technical setup that supports: - Automated testing with coverage - Containerized application builds - GitLab Container Registry - Automated deployment to staging - Manual approval before production deployment - Separate Kubernetes namespaces for staging and production - SQLite for local development - PostgreSQL for staging and production - Gunicorn for containerized runtime ## Repository Structure ```text . ├── app.py # Flask application routes ├── database.py # SQLite/PostgreSQL database access ├── config.py # Flask configuration ├── requirements.txt # Python dependencies ├── Dockerfile # Container image definition ├── compose.yml # Local Docker Compose setup ├── .gitlab-ci.yml # GitLab CI/CD pipeline ├── .dockerignore # Files excluded from Docker build context ├── tests/ # Pytest test suite ├── manifests/ │ ├── stage/ # Kubernetes manifests for staging │ └── prod/ # Kubernetes manifests for production ├── templates/ # Flask HTML templates ├── static/ # Static assets ├── image_pool/ # Uploaded/example images └── database_file/ # Local SQLite databases ``` ## Local Development The application uses SQLite by default when DATABASE_URL is not set. ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt python app.py ``` The application starts on: http://localhost:5000 Example login: ```text Username: admin Password: admin ``` ## Running Tests Run the automated test suite: ```bash PYTHONPATH=. pytest -q ``` Run tests with coverage reporting: ```bash PYTHONPATH=. pytest --cov=. --cov-report=term-missing ``` At the time of writing, the test suite covers basic routing, authentication behavior and selected authenticated actions, reaching approximately 69% coverage. ## Docker Build the application image locally: ```bash docker build -t flask-devops-app . ``` Run the image locally: ```bash docker run --rm -p 5000:5000 flask-devops-app ``` The container uses Gunicorn: ```bash gunicorn -b 0.0.0.0:5000 app:app ``` ## Docker Compose A local Compose setup is included: ```bash docker compose up --build ``` The Compose file starts: - Flask application - PostgreSQL database When DATABASE_URL is set, the application uses PostgreSQL. Otherwise it uses the local SQLite database files. ## CI/CD Pipeline The GitLab pipeline is defined in .gitlab-ci.yml. Pipeline stages: ```text test -> build -> deploy ``` The pipeline: 1. Runs pytest with coverage. 2. Builds a Docker image with Kaniko. 3. Pushes the image to GitLab Container Registry. 4. Deploys automatically to staging when changes are merged to main. 5. Provides a manual production deployment job. ## Kubernetes Deployment Kubernetes manifests are stored in: ```text manifests/stage/ manifests/prod/ ``` The setup uses separate namespaces: ```text stage prod ``` Each environment contains manifests for: - Flask deployment - Flask service - PostgreSQL deployment - PostgreSQL service - PostgreSQL secret The Flask application receives a DATABASE_URL environment variable in staging and production. ## GitLab Variables The pipeline expects the following variables: ```text KUBECONFIGCONTENT CI_REGISTRY CI_REGISTRY_USER CI_REGISTRY_PASSWORD CI_REGISTRY_IMAGE CI_COMMIT_SHORT_SHA ``` Most CI_* variables are provided by GitLab automatically. KUBECONFIGCONTENT must be configured in GitLab CI/CD variables and should be protected. ## Operational Notes This reference setup demonstrates the delivery workflow. In a production rollout, PostgreSQL should use persistent storage, secrets should be managed outside the repository, and Kubernetes health checks/resource limits should be added.