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
47 changes: 15 additions & 32 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ jobs:
matrix:
python-version:
- "3.12"
poetry-version:
- "1.8.5"
timeout-minutes: 5
steps:
- name: "Check out repository code"
Expand All @@ -52,28 +50,23 @@ jobs:
uses: "actions/setup-python@v6"
with:
python-version: ${{ matrix.python-version }}
- name: "Install Poetry ${{ matrix.poetry-version }}"
uses: "snok/install-poetry@v1"

- name: "Install uv"
uses: "astral-sh/setup-uv@v7"
with:
version: ${{ matrix.poetry-version }}
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
- name: "Setup Python environment"
run: |
poetry config virtualenvs.create true --local
poetry env use ${{ matrix.python-version }}
version: "0.9.18"

- name: "Install dependencies"
run: "poetry install --no-interaction --no-ansi --with dev"
run: "uv sync --group dev"

- name: "Linting: ruff check"
run: "poetry run ruff check ."
run: "uv run ruff check ."
- name: "Linting: ruff format"
run: "poetry run ruff format --check --diff ."
run: "uv run ruff format --check --diff ."
- name: "Mypy Tests"
run: "poetry run mypy --show-error-codes emma pages"
run: "uv run mypy --show-error-codes emma pages"
- name: "Pylint Tests"
run: "poetry run pylint emma pages *.py"
run: "uv run pylint emma pages *.py"

yaml-lint:
if: needs.files-changed.outputs.yaml == 'true'
Expand Down Expand Up @@ -153,8 +146,6 @@ jobs:
matrix:
python-version:
- "3.12"
poetry-version:
- "1.8.5"
timeout-minutes: 5
steps:
- name: "Check out repository code"
Expand All @@ -165,25 +156,17 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: "Install Poetry ${{ matrix.poetry-version }}"
uses: "snok/install-poetry@v1"
- name: "Install uv"
uses: "astral-sh/setup-uv@v7"
with:
version: ${{ matrix.poetry-version }}
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true

- name: "Setup Python environment"
run: |
poetry config virtualenvs.create true --local
poetry env use ${{ matrix.python-version }}
version: "0.9.18"

- name: "Install dependencies"
run: "poetry install --no-interaction --no-ansi"
run: "uv sync"

- name: "Run Streamlit"
run: |
timeout 30s poetry run streamlit run main.py &
timeout 30s uv run streamlit run main.py &
PID=$!
sleep 10
if ps -p $PID > /dev/null; then
Expand Down
1 change: 1 addition & 0 deletions .vale/styles/spelling-exceptions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ userinfo
uuid
UUID
UUIDs
uv
validator
validators
Version Control
Expand Down
10 changes: 5 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ Emma is an experimental AI-powered assistant for Infrahub, a network infrastruct

```bash
# Install dependencies
poetry install
uv sync

# Run the application
poetry run streamlit run main.py
uv run streamlit run main.py

# Format code
poetry run invoke format
uv run invoke format

# Run all linters (yaml, ruff, mypy, pylint)
poetry run invoke lint
uv run invoke lint

# Run tests
pytest
Expand Down Expand Up @@ -88,7 +88,7 @@ Infrastructure schemas are YAML-based and stored in `schema-library/`. They defi
- Streamlit for web UI
- Infrahub SDK for backend operations
- OpenAI/LangChain for AI features
- Poetry for dependency management
- uv for dependency management
- Ruff, MyPy, Pylint for code quality

## Development Guidelines
Expand Down
30 changes: 13 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
# TODO: Make python version an arg
FROM docker.io/python:3.12-slim

# Env variable for the build
# TODO: Review that part (e.g. poetry version ...)
ENV POETRY_NO_INTERACTION=1 \
POETRY_CACHE_DIR=/tmp/poetry_cache \
POETRY_VIRTUALENVS_CREATE=false \
POETRY_HOME='/usr/local' \
POETRY_VERSION=1.8.3
# Install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

# Env variables for the build
ENV UV_COMPILE_BYTECODE=1
ENV UV_LINK_MODE=copy

# Install libraries and packages
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install --no-install-recommends -y curl git pkg-config build-essential ca-certificates && \
curl -sSL https://install.python-poetry.org | python3 - &&\
apt-get autoremove -y && \
apt-get clean all && \
rm -rf /var/lib/apt/lists/* && \
pip --no-cache-dir install --no-compile --upgrade pip wheel
rm -rf /var/lib/apt/lists/*

# Copy lock and install all dependancies
# Copy lock and install all dependencies
WORKDIR /source
COPY poetry.lock pyproject.toml /source/
RUN poetry install --no-ansi --no-root --no-directory --without dev && \
rm -rf $POETRY_CACHE_DIR
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev --no-install-project

# Copy application and install it
COPY . ./
RUN poetry install --no-ansi --no-directory --without dev
RUN uv sync --frozen --no-dev

# Run streamlite app
# Run streamlit app
EXPOSE 8501
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
ENTRYPOINT ["streamlit", "run", "main.py", "--server.port=8501", "--server.address=0.0.0.0"]
ENTRYPOINT ["uv", "run", "streamlit", "run", "main.py", "--server.port=8501", "--server.address=0.0.0.0"]
12 changes: 6 additions & 6 deletions docs/docs/getting-started/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Emma is an experimental AI-powered assistant for Infrahub that helps you manage
Before installing Emma, ensure you have:

- **Infrahub instance**: Emma requires a running Infrahub instance to connect to
- **Docker** (for containerized deployment) or **Python 3.10+** and **Poetry** (for local development)
- **Docker** (for containerized deployment) or **Python 3.10+** and **uv** (for local development)

## Installation methods

Expand All @@ -23,7 +23,7 @@ The easiest way to get started is using the Infrahub quickstart with Emma includ

```bash
# Download and start Infrahub + Emma with Docker Compose
curl https://infrahub.opsmill.io/1.4.12-emma | docker compose -f - up -d
curl https://infrahub.opsmill.io/1.6.2-emma | docker compose -f - up -d
```

This command will:
Expand Down Expand Up @@ -79,16 +79,16 @@ git clone https://github.com/opsmill/emma.git
cd emma
```

