feat: add dockerfile, update sqlalchemy, fix template

This commit is contained in:
2026-01-11 20:42:58 +01:00
parent 95c8a5f066
commit 1b681ed101
7 changed files with 116 additions and 66 deletions

View File

@@ -0,0 +1,46 @@
---
name: Build and Publish Docker Image
on:
push:
branches:
- main
tags:
- 'v*'
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Log in to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: git.br0tkasten.de
username: ${{ gitea.actor }}
# access token of the user triggering this action
# in gitea -> user settings -> applications -> new token -> write:packages and write:repositories
# then in gitea -> user settings -> actions -> secrets -> add new secret named "TOKEN" with the value of the access token.
password: ${{ secrets.TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: git.br0tkasten.de/${{ gitea.repository }}
flavor: |
latest=true
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=sha
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

22
Dockerfile Normal file
View File

@@ -0,0 +1,22 @@
# Use an official Python runtime as a parent image
FROM python:3.11-slim
# Set the working directory in the container
WORKDIR /app
# Install curl for health check
RUN apt-get update && apt-get install -y curl libmagic1t64 && rm -rf /var/lib/apt/lists/*
COPY . .
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Add health check
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD curl http://localhost || exit 1
# Run the application using Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:80", "--workers", "4", "wsgi:app"]

70
app.py
View File

@@ -9,7 +9,7 @@ import string
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
app.secret_key = 'eng5iikeiwah3lae4idoo0woh4eiy6Th'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///homeschooling.db'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////app/homeschooling.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
@@ -30,42 +30,44 @@ def get_date():
date = datetime.now()
return { "now": date.strftime("%Y-%m-%d") }
@app.route('/', methods = ['GET', 'POST'])
@app.route('/', methods=['GET'])
def index():
if request.method == 'POST':
alle = []
zufall = []
for r in request.form.getlist('rechenreihen'):
alle.extend(rt_reihe.query.filter_by(set = r).all())
if request.form.get('anzahl'):
count = (int(request.form.get('anzahl')) + 1)
else:
count = len(alle)
reihen = db.session.execute(db.select(rt_rechenreihen).order_by(rt_rechenreihen.id)).scalars().all()
return render_template('generator.html', reihen=reihen)
while count > 1:
if len(alle) == 0:
break
term = alle.pop(random.randint(0,len(alle)-1))
term.c = ''
if request.form.get('gemischteAufgaben'):
maxValue = eval(str(term.a) + term.t.typ + str(term.b))
if random.randint(0,1):
term.c += ' + '
t = int(100 - maxValue)
maxValue = t
else:
term.c += ' - '
if maxValue <= 1:
alle.append(term)
continue
term.c += str(random.randint(1,maxValue))
zufall.append(term)
count -= 1
return render_template('arbeitsblatt.html',aufgaben=zufall,maxPerPage=int(request.form.get('maxPerPage')))
@app.route('/', methods=['POST'])
def index_post():
alle = []
zufall = []
for r in request.form.getlist('rechenreihen'):
alle.extend(db.session.execute(db.select(rt_reihe).filter_by(set=r)).scalars().all())
if request.form.get('anzahl'):
count = (int(request.form.get('anzahl')) + 1)
else:
return render_template('generator.html', reihen=rt_rechenreihen)
count = len(alle)
while count > 1:
if len(alle) == 0:
break
term = alle.pop(random.randint(0,len(alle)-1))
term.c = ''
if request.form.get('gemischteAufgaben'):
maxValue = eval(str(term.a) + term.t.typ + str(term.b))
if random.randint(0,1):
term.c += ' + '
t = int(100 - maxValue)
maxValue = t
else:
term.c += ' - '
if maxValue <= 1:
alle.append(term)
continue
term.c += str(random.randint(1,maxValue))
zufall.append(term)
count -= 1
return render_template('arbeitsblatt.html',aufgaben=zufall,maxPerPage=int(request.form.get('maxPerPage')))
if __name__ == "__main__":
app.run(debug=True)
app.run(debug=True)

8
app.sh
View File

@@ -1,8 +0,0 @@
#!/bin/sh
BASE=$(dirname $0)
cd $BASE
git pull
source env/bin/activate
pip3 install -r requirements.txt
gunicorn -D --bind 0.0.0.0:80 --pid /var/run/webapp.pid wsgi:app

View File

@@ -1,10 +1,10 @@
python-magic==0.4.15
Click==7.0
Flask==1.1.1
Flask-SQLAlchemy==2.4.1
gunicorn==20.0.4
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
SQLAlchemy==1.3.12
Werkzeug==0.16.0
python-magic
Click
Flask
Flask-SQLAlchemy
gunicorn
itsdangerous
Jinja2
MarkupSafe
SQLAlchemy
Werkzeug

View File

@@ -8,7 +8,7 @@
<td class="w3-cell-top">
<fieldset>
<legend>Multiplikation (a &middot; b = x)</legend>
{% for r in reihen.query.filter_by(typ = '*').order_by(reihen.id).all() %}
{% for r in reihen if r.typ == '*' %}
<input type="checkbox" name="rechenreihen" value="{{ r.id }}"> {{ r.name }}<br/>
{% endfor %}
</fieldset>
@@ -16,7 +16,7 @@
<td class="w3-cell-top">
<fieldset>
<legend>Division (a : b = x)</legend>
{% for r in reihen.query.filter_by(typ = '/').order_by(reihen.id).all() %}
{% for r in reihen if r.typ == '/' %}
<input type="checkbox" name="rechenreihen" value="{{ r.id }}"> {{ r.name }}<br/>
{% endfor %}
</fieldset>

View File

@@ -1,12 +0,0 @@
#!/sbin/openrc-run
name="busybox $SVCNAME"
command="/opt/webapp/app.sh"
command_args=""
pidfile="/var/run/$SVCNAME.pid"
depend() {
need net
use dns
}