Compare commits

...

48 Commits

Author SHA1 Message Date
8429b666e1 changed to v3
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 55s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m6s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 28s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m12s
only wanted to exec pipeline
2025-12-15 06:30:21 +00:00
d072e18124 Changed demo site version
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 14s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m15s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 27s
only to test pipeline
2025-12-09 06:20:27 +00:00
c356fca133 Revised Index.html
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m0s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 26s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m9s
2025-12-04 10:21:09 +00:00
0205a5f90b edited template/index.html
Some checks failed
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Failing after 11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Has been skipped
2025-12-04 10:16:35 +00:00
50d41b7da5 Added flavour to site
Some checks failed
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Failing after 11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Has been skipped
2025-12-04 10:13:53 +00:00
811885a258 Added welcome to website
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m0s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 27s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m11s
2025-12-04 10:06:51 +00:00
2ff402a68c Updated website header
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 12s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 58s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 24s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m8s
TEST
2025-12-04 09:47:42 +00:00
02d671d1f0 Update main website
Some checks failed
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 59s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m2s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 26s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Failing after 25s
2025-12-04 09:39:40 +00:00
986ed7f72d Force recreate pipeline
All checks were successful
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 52s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Successful in 1m5s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Successful in 37s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Successful in 1m10s
2025-11-27 11:53:00 +00:00
7b541269a1 adjusted client max boidy size
Some checks failed
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 12s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Failing after 3m11s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Has been skipped
fit to artifact size
2025-11-27 11:36:14 +00:00
cb404c8faa updated artifact implementation on pipeline
Some checks failed
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / test (push) Successful in 12s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / build (push) Failing after 3m41s
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / scan (push) Has been skipped
Build and Deploy Demo App (Artifacts, GHES/Gitea-safe) / deploy (push) Has been skipped
2025-11-27 11:23:30 +00:00
612b204c9a Adjusted artifact version in pipeline
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 1m35s
2025-11-27 11:20:02 +00:00
9f58cec1e4 artifacts implemented in cicd
Some checks failed
Build and Deploy Demo App (Artifacts) / test (push) Successful in 11s
Build and Deploy Demo App (Artifacts) / build (push) Failing after 29s
Build and Deploy Demo App (Artifacts) / scan (push) Has been skipped
Build and Deploy Demo App (Artifacts) / deploy (push) Has been skipped
2025-11-27 11:08:06 +00:00
a286600240 added tags to readme
All checks were successful
Build and Deploy Demo App / test (push) Successful in 12s
Build and Deploy Demo App / build (push) Successful in 8s
Build and Deploy Demo App / scan (push) Successful in 19s
Build and Deploy Demo App / deploy (push) Successful in 1m9s
2025-11-27 10:08:48 +00:00
669c3ce985 Updated README
All checks were successful
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 19s
Build and Deploy Demo App / deploy (push) Successful in 1m10s
2025-11-27 10:00:33 +00:00
a12faab953 Adjusted README Info
Some checks failed
Build and Deploy Demo App / test (push) Successful in 14s
Build and Deploy Demo App / build (push) Successful in 8s
Build and Deploy Demo App / scan (push) Successful in 23s
Build and Deploy Demo App / deploy (push) Failing after 25s
2025-11-27 09:56:28 +00:00
9fc2316459 fixed app unhealthy status
All checks were successful
Build and Deploy Demo App / build (push) Successful in 15s
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / scan (push) Successful in 20s
Build and Deploy Demo App / deploy (push) Successful in 1m10s
2025-11-26 14:38:58 +03:30
0c5eaa19cd removed features.seed-db
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 15s
Build and Deploy Demo App / deploy (push) Failing after 2m14s
Build and Deploy Demo App / scan (push) Successful in 19s
2025-11-26 13:58:30 +03:30
ea335c96d0 Refactored Dockerfile
Some checks failed
Build and Deploy Demo App / test (push) Successful in 12s
Build and Deploy Demo App / build (push) Successful in 16s
Build and Deploy Demo App / scan (push) Successful in 19s
Build and Deploy Demo App / deploy (push) Failing after 2m13s
2025-11-26 13:50:06 +03:30
09af728f80 refactored deployment phase
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 18s
Build and Deploy Demo App / deploy (push) Failing after 47s
2025-11-26 13:39:16 +03:30
a8699e2eb4 refactored deployment phase
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 18s
Build and Deploy Demo App / deploy (push) Failing after 26s
2025-11-26 13:35:31 +03:30
e6921d00f5 refactored deployment phase
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 18s
Build and Deploy Demo App / deploy (push) Failing after 25s
2025-11-26 13:32:13 +03:30
35522c3f8d Refactored Ci/Cd pipeline
All checks were successful
Build and Deploy Demo App / test (push) Successful in 1m2s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 21s
Build and Deploy Demo App / deploy (push) Successful in 26s
2025-11-26 13:19:04 +03:30
1f2e223b42 refactor cicd pipeline
All checks were successful
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 7s
Build and Deploy Demo App / scan (push) Successful in 26s
Build and Deploy Demo App / deploy (push) Successful in 37s
2025-11-26 13:11:55 +03:30
c473ffbd16 refactor cicd pipeline
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Successful in 20s
Build and Deploy Demo App / scan (push) Failing after 8s
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 13:03:25 +03:30
340d3ed95c Improved Pipeline manifest
Some checks failed
Build and Deploy Demo App / test (push) Successful in 12s
Build and Deploy Demo App / build_scan_deploy (push) Failing after 10m42s
2025-11-26 12:24:05 +03:30
717b059670 Improved Pipeline manifest
Some checks failed
Build and Deploy Demo App / test (push) Successful in 12s
Build and Deploy Demo App / build (push) Successful in 5m32s
Build and Deploy Demo App / scan (push) Failing after 11s
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 12:12:43 +03:30
428b11e37a Improved Project
Some checks failed
Build and Deploy Demo App / test (push) Successful in 11s
Build and Deploy Demo App / build (push) Failing after 5m49s
Build and Deploy Demo App / scan (push) Has been skipped
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 12:00:04 +03:30
95dd832303 Improved Project 2025-11-26 11:58:06 +03:30
deeada2479 revised testing critera 2025-11-26 11:56:04 +03:30
78da8a061f revised testing critera
Some checks failed
Build and Deploy Demo App / test (push) Successful in 12s
Build and Deploy Demo App / build (push) Successful in 7m51s
Build and Deploy Demo App / scan (push) Failing after 6m24s
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 11:30:52 +03:30
44926969ce fixed testing script
Some checks failed
Build and Deploy Demo App / test (push) Failing after 11s
Build and Deploy Demo App / build (push) Has been skipped
Build and Deploy Demo App / scan (push) Has been skipped
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 11:23:48 +03:30
b3a9f19501 fixed tests env setup
Some checks failed
Build and Deploy Demo App / test (push) Failing after 10s
Build and Deploy Demo App / build (push) Has been skipped
Build and Deploy Demo App / scan (push) Has been skipped
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 11:22:07 +03:30
a7940b2044 fixed testing script
Some checks failed
Build and Deploy Demo App / test (push) Failing after 12s
Build and Deploy Demo App / build (push) Has been skipped
Build and Deploy Demo App / scan (push) Has been skipped
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 11:17:00 +03:30
fcd328ca2b Improved Application/DB
Some checks failed
Build and Deploy Demo App / test (push) Failing after 1m14s
Build and Deploy Demo App / build (push) Has been skipped
Build and Deploy Demo App / scan (push) Has been skipped
Build and Deploy Demo App / deploy (push) Has been skipped
2025-11-26 11:03:01 +03:30
c442b16a45 disabled auto certbot, switched to nginx:alpine
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 46s
2025-11-26 10:49:29 +03:30
af30ff772b manual ssl handler edit
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 34s
2025-11-26 10:40:48 +03:30
134b3d7538 fixed ssl cert handler
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 1m11s
2025-11-26 10:28:28 +03:30
7b85004b70 adjusted docker compose volume mount
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 46s
2025-11-26 09:45:35 +03:30
5a2ca2c037 fixing compose
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 35s
2025-11-26 01:21:03 +03:30
913e7f531a adding reverse proxy and letsEncrypt
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 45s
2025-11-26 01:11:39 +03:30
ae96b79fb2 adding reverse proxy with ssl
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 33s
2025-11-26 00:59:21 +03:30
acb7df5cf9 improved index
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 1m56s
2025-11-25 18:56:49 +03:30
cf8df36d4f improved project
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 50s
2025-11-25 18:52:52 +03:30
d00626a62c improved project
Some checks failed
Build and Deploy Demo App / build-and-deploy (push) Failing after 18s
2025-11-25 18:49:09 +03:30
a4a588be94 deploying cicd demo app
All checks were successful
Build and Deploy Demo App / build-and-deploy (push) Successful in 1m42s
2025-11-25 18:20:52 +03:30
aba3c9cb98 edit runner label
All checks were successful
Hello from Gitea Actions / hello (push) Successful in 1m3s
2025-11-25 11:41:50 +03:30
beea66532d edit runner label 2025-11-25 11:37:05 +03:30
10 changed files with 441 additions and 13 deletions