2. **Install dependencies with Poetry:**
2. **Install dependencies with uv:**

```bash
poetry install
uv sync
```

3. **Run Emma:**

```bash
poetry run streamlit run main.py
uv run streamlit run main.py
```

Emma will start on http://localhost:8501
Expand All @@ -108,4 +108,4 @@ If you encounter issues during installation:
- **Docker issues**: Check Docker is running and you have sufficient resources allocated
- **Network connectivity**: Verify Emma can reach your Infrahub instance

For more detailed troubleshooting, see the [Troubleshooting Guide](../reference/troubleshooting).
For more detailed troubleshooting, see the [Troubleshooting Guide](../reference/troubleshooting).
2 changes: 1 addition & 1 deletion docs/docs/readme.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Ready to get started? Choose your preferred installation method:
Use the one-command quickstart to get Emma and Infrahub running together:

```bash
curl https://infrahub.opsmill.io/1.4.12-emma | docker compose -f - up -d
curl https://infrahub.opsmill.io/1.6.2-emma | docker compose -f - up -d
```

Then open [Emma](http://localhost:8501) and [Infrahub](http://localhost:8000) in your browser.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/reference/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ WARNING: Unknown feature flag 'invalid_flag' ignored

```bash
# Test configuration without starting full application
poetry run python -c "from emma.utils import validate_config; validate_config()"
uv run python -c "from emma.utils import validate_config; validate_config()"
```

## Migration and upgrades
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/reference/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ This guide covers common issues you might encounter while using Emma and how to

```bash
# Ensure you're using the correct command
poetry run streamlit run main.py
uv run streamlit run main.py

# Or for direct Python execution
python -m streamlit run main.py
Expand Down Expand Up @@ -343,7 +343,7 @@ export STREAMLIT_LOGGER_LEVEL=debug

# Set Python logging level
export PYTHONPATH=.
poetry run python -c "import logging; logging.basicConfig(level=logging.DEBUG)"
uv run python -c "import logging; logging.basicConfig(level=logging.DEBUG)"
```

**For Docker:**
Expand All @@ -361,7 +361,7 @@ environment:

```bash
# Run with verbose output
poetry run streamlit run main.py --logger.level=debug
uv run streamlit run main.py --logger.level=debug

# Check Emma logs
tail -f ~/.streamlit/logs/
Expand Down
8 changes: 3 additions & 5 deletions emma/gql_queries.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Optional

from graphql import GraphQLList, GraphQLNonNull, GraphQLObjectType, build_client_schema, get_introspection_query
from langchain.tools import tool

Expand All @@ -24,7 +22,7 @@
)


def get_gql_schema(branch: Optional[str] = None) -> Optional[GraphQLObjectType]:
def get_gql_schema(branch: str | None = None) -> GraphQLObjectType | None:
schema_query = get_introspection_query()
introspection_result = run_gql_query(query=schema_query, branch=branch)

Expand All @@ -35,7 +33,7 @@ def get_gql_schema(branch: Optional[str] = None) -> Optional[GraphQLObjectType]:
return None


def generate_query(object_type: GraphQLObjectType, visited_types: Optional[set] = None) -> str:
def generate_query(object_type: GraphQLObjectType, visited_types: set | None = None) -> str:
if visited_types is None:
visited_types = set()

Expand Down Expand Up @@ -71,7 +69,7 @@ def generate_query(object_type: GraphQLObjectType, visited_types: Optional[set]


@tool
def generate_full_query(branch: Optional[str], root_object_name: str) -> Optional[str]:
def generate_full_query(branch: str | None, root_object_name: str) -> str | None:
"""
Generates a comprehensive GraphQL query for a specified root object, including all its fields
and nested sub-objects, based on the schema retrieved from the specified branch.
Expand Down
2 changes: 1 addition & 1 deletion pages/data_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def create_column_label_mapping(
f"{col} (Mandatory)" if col in mandatory_columns and col not in to_omit else f"{col} (Optional)"
for col in mandatory_columns + optional_columns
]
label_to_col = {label: col for label, col in zip(column_labels, mandatory_columns + optional_columns)}
label_to_col = {label: col for label, col in zip(column_labels, mandatory_columns + optional_columns, strict=True)}
return ColumnMapping(labels=column_labels, label_to_col=label_to_col)


Expand Down
Loading