Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions backend/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ clean-backend-docker:
@docker container rm -f nest-backend >/dev/null 2>&1 || true
@docker container rm -f nest-cache >/dev/null 2>&1 || true
@docker container rm -f nest-db >/dev/null 2>&1 || true
@docker container rm -f nest-nestbot >/dev/null 2>&1 || true
@docker container rm -f nest-worker >/dev/null 2>&1 || true
@docker image rm -f nest-backend:base >/dev/null 2>&1 || true
@docker image rm -f nest-nestbot:base >/dev/null 2>&1 || true
@docker image rm -f nest-local-backend >/dev/null 2>&1 || true
@docker image rm -f nest-local-nestbot >/dev/null 2>&1 || true
@docker image rm -f nest-snapshot-video >/dev/null 2>&1 || true
@docker volume rm -f nest-local_backend-venv >/dev/null 2>&1 || true
@docker volume rm -f nest-local_cache-data >/dev/null 2>&1 || true
@docker volume rm -f nest-local_nestbot-venv >/dev/null 2>&1 || true

create-superuser:
@CMD="python manage.py createsuperuser" $(MAKE) exec-backend-command-it
Expand Down
3 changes: 2 additions & 1 deletion backend/apps/ai/models/chunk.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""AI app chunk model."""

from django.db import models
from langchain.text_splitter import RecursiveCharacterTextSplitter
from pgvector.django import VectorField

from apps.ai.models.context import Context
Expand Down Expand Up @@ -34,6 +33,8 @@ def bulk_save(chunks, fields=None):
@staticmethod
def split_text(text: str) -> list[str]:
"""Split text into chunks."""
from langchain_text_splitters import RecursiveCharacterTextSplitter

Comment thread
coderabbitai[bot] marked this conversation as resolved.
return RecursiveCharacterTextSplitter(
chunk_size=200,
chunk_overlap=20,
Expand Down
3 changes: 2 additions & 1 deletion backend/apps/slack/common/handlers/ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import logging

from apps.ai.flows import process_query
from apps.slack.blocks import markdown
from apps.slack.utils import format_ai_response_for_slack

Expand Down Expand Up @@ -61,6 +60,8 @@ def process_ai_query(

"""
try:
from apps.ai.flows import process_query

return process_query(
query, images=images, channel_id=channel_id, is_app_mention=is_app_mention
)
Expand Down
915 changes: 196 additions & 719 deletions backend/poetry.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ packages = [ { include = "apps" } ]
[tool.poetry.dependencies]
algoliasearch = "^4.13.2"
algoliasearch-django = "^4.0.0"
crewai = { version = "^1.7.2", python = ">=3.10,<3.14" }
django = "^6.0"
django-configurations = "^2.5.1"
django-cors-headers = "^4.7.0"
Expand All @@ -27,9 +26,6 @@ geopy = "^2.4.1"
gunicorn = "^23.0.0"
humanize = "^4.11.0"
jinja2 = "^3.1.6"
langchain = "^0.3.26"
langchain-community = "^0.3.26"
langgraph = "^1.0.1"
lxml = "^6.0.0"
markdown = "^3.7"
openai = "~=1.83.0"
Expand Down Expand Up @@ -57,6 +53,10 @@ djlint = "^1.36.4"
pre-commit = "^4.1.0"
ruff = "^0.14.2"

[tool.poetry.group.nestbot.dependencies]
crewai = { version = "^1.7.2", python = ">=3.10,<3.14" }
langchain-text-splitters = "^1.1.1"

[tool.poetry.group.test.dependencies]
pytest = "^9.0.1"
pytest-cov = "^7.0"
Expand Down
52 changes: 45 additions & 7 deletions docker-compose/local/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ services:
DJANGO_DB_PORT: ${DJANGO_DB_PORT:-5432}
DJANGO_DB_USER: ${DJANGO_DB_USER:-nest_user_dev}
DJANGO_REDIS_HOST: ${DJANGO_REDIS_HOST:-nest-cache}
DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_HOST:-nest-cache-password}
DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_PASSWORD:-nest-cache-password}
# Disable Slack in backend - routes won't be registered
DJANGO_SLACK_BOT_TOKEN: None
DJANGO_SLACK_SIGNING_SECRET: None
Comment thread
Ani07-05 marked this conversation as resolved.
Outdated
networks:
- nest-network
ports:
Expand All @@ -32,6 +35,39 @@ services:
- ../../backend:/home/owasp
- backend-venv:/home/owasp/.venv

