diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9c7fd7c..e3ffc52 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ on: - main - develop types: [opened, synchronize, reopened, ready_for_review] + workflow_dispatch: permissions: contents: read @@ -35,7 +36,7 @@ jobs: uses: actions/cache@v4 with: path: .venv - key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('pyproject.toml', 'src/**/*.py') }} + key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('requirements.txt', 'requirements-dev.txt') }} restore-keys: | venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}- @@ -44,15 +45,14 @@ jobs: run: | python -m venv .venv .venv/bin/pip install --upgrade pip - .venv/bin/pip install ".[dev]" - - - name: Re-install local package (ensures source changes are picked up) - if: steps.cache-venv.outputs.cache-hit == 'true' - run: .venv/bin/pip install --force-reinstall --no-deps ".[dev]" + .venv/bin/pip install -r requirements-dev.txt - name: Add venv to PATH run: echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH + - name: Set PYTHONPATH + run: echo "PYTHONPATH=${{ github.workspace }}/src" >> $GITHUB_ENV + - name: Create .env file for testing run: cp .env.example .env diff --git a/Dockerfile b/Dockerfile index 03e41b5..89d1350 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ LABEL org.opencontainers.image.description="Dynamischer Formular- & PDF-Generato WORKDIR /app -# Installiere Systemabhängigkeiten für WeasyPrint (Pango, Cairo, etc.) +# Layer 1: Systemabhängigkeiten für WeasyPrint (Pango, Cairo, etc.) – ändert sich quasi nie RUN apt-get update && apt-get install -y \ libpango-1.0-0 \ libpangoft2-1.0-0 \ @@ -16,11 +16,20 @@ RUN apt-get update && apt-get install -y \ curl \ && rm -rf /var/lib/apt/lists/* -COPY pyproject.toml . +# Layer 2: Python-Dependencies – ändert sich nur bei Dependency-Updates +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Layer 3: Anwendungscode – ändert sich häufig, aber nur dieser Layer wird invalidiert COPY src/ src/ -RUN pip install --no-cache-dir . +COPY app.py . +COPY forms/ forms/ + +ENV PYTHONPATH=/app/src -COPY . . +RUN mkdir -p /app/static && cp -r src/formflow/static/. /app/static/ + +RUN mkdir -p /data/forms /data/pdf_templates # Statische Dateien (CSS, JS, Standard-Logo) in den festen static-Pfad kopieren, # der von Flask als static_folder verwendet wird. diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index d59f1ed..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,36 +0,0 @@ -[build-system] -requires = ["setuptools>=69"] -build-backend = "setuptools.build_meta" - -[project] -name = "formflow" -version = "0.1.0" -description = "Dynamischer Formular- & PDF-Generator" -requires-python = ">=3.11" -dependencies = [ - "Flask==3.1.3", - "PyYAML==6.0.3", - "gunicorn==25.1.0", - "WeasyPrint==68.1", - "smbprotocol==1.16.0", - "pydantic==2.12.5", - "pydantic-settings==2.13.1", -] - -[project.optional-dependencies] -dev = [ - "pytest==9.0.2", - "requests==2.32.5", - "pytest-mock==3.15.1", -] - -[tool.setuptools.packages.find] -where = ["src"] -include = ["formflow*"] - -[tool.setuptools.package-data] -formflow = [ - "pdf_templates/*.html", - "templates/*.html", - "static/**/*", -] diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..7f82a9a --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,4 @@ +-r requirements.txt +pytest==9.0.2 +requests==2.32.5 +pytest-mock==3.15.1 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e786d28 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +Flask==3.1.3 +PyYAML==6.0.3 +gunicorn==25.1.0 +WeasyPrint==68.1 +smbprotocol==1.16.0 +pydantic==2.12.5 +pydantic-settings==2.13.1 diff --git a/update_dependencies.sh b/update_dependencies.sh index 193eb29..e046be9 100755 --- a/update_dependencies.sh +++ b/update_dependencies.sh @@ -10,10 +10,10 @@ echo "🔍 Prüfe auf Updates für alle Abhängigkeiten (das kann einen Moment d LATEST_BOOTSTRAP=$(curl -s "https://registry.npmjs.org/bootstrap/latest" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4) LATEST_SIGPAD=$(curl -s "https://registry.npmjs.org/signature_pad/latest" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4) -# --- 2. Backend (pyproject.toml) --- -CUR_FLASK=$(grep -i '"Flask==' pyproject.toml | grep -o '[0-9][^"]*' | head -1) -CUR_WEASYPRINT=$(grep -i '"WeasyPrint==' pyproject.toml | grep -o '[0-9][^"]*' | head -1) -CUR_SMBPROTO=$(grep -i '"smbprotocol==' pyproject.toml | grep -o '[0-9][^"]*' | head -1 || true) +# --- 2. Backend (requirements.txt) --- +CUR_FLASK=$(grep -i 'Flask==' requirements.txt | grep -o '[0-9][^[:space:]]*' | head -1) +CUR_WEASYPRINT=$(grep -i 'WeasyPrint==' requirements.txt | grep -o '[0-9][^[:space:]]*' | head -1) +CUR_SMBPROTO=$(grep -i 'smbprotocol==' requirements.txt | grep -o '[0-9][^[:space:]]*' | head -1 || true) CUR_FPDF2="(nicht installiert)" LATEST_FLASK=$(curl -s "https://pypi.org/pypi/Flask/json" | grep -o '"version":"[^"]*"' | head -1 | cut -d'"' -f4) @@ -39,7 +39,7 @@ echo "📦 Frontend (Lokale Dateien):" echo " Bootstrap: $BOOTSTRAP_VER -> $LATEST_BOOTSTRAP" echo " Signature Pad: $SIGPAD_VER -> $LATEST_SIGPAD" echo "" -echo "🐍 Backend (pyproject.toml):" +echo "🐍 Backend (requirements.txt):" echo " Flask: $CUR_FLASK -> $LATEST_FLASK" echo " WeasyPrint: $CUR_WEASYPRINT -> $LATEST_WEASYPRINT" if [ -n "$CUR_SMBPROTO" ]; then @@ -72,14 +72,14 @@ then echo "🔄 Aktualisiere Konfigurationsdateien..." # Sicherungsdateien anlegen, damit wir bei Buildfehlern zurückrollen können - cp pyproject.toml pyproject.toml.bak + cp requirements.txt requirements.txt.bak cp Dockerfile Dockerfile.bak tar cfz frontend-backup.tar.gz static/css static/js || true - # Update pyproject.toml - sed -i "s/\"Flask==[^\"]*\"/\"Flask==$LATEST_FLASK\"/" pyproject.toml - sed -i "s/\"WeasyPrint==[^\"]*\"/\"WeasyPrint==$LATEST_WEASYPRINT\"/" pyproject.toml - sed -i "s/\"smbprotocol==[^\"]*\"/\"smbprotocol==$LATEST_SMBPROTO\"/" pyproject.toml + # Update requirements.txt + sed -i "s/Flask==[^ ]*/Flask==$LATEST_FLASK/" requirements.txt + sed -i "s/WeasyPrint==[^ ]*/WeasyPrint==$LATEST_WEASYPRINT/" requirements.txt + sed -i "s/smbprotocol==[^ ]*/smbprotocol==$LATEST_SMBPROTO/" requirements.txt # Update Dockerfile sed -i "s/^FROM python:.*/FROM python:$LATEST_PYTHON/" Dockerfile @@ -102,7 +102,7 @@ then if [ -n "$BUILD_FAILED" ]; then echo "❌ Build fehlgeschlagen – rolle Änderungen zurück." - mv pyproject.toml.bak pyproject.toml + mv requirements.txt.bak requirements.txt mv Dockerfile.bak Dockerfile [ -f frontend-backup.tar.gz ] && tar xfz frontend-backup.tar.gz exit 1