Skip to content

Commit 5f25ae8

Browse files
Add CI to run checks and tests; reformat everything so those tests pass (#10)
1 parent 0d0764d commit 5f25ae8

20 files changed

+305
-206
lines changed

.github/workflows/ci.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# .github/workflows/ci.yml
2+
name: CI
3+
on: [push, pull_request]
4+
5+
jobs:
6+
run-make:
7+
name: ${{ matrix.name }}
8+
runs-on: ubuntu-latest
9+
strategy:
10+
fail-fast: false
11+
matrix:
12+
include:
13+
- { name: "make check", cmd: "make check" }
14+
- { name: "make test", cmd: "make test" }
15+
- { name: "make format --check", cmd: "make format FLAGS=--check" }
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: '3.12'
23+
24+
- name: Cache uv
25+
uses: actions/cache@v4
26+
with:
27+
path: |
28+
~/.cache/uv
29+
.venv
30+
key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }}
31+
restore-keys: ${{ runner.os }}-uv-
32+
33+
- name: Install uv
34+
run: |
35+
set -euxo pipefail
36+
curl -LsSf https://astral.sh/uv/install.sh | sh
37+
echo "$HOME/.local/bin" >> $GITHUB_PATH
38+
39+
- run: ${{ matrix.cmd }}

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ __pycache__
88
/evals
99
/gmail/client_secret.json
1010
/gmail/token.json
11-
/gmail/mail_dump/
11+
/gmail/*_dump/
1212
/testdata/Episode_53_Answer_results.json
1313
/testdata/Episode_53_Search_results.json
1414
/testdata/MP/

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ all: venv format check test build
88

99
.PHONY: format
1010
format: venv
11-
.venv/bin/black typeagent test tools
11+
.venv/bin/black typeagent test tools $(FLAGS)
1212

1313
.PHONY: check
1414
check: venv

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Homepage = "https://github.com/microsoft/TypeAgent/tree/main"
4747
packages = [
4848
"typeagent",
4949
"typeagent.aitools",
50+
"typeagent.emails",
5051
"typeagent.knowpro",
5152
"typeagent.mcp",
5253
"typeagent.podcasts",
@@ -58,6 +59,7 @@ packages = [
5859

5960
[tool.setuptools.package-data]
6061
"typeagent.podcasts" = ["*.json"]
62+
"typeagent.emails" = ["*.json"]
6163

6264
[tool.pytest.ini_options]
6365
asyncio_default_fixture_loop_scope = "function"

test/fixtures.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ def needs_auth() -> None:
4545
utils.load_dotenv()
4646

4747

48+
@pytest.fixture(scope="session")
49+
def really_needs_auth() -> None:
50+
utils.load_dotenv()
51+
# Check if any of the supported API keys is set
52+
if not (os.getenv("OPENAI_API_KEY") or os.getenv("AZURE_OPENAI_API_KEY")):
53+
pytest.skip("No API key found")
54+
55+
4856
@pytest.fixture(scope="session")
4957
def embedding_model() -> AsyncEmbeddingModel:
5058
"""Fixture to create a test embedding model with small embedding size for faster tests."""

test/test_demo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from typeagent.knowpro.interfaces import ScoredSemanticRefOrdinal
1313
from typeagent.podcasts import podcast
1414

15-
from fixtures import needs_auth
15+
from fixtures import really_needs_auth
1616

1717
tests_dir = os.path.dirname(__file__)
1818
root_dir = os.path.dirname(tests_dir)
@@ -27,7 +27,7 @@
2727
)
2828

2929

30-
def test_main(needs_auth: None):
30+
def test_main(really_needs_auth: None):
3131
# auth is needed because we use embeddings.
3232
# TODO: Only use the embeddings loaded from the file and cached.
3333
asyncio.run(main(DEFAULT_FILE))

test/test_knowledge.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
)
1515
from typeagent.knowpro import convknowledge, kplib
1616

17-
from fixtures import needs_auth # type: ignore # Used!
17+
from fixtures import really_needs_auth
1818

1919

2020
class MockKnowledgeExtractor:
@@ -34,7 +34,7 @@ def mock_knowledge_extractor() -> convknowledge.KnowledgeExtractor:
3434
return MockKnowledgeExtractor() # type: ignore
3535

3636

37-
def test_create_knowledge_extractor(needs_auth: None):
37+
def test_create_knowledge_extractor(really_needs_auth: None):
3838
"""Test creating a knowledge extractor."""
3939
extractor = create_knowledge_extractor()
4040
assert isinstance(extractor, convknowledge.KnowledgeExtractor)

test/test_property_index_population.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from typeagent.podcasts.podcast import PodcastMessage
2222
from typeagent.storage import SqliteStorageProvider
2323

24+
from fixtures import really_needs_auth
25+
2426

2527
class MockEmbeddingModel(AsyncEmbeddingModel):
2628
def __init__(self):
@@ -33,7 +35,7 @@ async def get_embeddings(self, keys: list[str]) -> np.ndarray:
3335

3436

3537
@pytest.mark.asyncio
36-
async def test_property_index_population_from_database():
38+
async def test_property_index_population_from_database(really_needs_auth):
3739
"""Test that property index is correctly populated when reopening a database."""
3840
load_dotenv()
3941
temp_db_path = tempfile.mktemp(suffix=".sqlite")

test/test_query_method.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,11 @@
1111
from typeagent.knowpro.convsettings import ConversationSettings
1212
from typeagent.transcripts.transcript import TranscriptMessage, TranscriptMessageMeta
1313

14-
15-
@pytest.fixture(scope="session")
16-
def needs_auth() -> None:
17-
"""Load environment variables for authentication."""
18-
load_dotenv()
14+
from fixtures import really_needs_auth
1915

2016

2117
@pytest.mark.asyncio
22-
async def test_query_method_basic(needs_auth: None):
18+
async def test_query_method_basic(really_needs_auth: None):
2319
"""Test the basic query method workflow."""
2420
# Create a conversation with some test data
2521
test_model = AsyncEmbeddingModel(model_name=TEST_MODEL_NAME)
@@ -65,7 +61,7 @@ async def test_query_method_basic(needs_auth: None):
6561

6662

6763
@pytest.mark.asyncio
68-
async def test_query_method_empty_conversation(needs_auth: None):
64+
async def test_query_method_empty_conversation(really_needs_auth: None):
6965
"""Test query method on an empty conversation."""
7066
test_model = AsyncEmbeddingModel(model_name=TEST_MODEL_NAME)
7167
settings = ConversationSettings(model=test_model)

test/test_related_terms_index_population.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
"""Test to verify related terms index population in storage providers."""
66

7-
import asyncio
87
import tempfile
98
import os
109
import pytest
@@ -18,13 +17,14 @@
1817
MessageTextIndexSettings,
1918
RelatedTermIndexSettings,
2019
)
21-
from typeagent.storage.memory.reltermsindex import RelatedTermsIndex
2220
from typeagent.podcasts.podcast import PodcastMessage, PodcastMessageMeta
2321
from typeagent.storage import SqliteStorageProvider
2422

23+
from fixtures import really_needs_auth
24+
2525

2626
@pytest.mark.asyncio
27-
async def test_related_terms_index_population_from_database():
27+
async def test_related_terms_index_population_from_database(really_needs_auth):
2828
"""Test that related terms index is correctly populated when reopening a database."""
2929
load_dotenv()
3030
temp_db_path = tempfile.mktemp(suffix=".sqlite")

0 commit comments

Comments
 (0)