nestbot:
container_name: nest-nestbot
command: >
sh -c '
python manage.py migrate &&
python manage.py runserver 0.0.0.0:8001
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Outdated
'
image: nest-local-nestbot
build:
context: ../../backend
dockerfile: ../docker/backend/Dockerfile.nestbot.local
depends_on:
cache:
condition: service_healthy
db:
condition: service_healthy
env_file: ../../backend/.env
environment:
DJANGO_DB_HOST: ${DJANGO_DB_HOST:-db}
DJANGO_DB_NAME: ${DJANGO_DB_NAME:-nest_db_dev}
DJANGO_DB_PASSWORD: ${DJANGO_DB_PASSWORD:-nest_user_dev_password}
DJANGO_DB_PORT: ${DJANGO_DB_PORT:-5432}
DJANGO_DB_USER: ${DJANGO_DB_USER:-nest_user_dev}
DJANGO_REDIS_HOST: ${DJANGO_REDIS_HOST:-nest-cache}
DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_PASSWORD:-nest-cache-password}
networks:
- nest-network
ports:
- 8001:8001
volumes:
- ../../backend:/home/owasp
- nestbot-venv:/home/owasp/.venv

cache:
command: >
sh -c '
Expand Down Expand Up @@ -80,7 +116,7 @@ services:
networks:
- nest-network
ports:
- 8001:8001
- 8002:8001
volumes:
- ../../docs:/home/owasp/docs
- docs-venv:/home/owasp/.venv
Expand Down Expand Up @@ -114,28 +150,29 @@ services:
sh -c '
python manage.py rqworker ai --with-scheduler
'
image: nest-local-backend
image: nest-local-nestbot
depends_on:
backend:
condition: service_started
cache:
condition: service_healthy
db:
condition: service_healthy
nestbot:
condition: service_started
env_file: ../../backend/.env
environment:
DJANGO_DB_HOST: ${DJANGO_DB_HOST:-db}
DJANGO_DB_NAME: ${DJANGO_DB_NAME:-nest_db_dev}
DJANGO_DB_PASSWORD: ${DJANGO_DB_PASSWORD:-nest_user_dev_password}
DJANGO_DB_PORT: ${DJANGO_DB_PORT:-5432}
DJANGO_DB_USER: ${DJANGO_DB_USER:-nest_user_dev}
DJANGO_REDIS_HOST: ${DJANGO_REDIS_HOST:-cache}
DJANGO_REDIS_HOST: ${DJANGO_REDIS_HOST:-nest-cache}
DJANGO_REDIS_PASSWORD: ${DJANGO_REDIS_PASSWORD:-nest-cache-password}
# Worker needs Slack tokens for SlackConfig.app.client (inherited from .env)
networks:
- nest-network
volumes:
- ../../backend:/home/owasp
- backend-venv:/home/owasp/.venv
- nestbot-venv:/home/owasp/.venv

networks:
nest-network:
Expand All @@ -147,3 +184,4 @@ volumes:
docs-venv:
frontend-next:
frontend-node-modules:
nestbot-venv:
2 changes: 1 addition & 1 deletion docker/backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ USER owasp

COPY --chmod=444 --chown=root:root poetry.lock pyproject.toml ./
RUN --mount=type=cache,target=${POETRY_CACHE_DIR},uid=${OWASP_UID},gid=${OWASP_GID} \
poetry install --no-root --without dev --without test --without video
poetry install --no-root --without dev --without nestbot --without test --without video

COPY apps apps
COPY entrypoint.sh manage.py wsgi.py ./
Expand Down
47 changes: 11 additions & 36 deletions docker/backend/Dockerfile.local
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Docker Hardened Images (DHI) - requires: docker login dhi.io
# Use -dev variant for builder stage (includes build tools and shell)
FROM dhi.io/python:3.13-dev AS builder
# python:slim is used as base image to keep the image size small

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't need backend image to be based on python slim for NestBot I'd prefer to keep it based on alpine.

FROM python:3.13-slim AS builder
Comment thread
Ani07-05 marked this conversation as resolved.
Outdated

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

