Skip to content
Merged
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
261 changes: 130 additions & 131 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,143 +15,142 @@ jobs:
runs-on: ubuntu-latest

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

- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Install dependencies
run: python -m pip install -U "jupyterlab>=4.0.0,<5"

- name: Lint the extension
run: |
set -eux
jlpm
jlpm run lint:check

- name: Test the extension
run: |
set -eux
jlpm run test

- name: Build the extension
run: |
set -eux
python -m pip install .[test]

pytest -vv -r ap --cov jupyter_ai_jupyternaut
jupyter server extension list
jupyter server extension list 2>&1 | grep -ie "jupyter_ai_jupyternaut.*OK"

jupyter labextension list
jupyter labextension list 2>&1 | grep -ie "@jupyter-ai/jupyternaut.*OK"
python -m jupyterlab.browser_check

- name: Package the extension
run: |
set -eux

pip install build
python -m build
pip uninstall -y "jupyter_ai_jupyternaut" jupyterlab

- name: Upload extension packages
uses: actions/upload-artifact@v4
with:
name: extension-artifacts
path: dist/jupyter_ai_jupyternaut*
if-no-files-found: error
- name: Checkout
uses: actions/checkout@v4

- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Install dependencies
run: python -m pip install -U "jupyterlab>=4.0.0,<5"

- name: Lint the extension
run: |
set -eux
jlpm
jlpm run lint:check

- name: Test the extension
run: |
set -eux
jlpm run test

- name: Build the extension
run: |
set -eux
python -m pip install .[test]

pytest -vv -r ap --cov jupyter_ai_jupyternaut
jupyter server extension list
jupyter server extension list 2>&1 | grep -ie "jupyter_ai_jupyternaut.*OK"

jupyter labextension list
jupyter labextension list 2>&1 | grep -ie "@jupyter-ai/jupyternaut.*OK"
# python -m jupyterlab.browser_check
- name: Package the extension
run: |
set -eux

pip install build
python -m build
pip uninstall -y "jupyter_ai_jupyternaut" jupyterlab

- name: Upload extension packages
uses: actions/upload-artifact@v4
with:
name: extension-artifacts
path: dist/jupyter_ai_jupyternaut*
if-no-files-found: error

test_isolated:
needs: build
runs-on: ubuntu-latest

steps:
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x64'
- uses: actions/download-artifact@v4
with:
name: extension-artifacts
- name: Install and Test
run: |
set -eux
# Remove NodeJS, twice to take care of system and locally installed node versions.
sudo rm -rf $(which node)
sudo rm -rf $(which node)

pip install "jupyterlab>=4.0.0,<5" jupyter_ai_jupyternaut*.whl


jupyter server extension list
jupyter server extension list 2>&1 | grep -ie "jupyter_ai_jupyternaut.*OK"

jupyter labextension list
jupyter labextension list 2>&1 | grep -ie "@jupyter-ai/jupyternaut.*OK"
python -m jupyterlab.browser_check --no-browser-test

integration-tests:
name: Integration tests
needs: build
runs-on: ubuntu-latest

env:
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/pw-browsers

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

- name: Base Setup
uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

- name: Download extension package
uses: actions/download-artifact@v4
with:
name: extension-artifacts

- name: Install the extension
run: |
set -eux
python -m pip install "jupyterlab>=4.0.0,<5" jupyter_ai_jupyternaut*.whl

- name: Install dependencies
working-directory: ui-tests
env:
YARN_ENABLE_IMMUTABLE_INSTALLS: 0
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
run: jlpm install

- name: Set up browser cache
uses: actions/cache@v4
with:
path: |
${{ github.workspace }}/pw-browsers
key: ${{ runner.os }}-${{ hashFiles('ui-tests/yarn.lock') }}

- name: Install browser
run: |
set -eux
jlpm playwright install-deps
jlpm playwright install chromium
working-directory: ui-tests

- name: Execute integration tests
working-directory: ui-tests
run: |
jlpm playwright test

- name: Upload Playwright Test report
if: always()
uses: actions/upload-artifact@v4
with:
name: jupyter_ai_jupyternaut-playwright-tests
path: |
ui-tests/test-results
ui-tests/playwright-report
- name: Install Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
architecture: 'x64'
- uses: actions/download-artifact@v4
with:
name: extension-artifacts
- name: Install and Test
run: |
set -eux
# Remove NodeJS, twice to take care of system and locally installed node versions.
sudo rm -rf $(which node)
sudo rm -rf $(which node)

pip install "jupyterlab>=4.0.0,<5" jupyter_ai_jupyternaut*.whl


jupyter server extension list
jupyter server extension list 2>&1 | grep -ie "jupyter_ai_jupyternaut.*OK"

jupyter labextension list
jupyter labextension list 2>&1 | grep -ie "@jupyter-ai/jupyternaut.*OK"
python -m jupyterlab.browser_check --no-browser-test

