Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
95 changes: 95 additions & 0 deletions .github/workflows/test-and-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Test and lint

on:
push:
branches:
- "**"
pull_request:
branches:
- main
- develop

jobs:
backend:
name: Backend tests and Ruff
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16
env:
POSTGRES_DB: ai4mdestudio
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd="pg_isready -U postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=5

defaults:
run:
working-directory: api

env:
POSTGRES_DB: ai4mdestudio
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_HOST: localhost
POSTGRES_PORT: 5432
SECRET_KEY: test-secret-key
DEBUG: "True"

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install Poetry
run: pipx install poetry

- name: Install backend dependencies
run: poetry install --no-interaction --no-root

- name: Show test files
run: find model -name "tests.py" -o -path "*/tests/*.py"

- name: Run Django tests
run: poetry run python model/manage.py test metadata diagram generator prose prompt -v 2

- name: Run Ruff
run: poetry run ruff check .

frontend:
name: Frontend tests and build
runs-on: ubuntu-latest

defaults:
run:
working-directory: frontend

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: frontend/package-lock.json

- name: Install frontend dependencies
run: npm ci

- name: Run frontend tests
run: npm run test:run

- name: Build frontend
run: npm run build
3 changes: 1 addition & 2 deletions api/model/diagram/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from ninja import Router, Schema

from metadata.specification import Classifier, Relation
from ninja import Router, Schema

from .views import diagrams

Expand Down
28 changes: 13 additions & 15 deletions api/model/diagram/api/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
from diagram.api.schemas.diagram import (
ImportDiagram,
CreateDiagram,
ExportDiagram,
FullDiagram,
ImportDiagram,
ReadDiagram,
UpdateDiagram,
FullDiagram,
ExportDiagram,
)

from diagram.api.schemas.edge import (
CreateEdge,
EdgeSchema,
ListEdges,
PatchEdge,
UpdateEdge,
)
from diagram.api.schemas.node import (
ClassifierUsageResponse,
CreateNode,
PatchNode,
DiagramUsageItem,
ListNodes,
NodeSchema,
DiagramUsageItem,
ClassifierUsageResponse,
PatchNode,
RelationUsageResponse,
)

from diagram.api.schemas.edge import (
CreateEdge,
ListEdges,
EdgeSchema,
UpdateEdge,
PatchEdge,
)

