From 00c5d0bc4b19a3de8b7481682bb2cf05c90a0f09 Mon Sep 17 00:00:00 2001 From: Chris Sanden Date: Wed, 13 May 2026 16:38:46 +0200 Subject: [PATCH] Updated README to accurately reflect the repo --- README.md | 177 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 150 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index aac6ae5..30feb81 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,183 @@ -# flask-example +# Flask DevOps Reference Application -A minimal web app developed with [Flask](http://flask.pocoo.org/) framework. +This repository contains a modified Flask application used as a reference implementation for a DevOps setup for Auby & Brinch Finance. -The main purpose is to introduce how to implement the essential elements in web application with Flask, including +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. -- URL Building +## Project Context -- Authentication with Sessions +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. -- Template & Template Inheritance +The purpose of this repository is to demonstrate a suggested technical setup that supports: -- Error Handling +- 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 -- Integrating with *Bootstrap* +## Repository Structure -- Interaction with Database (SQLite) +```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 +``` -- Invoking static resources +## Local Development -For more basic knowledge of Flask, you can refer to [a tutorial on Tutorialspoint](https://www.tutorialspoint.com/flask/). +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 +``` -## How to Run +The application starts on: -- Step 1: Make sure you have Python +http://localhost:5000 -- Step 2: Install the requirements: `pip install -r requirements.txt` +Example login: -- Step 3: Go to this app's directory and run `python app.py` +```text +Username: admin +Password: admin +``` +## Running Tests +Run the automated test suite: -## Details about This Toy App +```bash +PYTHONPATH=. pytest -q +``` -There are three tabs in this toy app +Run tests with coverage reporting: -- **Public**: this is a page which can be accessed by anyone, no matter if the user has logged in or not. +```bash +PYTHONPATH=. pytest --cov=. --cov-report=term-missing +``` -- **Private**: Only logged-in user can access this page. Otherwise the user will get a 401 error page. +At the time of writing, the test suite covers basic routing, authentication behavior and selected authenticated actions, reaching approximately 69% coverage. -- **Admin Page**: This part is only open to the user who logged in as "Admin". In this tab, the administrator can manage accounts (list, delete, or add). +## Docker +Build the application image locally: -A few accounts were set for testing, like ***admin*** (password: admin), ***test*** (password: 123456), etc. You can also delete or add accounts after you log in as ***admin***. +```bash +docker build -t flask-devops-app . +``` +Run the image locally: +```bash +docker run --rm -p 5000:5000 flask-devops-app +``` -## References +The container uses Gunicorn: -- http://flask.pocoo.org/ +```bash +gunicorn -b 0.0.0.0:5000 app:app +``` -- https://www.tutorialspoint.com/flask/ +## Docker Compose +A local Compose setup is included: +```bash +docker compose up --build +``` -## Credict -Image private.jpg: https://commons.wikimedia.org/wiki/File:(315-365)_Locked_(6149414678).jpg +The Compose file starts: -Image public.jpg: https://commons.wikimedia.org/wiki/File:Drown%3F!_(131380682).jpg +- 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.