feat(projekt-matching): deployment scripts and programmatic flow builder
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
67
projekt-matching/deploy/deploy_files.sh
Executable file
67
projekt-matching/deploy/deploy_files.sh
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
# Copy the projektmatch package and vorgaben files into the Langflow data dir
|
||||
# (mounted at /app/langflow in the container). Idempotent.
|
||||
#
|
||||
# NOTE: /home/tlg/mkt/bewerb/vorgaben/Lebenslauf_Dr-Ing_Thomas_Langer.md and
|
||||
# /home/tlg/mkt/bewerb/.secrets/espocrm-api.md are chmod 600, owned by tlg.
|
||||
# This script normally runs as the lwc automation user, which cannot read
|
||||
# those two files (verified: `cp` fails with EACCES). Rather than aborting
|
||||
# the whole deploy (set -e) on a permission error, each vorgaben file is
|
||||
# copied individually and a missing/unreadable file only produces a WARN,
|
||||
# so the parts of the pipeline that don't need it still deploy correctly.
|
||||
set -e
|
||||
SRC="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
DEST="$HOME/.local/share/langflow_pod/langflow-data"
|
||||
|
||||
rsync -a --delete --exclude __pycache__ "$SRC/projektmatch/" "$DEST/projektmatch/"
|
||||
mkdir -p "$DEST/vorgaben"
|
||||
for f in /home/tlg/mkt/bewerb/vorgaben/Lebenslauf_Dr-Ing_Thomas_Langer.md \
|
||||
/home/tlg/mkt/bewerb/vorgaben/rahmenbedingungen.md; do
|
||||
if [ -r "$f" ]; then
|
||||
cp "$f" "$DEST/vorgaben/"
|
||||
else
|
||||
echo "WARN: cannot read $f as $(whoami) (permission denied) - skipping" >&2
|
||||
fi
|
||||
done
|
||||
# Langflow runs as uid 1000 gid 0 -> needs group read
|
||||
chmod -R g+rX "$DEST/projektmatch" "$DEST/vorgaben"
|
||||
|
||||
# Make /app/langflow importable as a Python path root inside the container.
|
||||
# The component files (Task 9) do `sys.path.insert(0, "/app/langflow")` as
|
||||
# a *runtime* statement, but Langflow 1.10's custom-component loader
|
||||
# (lfx/custom/validate.py: prepare_global_scope/create_class) statically
|
||||
# scans the module's top-level `import`/`from ... import` AST nodes and
|
||||
# resolves them via importlib BEFORE executing any other code -- an `if:`
|
||||
# block containing the sys.path hack is a plain ast.If node, which that
|
||||
# loader silently drops without ever executing it. So "import projektmatch"
|
||||
# 404s both at design time (POST /custom_component, used by build_flows.py)
|
||||
# and at real flow-run time, regardless of the in-file sys.path trick,
|
||||
# unless /app/langflow is already on sys.path when the interpreter starts.
|
||||
# Fix: drop a .pth file into the venv's site-packages (only takes effect
|
||||
# for *new* Python processes, so the running langflow server needs a
|
||||
# restart to pick it up -- the venv itself lives in the container's
|
||||
# ephemeral overlay, not the bind-mounted data dir, so this must be
|
||||
# redone after any container recreation).
|
||||
CTR="langflow_ctr"
|
||||
if podman inspect "$CTR" >/dev/null 2>&1; then
|
||||
SITE_PKGS="$(podman exec "$CTR" python -c 'import site; print(site.getsitepackages()[0])')"
|
||||
PTH_FILE="$SITE_PKGS/projektmatch.pth"
|
||||
CURRENT="$(podman exec "$CTR" cat "$PTH_FILE" 2>/dev/null || true)"
|
||||
if [ "$CURRENT" != "/app/langflow" ]; then
|
||||
echo "Registering /app/langflow on container sys.path (restart required)..."
|
||||
podman exec "$CTR" sh -c "echo /app/langflow > '$PTH_FILE'"
|
||||
podman restart "$CTR" >/dev/null
|
||||
for i in $(seq 1 40); do
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8090/api/v1/auto_login || true)
|
||||
[ "$code" = "200" ] && break
|
||||
sleep 3
|
||||
done
|
||||
if [ "$code" != "200" ]; then
|
||||
echo "WARN: $CTR did not come back healthy after restart (last health code: $code)" >&2
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "WARN: container $CTR not found - skipping sys.path fix" >&2
|
||||
fi
|
||||
|
||||
echo "Deployed to $DEST"
|
||||
Reference in New Issue
Block a user