# integration-tests:
# name: Integration tests
# needs: build
# runs-on: ubuntu-latest

# env:
# PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/pw-browsers

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

# - name: Base Setup
# uses: jupyterlab/maintainer-tools/.github/actions/base-setup@v1

# - name: Download extension package
# uses: actions/download-artifact@v4
# with:
# name: extension-artifacts

# - name: Install the extension
# run: |
# set -eux
# python -m pip install "jupyterlab>=4.0.0,<5" jupyter_ai_jupyternaut*.whl

# - name: Install dependencies
# working-directory: ui-tests
# env:
# YARN_ENABLE_IMMUTABLE_INSTALLS: 0
# PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
# run: jlpm install

# - name: Set up browser cache
# uses: actions/cache@v4
# with:
# path: |
# ${{ github.workspace }}/pw-browsers
# key: ${{ runner.os }}-${{ hashFiles('ui-tests/yarn.lock') }}

# - name: Install browser
# run: |
# set -eux
# jlpm playwright install-deps
# jlpm playwright install chromium
# working-directory: ui-tests

# - name: Execute integration tests
# working-directory: ui-tests
# run: |
# jlpm playwright test

# - name: Upload Playwright Test report
# if: always()
# uses: actions/upload-artifact@v4
# with:
# name: jupyter_ai_jupyternaut-playwright-tests
# path: |
# ui-tests/test-results
# ui-tests/playwright-report

check_links:
name: Check Links
Expand Down
58 changes: 56 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,62 @@
from __future__ import annotations
import asyncio
from pathlib import Path
import pytest
from traitlets.config import Config, LoggingConfigurable
import logging
from jupyter_server.services.contents.filemanager import AsyncFileContentsManager
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from jupyter_server.serverapp import ServerApp


pytest_plugins = ("pytest_jupyter.jupyter_server", )


@pytest.fixture
def jp_server_config(jp_server_config):
return {"ServerApp": {"jpserver_extensions": {"jupyter_ai_jupyternaut": True}}}
def jp_server_config(jp_server_config, tmp_path):
return Config({"ServerApp": {"jpserver_extensions": {"jupyter_ai_jupyternaut": True}}, "ContentsManager": {"root_dir": str(tmp_path)}})


class MockJupyternautExtension(LoggingConfigurable):
"""Mock AiExtension class for testing purposes."""

serverapp: ServerApp

def __init__(self, *args, serverapp: ServerApp, **kwargs):
super().__init__(*args, **kwargs)
self.serverapp = serverapp
self._log = None

@property
def log(self) -> logging.Logger:
return self.serverapp.log

@property
def event_loop(self) -> asyncio.AbstractEventLoop:
return self.serverapp.io_loop.asyncio_loop

@property
def contents_manager(self) -> AsyncFileContentsManager:
return self.serverapp.contents_manager


@pytest.fixture
def mock_extension(jp_server_config, jp_configurable_serverapp) -> MockJupyternautExtension:
"""
Returns a mocked `JupyternautExtension` object that can be passed as the
`parent` argument to objects normally initialized by `JupyternautExtension`.
This should be passed to the "manager singletons" like `ConfigManager` and
`EnvSecretsManager`.

See `MockJupyternautExtension` in `conftest.py` for a complete description of the
attributes, properties, and methods available. If something is missing,
please feel free to add to it in your PR.

Returns:
A `MockAiExtension` instance that can be passed as the `parent` argument
to objects normally initialized by `AiExtension`.
"""
serverapp = jp_configurable_serverapp()
return MockJupyternautExtension(config=jp_server_config, serverapp=serverapp)
18 changes: 3 additions & 15 deletions jupyter_ai_jupyternaut/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import warnings
warnings.warn("Importing 'jupyter_ai_jupyternaut' outside a proper installation.")
__version__ = "dev"
from .handlers import setup_handlers
from .extension_app import JupyternautExtension


def _jupyter_labextension_paths():
Expand All @@ -19,18 +19,6 @@ def _jupyter_labextension_paths():

def _jupyter_server_extension_points():
return [{
"module": "jupyter_ai_jupyternaut"
"module": "jupyter_ai_jupyternaut",
"app": JupyternautExtension
}]


def _load_jupyter_server_extension(server_app):
"""Registers the API handler to receive HTTP requests from the frontend extension.

Parameters
----------
server_app: jupyterlab.labapp.LabApp
JupyterLab application instance
"""
setup_handlers(server_app.web_app)
name = "jupyter_ai_jupyternaut"
server_app.log.info(f"Registered {name} server extension")
3 changes: 3 additions & 0 deletions jupyter_ai_jupyternaut/config/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .config_models import *
from .config_manager import ConfigManager
from .config_rest_api import ConfigRestAPI
Loading