__all__ = [
"ImportDiagram",
"ReadDiagram",
Expand Down
12 changes: 4 additions & 8 deletions api/model/diagram/api/schemas/diagram.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from uuid import UUID
from enum import Enum
from typing import List, Optional
from uuid import UUID

from ninja import ModelSchema, Schema

from diagram.models import Diagram, Node
from .node import CreateNode, NodeSchema, ExportNode, ImportNode
from .edge import CreateEdge, EdgeSchema, ExportEdge, ImportEdge

from .edge import EdgeSchema, ExportEdge, ImportEdge
from .node import ExportNode, ImportNode, NodeSchema


class DiagramType(str, Enum):
Expand Down Expand Up @@ -122,11 +123,6 @@ def resolve_related_diagrams(obj):
return Diagram.objects.filter(system=obj.system.id).exclude(id=obj.id)


class ImportDiagram(CreateDiagram):
nodes: List[CreateNode]
edges: List[CreateEdge]


class ExportDiagram(ModelSchema):
nodes: List[ExportNode] = []
edges: List[ExportEdge] = []
Expand Down
5 changes: 3 additions & 2 deletions api/model/diagram/api/schemas/edge.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from typing import Any, List, Optional
from uuid import UUID

from ninja import ModelSchema, Schema
from diagram.models import Edge, Relation as RelationModel
from metadata.specification import Relation
from ninja import ModelSchema, Schema

from diagram.models import Edge


class Point(Schema):
Expand Down
3 changes: 2 additions & 1 deletion api/model/diagram/api/schemas/node.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from typing import List, Optional
from uuid import UUID

from metadata.specification import Classifier
from ninja import ModelSchema, Schema

from diagram.models import Node
from metadata.specification import Classifier


class NodePosition(Schema):
Expand Down
6 changes: 4 additions & 2 deletions api/model/diagram/api/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from django.http import HttpRequest

from diagram.models import Diagram
from .node import create_node, import_node, remove_node, delete_classifier_everywhere
from .edge import create_edge, remove_edge_from_diagram, delete_relation_everywhere

from .edge import create_edge, delete_relation_everywhere, remove_edge_from_diagram
from .node import create_node, delete_classifier_everywhere, import_node, remove_node


def get_diagram(request: HttpRequest) -> Diagram | None:
Expand Down
6 changes: 3 additions & 3 deletions api/model/diagram/api/utils/edge.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import metadata.specification as spec
from django.db.models import Count, Q
from metadata.models import Relation

from diagram.models import Diagram, Edge, Node
from metadata.models import Relation
import metadata.specification as spec


def create_edge(diagram: Diagram, data: spec.Relation, source: Node, target: Node):
Expand All @@ -15,7 +15,7 @@ def create_edge(diagram: Diagram, data: spec.Relation, source: Node, target: Nod
)

# Create the edge in the current diagram
edge = Edge.objects.create(
Edge.objects.create(
diagram=diagram,
rel=relation,
data={},
Expand Down
7 changes: 4 additions & 3 deletions api/model/diagram/api/utils/node.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import metadata.specification as spec
from django.db import transaction
from diagram.models import Diagram, Node, Edge
from metadata.models import Classifier, Relation
import metadata.specification as spec
from diagram.api.utils.edge import remove_edge_from_diagram, delete_relation_everywhere

from diagram.api.utils.edge import delete_relation_everywhere, remove_edge_from_diagram
from diagram.models import Diagram, Node


def create_node(diagram: Diagram, data: spec.Classifier):
Expand Down
15 changes: 7 additions & 8 deletions api/model/diagram/api/views/diagram.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
from typing import List
from uuid import uuid4

from django.db import transaction
from metadata.models import System
from ninja import Router

from diagram.api.schemas import (
ImportDiagram,
CreateDiagram,
FullDiagram,
ImportDiagram,
ReadDiagram,
UpdateDiagram,
)
from diagram.api.utils import create_edge, create_node
from diagram.models import Diagram
from diagram.api.utils import create_node, create_edge
from metadata.models import System
from django.db import transaction
from ninja import Router
import networkx as nx

from .node import node
from .edge import edge
from .node import node
from .system import system

diagrams = Router()
Expand Down
24 changes: 15 additions & 9 deletions api/model/diagram/api/views/edge.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
from typing import List
from uuid import UUID

from django.http import HttpRequest
from django.shortcuts import get_object_or_404

from metadata.specification import Relation
from ninja import Router
from pydantic import BaseModel

import diagram.api.utils as utils

from diagram.api.schemas import CreateEdge, EdgeSchema, UpdateEdge, DiagramUsageItem, RelationUsageResponse, PatchEdge
from diagram.models import Node, Edge, Edge
from diagram.api.utils.edge import fetch_and_update_edges, remove_edge_from_diagram, delete_relation_everywhere
from metadata.specification import Relation

from diagram.api.schemas import (
CreateEdge,
DiagramUsageItem,
EdgeSchema,
RelationUsageResponse,
UpdateEdge,
)
from diagram.api.utils.edge import (
delete_relation_everywhere,
fetch_and_update_edges,
remove_edge_from_diagram,
)
from diagram.models import Edge, Node

edge = Router()

Expand All @@ -38,8 +46,6 @@ def relation_usage(request, edge_id: str):
return 404, "Edge not found"

rel = edge.rel
rel_label = (rel.data or {}).get("label") or (rel.data or {}).get("type") or str(rel.id)

edges = Edge.objects.select_related("diagram", "diagram__system").filter(rel=rel)

seen = set()
Expand Down
8 changes: 4 additions & 4 deletions api/model/diagram/api/views/llm_generation/generation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from diagram.models import System, Diagram
from diagram.api.schemas import FullDiagram
from typing import Dict, Any
from openai import OpenAI
import os
from typing import Any, Dict

from openai import OpenAI


def execute_prompt(prompt_path: str, prompt_data: Dict[str, Any] ) -> str:
try:
Expand Down
29 changes: 16 additions & 13 deletions api/model/diagram/api/views/node.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
from typing import List
from django.http import HttpRequest

from django.core import serializers
from django.db.models import Q

from ninja import Router, Schema
from django.http import HttpRequest
from llm.handler import llm_handler, remove_reply_markdown
from metadata.models import Classifier as MetaClassifier
from metadata.models import Relation
from metadata.specification import Classifier
from ninja import Router
from pydantic import BaseModel

import diagram.api.utils as utils

from diagram.api.schemas import CreateNode, PatchNode, NodeSchema, FullDiagram, DiagramUsageItem, ClassifierUsageResponse

from metadata.specification import Classifier
from metadata.models import Classifier as MetaClassifier, Relation

from diagram.models import Node, Edge, Diagram

from llm.handler import llm_handler, remove_reply_markdown
from diagram.api.schemas import (
ClassifierUsageResponse,
CreateNode,
DiagramUsageItem,
FullDiagram,
NodeSchema,
PatchNode,
)
from diagram.models import Diagram, Edge, Node

node = Router()

Expand Down Expand Up @@ -180,7 +184,6 @@ def import_node(request: HttpRequest, classifier_id: str):

# Map of classifier id -> node
nodes = diagram.nodes.select_related("cls").all()
classifier_ids_in_diagram = [n.cls_id for n in nodes]
nodes_by_classifier_id = {str(n.cls_id): n for n in nodes}

relations = Relation.objects.filter(
Expand Down
Loading
Loading