diff --git a/.dockerignore b/.dockerignore index d43f823..c39c107 100644 --- a/.dockerignore +++ b/.dockerignore @@ -56,6 +56,15 @@ build/ *.egg-info/ dist/ .pytest_cache/ +*.ipynb +.ipynb_checkpoints/ +*.coverage +htmlcov/ + +# AI service specific +services/ai-service/data/evaluations/ +services/ai-service/data/reports/ +services/ai-service/test.ipynb # Temporary files *.tmp diff --git a/.github/.copilot-instructions.md b/.github/.copilot-instructions.md index f58ea44..0b6516c 100644 --- a/.github/.copilot-instructions.md +++ b/.github/.copilot-instructions.md @@ -4,6 +4,7 @@ - Treat all backends as APIs; do not couple services together. - The AI service is stateless and must not call application APIs directly. - always use pnpm and pnpx for package management +- don't write unnecessary markdown files or documentation, prefer inline code comments and self documenting code where possible. ## Monorepo Structure @@ -32,6 +33,7 @@ - Use Tailwind CSS for styling. - Prefer shadcn/ui components where applicable. - Do not create ad-hoc UI components in app folders. +- [tanstack-start](https://tanstack.com/start/llms.txt) is the frontend application framework ## Forms & State diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..851a84e --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,76 @@ +name: Build and Push Docker Images + +on: + push: + branches: + - main + - dev + tags: + - 'v*' + pull_request: + branches: + - main + - dev + workflow_dispatch: + +env: + REGISTRY: docker.io + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + strategy: + matrix: + include: + - dockerfile: ai.dockerfile + image: governance-agent-ai_service + context: . + - dockerfile: next.dockerfile + image: governance-agent-frontend + context: . + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ secrets.DOCKERHUB_USERNAME }}/${{ matrix.image }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: ${{ matrix.context }} + file: ${{ matrix.dockerfile }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64 + + - name: Image digest + run: echo "Image pushed with digest ${{ steps.build.outputs.digest }}" diff --git a/ai.dockerfile b/ai.dockerfile index 9f59ff8..f80fa5d 100644 --- a/ai.dockerfile +++ b/ai.dockerfile @@ -1,18 +1,55 @@ -FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim +# Build stage +FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS builder WORKDIR /app ENV UV_COMPILE_BYTECODE=1 ENV PYTHONPATH=/app/src +ENV UV_INDEX_STRATEGY=unsafe-best-match +ENV UV_HTTP_TIMEOUT=300 -COPY services/ai-service/pyproject.toml ./ +# Copy dependency files for caching +COPY services/ai-service/pyproject.toml services/ai-service/uv.lock ./ +# Install CPU-only PyTorch to reduce image size dramatically +RUN uv pip install --system --no-cache \ + torch==2.5.1+cpu \ + --index-url https://download.pytorch.org/whl/cpu + +# Install other dependencies RUN uv sync --no-install-project --no-dev COPY services/ai-service/ ./ RUN uv sync --no-dev +# Remove unnecessary files +RUN find /app/.venv -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true +RUN find /app/.venv -type f -name "*.pyc" -delete +RUN find /app/.venv -type f -name "*.pyo" -delete +RUN find /app/.venv -name "tests" -type d -exec rm -rf {} + 2>/dev/null || true +RUN find /app/.venv -name "test" -type d -exec rm -rf {} + 2>/dev/null || true + +# Runtime stage +FROM python:3.13-slim-bookworm + +WORKDIR /app + +ENV PYTHONPATH=/app/src +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 + +# Install runtime dependencies only +RUN apt-get update && apt-get install -y --no-install-recommends \ + libgomp1 \ + && rm -rf /var/lib/apt/lists/* + +# Copy only the virtual environment and application code +COPY --from=builder /app/.venv /app/.venv +COPY --from=builder /app/src /app/src +COPY --from=builder /app/run.py /app/run.py +COPY --from=builder /app/main.py /app/main.py + # Create non-root user RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app USER appuser diff --git a/apps/tanstack-start/package.json b/apps/tanstack-start/package.json index e26f9de..df5e667 100644 --- a/apps/tanstack-start/package.json +++ b/apps/tanstack-start/package.json @@ -10,7 +10,7 @@ "format": "prettier --check . --ignore-path ../../.gitignore --ignore-path .prettierignore", "lint": "eslint --flag unstable_native_nodejs_ts_config", "typecheck": "tsc --noEmit", - "with-env": "dotenv -e ../../.env --" + "with-env": "dotenv -e ../../.env.local --" }, "dependencies": { "@fontsource-variable/geist": "^5.2.8", @@ -19,6 +19,7 @@ "@governance/auth": "workspace:*", "@governance/db": "workspace:*", "@governance/ui": "workspace:*", + "@radix-ui/themes": "^3.3.0", "@t3-oss/env-core": "^0.13.8", "@tanstack/react-form": "catalog:", "@tanstack/react-query": "catalog:", @@ -29,6 +30,8 @@ "@trpc/client": "catalog:", "@trpc/server": "catalog:", "@trpc/tanstack-react-query": "catalog:", + "@workos-inc/widgets": "^1.8.0", + "@workos-inc/widgets-i18n": "^0.1.0", "@workos/authkit-tanstack-react-start": "^0.5.0", "nitro": "3.0.1-alpha.1", "react": "catalog:react19", diff --git a/apps/tanstack-start/src/component/NotFound.tsx b/apps/tanstack-start/src/component/NotFound.tsx index c4e06aa..88028f0 100644 --- a/apps/tanstack-start/src/component/NotFound.tsx +++ b/apps/tanstack-start/src/component/NotFound.tsx @@ -1,26 +1,28 @@ import { Link, useLocation } from "@tanstack/react-router"; export function NotFound() { - const location = useLocation(); - console.log("NotFound triggered for path:", location.pathname); + const location = useLocation(); + console.log("NotFound triggered for path:", location.pathname); - return ( -
- {subtitle} -
-{subtitle}
+
-
+ return (
+
+
- {/* Navigation */}
-
- + {error.message || "An unexpected error occurred"} +
+