View File

@@ -1,20 +1,141 @@
name: Hello from Gitea Actions # .gitea/workflows/cicd.yaml
name: Build and Deploy Demo App (Artifacts, GHES/Gitea-safe)
on: on:
push: # run on every push push:
branches: branches: [ main ]
- main # adjust if your default branch is different
jobs: jobs:
hello: # ---------- TEST ----------
runs-on: devops # must match your runner's label test:
runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Say hello - name: Set up Python
run: | uses: actions/setup-python@v5
echo "Hello from Gitea Actions!" with:
echo "Runner: ${{ runner.name }}" python-version: "3.12"
echo "Repo: ${{ gitea.repository }}"
- name: Install deps
run: pip install -r requirements.txt
- name: Run tests (SQLite fallback)
env:
DB_USER: "" # force SQLite fallback in app.py
DB_PASS: ""
DB_NAME: ""
run: pytest
# ---------- BUILD ----------
build:
needs: test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t demo-app:latest .
- name: Save Docker image to tar
run: docker save demo-app:latest > demo-app.tar
# IMPORTANT: use v3 on Gitea/GHES
- name: Upload image artifact
uses: actions/upload-artifact@v3
with:
name: demo-image
path: demo-app.tar
if-no-files-found: error
# retention-days: 7 # optional; depends on your Gitea settings
# ---------- SCAN ----------
scan:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# IMPORTANT: use v3 on Gitea/GHES
- name: Download image artifact
uses: actions/download-artifact@v3
with:
name: demo-image
path: . # place demo-app.tar in the workspace root
- name: Load Docker image from artifact
run: docker load -i demo-app.tar
- name: Scan image with Trivy
run: |
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy:latest \
image --exit-code 1 --severity CRITICAL,HIGH --no-progress demo-app:latest
# ---------- DEPLOY ----------
deploy:
needs: [build, scan]
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# IMPORTANT: use v3 on Gitea/GHES
- name: Download image artifact
uses: actions/download-artifact@v3
with:
name: demo-image
path: .
- name: Set up SSH
run: |
apt update && apt install -y openssh-client
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-keyscan -p ${{ secrets.SERVER_PORT }} ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Copy files to server
run: |
scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} \
demo-app.tar \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:"${{ secrets.DEPLOY_PATH }}/demo-app.tar"
scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} \
docker-compose.yml \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:"${{ secrets.DEPLOY_PATH }}/docker-compose.yml"
scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} -r \
nginx_user_conf.d \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:"${{ secrets.DEPLOY_PATH }}/nginx_user_conf.d"
- name: Deploy on server
run: |
ssh -o StrictHostKeyChecking=no -p ${{ secrets.SERVER_PORT }} \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} << 'EOF'
set -e
cd "${{ secrets.DEPLOY_PATH }}"
# Write DB secrets for compose
echo "DB_USER=${{ secrets.DB_USER }}" > .env
echo "DB_PASS=${{ secrets.DB_PASS }}" >> .env
echo "DB_NAME=${{ secrets.DB_NAME }}" >> .env
# Load image and restart stack
docker load -i demo-app.tar
if [ ! -f docker-compose.yml ]; then
echo "ERROR: docker-compose.yml not found in $(pwd)" >&2
ls -la
exit 1
fi
docker compose -f docker-compose.yml down
docker compose -f docker-compose.yml --env-file .env up -d --remove-orphans
rm -f demo-app.tar
EOF