Expand All @@ -15,6 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libffi-dev \
libssl-dev \
libpq-dev \
passwd \
&& rm -rf /var/lib/apt/lists/* && \
groupadd -g ${OWASP_GID} owasp && \
Expand All @@ -28,62 +28,37 @@ RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
USER owasp
WORKDIR /home/owasp

# Copy files as root first, then fix ownership and permissions
USER root
COPY --chown=${OWASP_UID}:${OWASP_GID} poetry.lock pyproject.toml ./
RUN chmod 644 poetry.lock pyproject.toml

USER owasp

# Update lock file if pyproject.toml changed (e.g., Python version upgrade)
COPY --chmod=444 --chown=root:root poetry.lock pyproject.toml ./
RUN --mount=type=cache,target=${POETRY_CACHE_DIR},uid=${OWASP_UID},gid=${OWASP_GID} \
--mount=type=cache,target=${PIP_CACHE_DIR} \
poetry install --no-root --without dev --without test --without video
poetry install --no-root --without dev --without test --without video --without nestbot

# Use -dev variant for runtime stage to allow installing runtime dependencies
# Still hardened, just includes shell and package manager for flexibility
FROM dhi.io/python:3.13-dev
# Runtime stage using python:slim
FROM python:3.13-slim

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

ENV FORCE_COLOR=1 \
PIP_CACHE_DIR="/home/owasp/.cache/pip" \
PATH="/home/owasp/.venv/bin:/usr/local/bin:$PATH" \
PYTHONPATH="/home/owasp:/home/owasp/.venv/lib/python3.13/site-packages" \
VIRTUAL_ENV="/home/owasp/.venv" \
PATH="/home/owasp/.venv/bin:$PATH" \
PYTHONUNBUFFERED=1

RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-client \
libpq5 \
passwd \
curl \
&& rm -rf /var/lib/apt/lists/* && \
groupadd -g 1000 owasp && \
useradd -u 1000 -g owasp -m -s /bin/bash owasp

# Install poetry for runtime (needed for volume-based development setup)
RUN --mount=type=cache,target=/root/.cache/pip \
python3 -m pip install poetry --cache-dir /root/.cache/pip
RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
python -m pip install poetry --cache-dir ${PIP_CACHE_DIR}

EXPOSE 8000

USER owasp
WORKDIR /home/owasp

COPY --from=builder --chmod=555 --chown=root:root /home/owasp /home/owasp

# Fix ownership and permissions for volume compatibility
# Also backup .venv to /tmp for volume initialization
USER root
RUN if [ -d /home/owasp/.venv ]; then \
chown -R 1000:1000 /home/owasp/.venv && \
chmod -R u+w /home/owasp/.venv && \
cp -r /home/owasp/.venv /tmp/.venv-backup && \
chown -R 1000:1000 /tmp/.venv-backup; \
fi && \
mkdir -p /home/owasp/.local/share && \
chown -R 1000:1000 /home/owasp/.local && \
chmod -R u+w /home/owasp/.local

USER owasp
64 changes: 64 additions & 0 deletions docker/backend/Dockerfile.nestbot.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# python:slim is used as base image to keep the image size small
FROM python:3.13.7-slim AS builder

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

ENV OWASP_GID=1000 \
OWASP_UID=1000 \
PIP_CACHE_DIR="/home/owasp/.cache/pip" \
POETRY_CACHE_DIR="/home/owasp/.cache/pypoetry" \
POETRY_VIRTUALENVS_IN_PROJECT=true \
PYTHONUNBUFFERED=1

RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libffi-dev \
libssl-dev \
libpq-dev \
passwd \
&& rm -rf /var/lib/apt/lists/* && \
groupadd -g ${OWASP_GID} owasp && \
useradd -u ${OWASP_UID} -g owasp -m -s /bin/bash owasp && \
mkdir -p ${POETRY_CACHE_DIR} /home/owasp/.local/share && \
chown -R owasp:owasp /home/owasp

RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
python -m pip install poetry --cache-dir ${PIP_CACHE_DIR}

USER owasp
WORKDIR /home/owasp

COPY --chmod=444 --chown=root:root poetry.lock pyproject.toml ./
RUN --mount=type=cache,target=${POETRY_CACHE_DIR},uid=${OWASP_UID},gid=${OWASP_GID} \
--mount=type=cache,target=${PIP_CACHE_DIR} \
poetry install --no-root --without dev --without test --without video

# Runtime stage using python:slim
FROM python:3.13-slim

SHELL ["/bin/bash", "-o", "pipefail", "-c"]

ENV FORCE_COLOR=1 \
PIP_CACHE_DIR="/home/owasp/.cache/pip" \
PATH="/home/owasp/.venv/bin:$PATH" \
PYTHONUNBUFFERED=1

RUN apt-get update && \
apt-get install -y --no-install-recommends \
postgresql-client \
libpq5 \
passwd \
curl \
&& rm -rf /var/lib/apt/lists/* && \
groupadd -g 1000 owasp && \
useradd -u 1000 -g owasp -m -s /bin/bash owasp

RUN --mount=type=cache,target=${PIP_CACHE_DIR} \
python -m pip install poetry --cache-dir ${PIP_CACHE_DIR}

EXPOSE 8001

USER owasp
WORKDIR /home/owasp

COPY --from=builder --chmod=555 --chown=root:root /home/owasp /home/owasp