21
Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
# Build stage
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
# NEW: Copy binaries like gunicorn
COPY --from=builder /usr/local/bin /usr/local/bin
COPY app.py models.py .
COPY templates ./templates
# NEW: Install wget for healthcheck (run as root, before switching user)
RUN apt-get update && apt-get install -y --no-install-recommends wget && rm -rf /var/lib/apt/lists/*
RUN useradd -m appuser
USER appuser
EXPOSE 5000
HEALTHCHECK --interval=30s --timeout=3s CMD wget --no-verbose --tries=1 --spider http://localhost:5000/ || exit 1
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]

View File

@@ -1,3 +1,5 @@
# devops # tags: DevOps CI/CD Pipeline Gitea Docker
DevOps PPC DevOps CI/CD Pipeline Demo Application
Prod project implementation

38
app.py Normal file
View File

@@ -0,0 +1,38 @@
import os
from flask import Flask, render_template
from flask_bootstrap import Bootstrap5
from models import db, Feature
app = Flask(__name__)
# Database config
db_user = os.getenv('DB_USER')
db_pass = os.getenv('DB_PASS')
db_name = os.getenv('DB_NAME')
app.config['SQLALCHEMY_DATABASE_URI'] = (
f'postgresql://{db_user}:{db_pass}@db:5432/{db_name}'
if db_user else 'sqlite:///:memory:'
)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
bootstrap = Bootstrap5(app)
db.init_app(app)
# ────────────────────────────────
# THIS IS THE MISSING PART:
# Create tables + seed data ONCE at startup
# ────────────────────────────────
with app.app_context():
db.create_all() # ← Creates the "feature" table if missing
Feature.seed_db() # ← Now works without error
@app.route('/')
def index():
features = Feature.query.all()
return render_template('index.html', features=features)
# Optional: nice health endpoint that doesn't touch DB
@app.route('/health')
def health():
return "OK", 200

65
docker-compose.yml Normal file
View File

@@ -0,0 +1,65 @@
services:
db:
image: postgres:16-alpine
container_name: demo-db
restart: unless-stopped
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASS}
POSTGRES_DB: ${DB_NAME}
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
interval: 10s
timeout: 5s
retries: 5
app:
image: demo-app:latest
container_name: demo-app
restart: unless-stopped
environment:
- DB_USER=${DB_USER}
- DB_PASS=${DB_PASS}
- DB_NAME=${DB_NAME}
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--spider", "http://localhost:5000"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: jonasal/nginx-certbot:latest
container_name: demo-nginx
restart: unless-stopped
ports:
- 8008:80
- 4433:443
environment:
- CERTBOT_EMAIL=the.dark.mist23@gmail.com
- ENVSUBST_TEMPLATE_SUFFIX=.tmpl
- CERTBOT_DISABLED=true
volumes:
- ./nginx_user_conf.d:/etc/nginx/conf.d/
- letsencrypt:/etc/letsencrypt
- /home/devroot/demo/certs/fullchain.pem:/etc/nginx/ssl/origin_cert.pem:ro
- /home/devroot/demo/certs/prvkey.pem:/etc/nginx/ssl/origin_key.key:ro
depends_on:
app:
condition: service_healthy
logging:
driver: json-file
options:
max-size: 10m
networks:
default:
driver: bridge
volumes:
letsencrypt:
db-data:

31
models.py Normal file
View File

@@ -0,0 +1,31 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Feature(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
description = db.Column(db.String(200), nullable=False)
@staticmethod
def seed_db():
# Seed only if empty
if Feature.query.count() == 0:
features = [
Feature(
title="Responsive Design",
description="Adapts seamlessly to mobile, tablet, and desktop devices.",
),
Feature(
title="Modern UI",
description="Uses Bootstrap 5 for clean, professional styling.",
),
Feature(
title="Easy Deployment",
description="Containerized with Docker for quick setup on any server.",
),
]
db.session.bulk_save_objects(features)
db.session.commit()

View File

@@ -0,0 +1,32 @@
server {
listen 80;
server_name demo.networkwizard.xyz;
location / {
return 301 https://$host:4433$request_uri;
}
}
server {
listen 443 ssl;
server_name demo.networkwizard.xyz;
ssl_certificate /etc/nginx/ssl/origin_cert.pem;
ssl_certificate_key /etc/nginx/ssl/origin_key.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
client_max_body_size 2g; # allow big artifacts
proxy_read_timeout 600s;
proxy_send_timeout 600s;
location / {
proxy_pass http://app:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

6
requirements.txt Normal file
View File

@@ -0,0 +1,6 @@
flask==3.0.3
bootstrap-flask==2.5.0
gunicorn==22.0.0
flask-sqlalchemy==3.1.1
psycopg2-binary==2.9.9 # Postgres driver
pytest==8.3.3 # For tests

72
templates/index.html Normal file
View File

@@ -0,0 +1,72 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Professional Demo Site</title>
{{ bootstrap.load_css() }}
<style>
body { padding-top: 60px; }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="/">Professional Demo Site V3</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarNav" aria-controls="navbarNav"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#features">Features</a></li>
<li class="nav-item"><a class="nav-link" href="#about">About</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="bg-primary text-white py-5 mt-4 rounded text-center">
<h1 class="display-4">Professional Demo Site</h1>
<p class="lead">
This is a realistic, Bootstrap-powered Flask application with DB integration for demonstration.
</p>
<a class="btn btn-light btn-lg" href="#features" role="button">Learn More</a>
</div>
<section id="features" class="py-5">
<h2 class="text-center mb-4">Key Features (from DB)</h2>
<div class="row">
{% for feature in features %}
<div class="col-md-4">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">{{ feature.title }}</h5>
<p class="card-text">{{ feature.description }}</p>
</div>
</div>
</div>
{% endfor %}
</div>
</section>
<section id="about" class="py-5 bg-light">
<h2 class="text-center mb-4">About This Demo</h2>
<p class="text-center">
Now with PostgreSQL for data persistence. Extend with more models and queries.
</p>
</section>
</div>
{{ bootstrap.load_js() }}
</body>
</html>

40
test_app.py Normal file
View File

@@ -0,0 +1,40 @@
import os
import pytest
# Ensure tests always use the in-memory SQLite DB, even if CI sets DB_* secrets
for var in ("DB_USER", "DB_PASS", "DB_NAME"):
os.environ.pop(var, None)
from app import app
from models import db, Feature
@pytest.fixture
def client():
app.config["TESTING"] = True
# app was already initialised with SQLite because DB_USER is now unset
# Fresh DB per test
with app.app_context():
db.drop_all()
db.create_all()
with app.test_client() as client:
yield client
# Clean up after test
with app.app_context():
db.drop_all()
def test_index(client):
response = client.get("/")
assert response.status_code == 200
assert b"Professional Demo Site" in response.data
def test_seed_db(client):
with app.app_context():
Feature.seed_db()
assert Feature.query.count() == 3