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
23 changes: 23 additions & 0 deletions .github/workflows/ci-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,26 @@ jobs:

- name: Build gate (phase-1 compile check)
run: python -m compileall -q dare_framework tests

smoke-tests:
name: smoke-tests
runs-on: ubuntu-latest
needs: [lint, build]
# Phase-1 rollout: publish smoke signal without blocking merges yet.
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v4

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

- name: Install smoke-test dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest pytest-asyncio langchain-openai langchain-core httpx starlette uvicorn

- name: Run smoke tests
run: pytest -q tests/smoke -m smoke
6 changes: 6 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ This repository uses PR-based delivery with CI gates to keep `main` stable under

These checks are designed to be fast and low-friction first. We will tighten them in later phases.

## Smoke Tests (phase-2 rollout)
- CI job: `smoke-tests`
- Current mode: non-blocking (`continue-on-error`), used as signal collection before becoming required.
- Scope: `tests/smoke/` only, deterministic checks with no external model calls.

## Run Checks Locally
```bash
python -m pip install -r requirements.txt
ruff check dare_framework tests --select E9,F63,F7
python -m compileall -q dare_framework tests
pytest -q tests/smoke -m smoke
```

## Team Agent Rules
Expand Down
5 changes: 5 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pytest]
addopts = -ra
testpaths = tests
markers =
smoke: fast deterministic regression checks for CI gate rollout
71 changes: 71 additions & 0 deletions tests/smoke/test_ci_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import annotations

from typing import Any

import pytest

from dare_framework.agent import BaseAgent
from dare_framework.infra.component import ComponentType
from dare_framework.model.kernel import IModelAdapter
from dare_framework.model.types import ModelInput, ModelResponse, Prompt


class DummyModelAdapter(IModelAdapter):
"""Dummy model prevents any external model call during smoke checks."""

@property
def name(self) -> str:
return "smoke-dummy"

@property
def model(self) -> str:
return "smoke-dummy-model"

@property
def component_type(self) -> ComponentType:
return ComponentType.MODEL_ADAPTER

async def generate(self, model_input: ModelInput, *, options: Any | None = None) -> ModelResponse:
return ModelResponse(content="smoke-ok")


def _base_prompt() -> Prompt:
return Prompt(
prompt_id="smoke.system",
role="system",
content="smoke prompt",
supported_models=["*"],
order=0,
)


async def _build_agent(name: str):
return await (
BaseAgent.simple_chat_agent_builder(name)
.with_model(DummyModelAdapter())
.with_prompt(_base_prompt())
.build()
)


@pytest.mark.asyncio
@pytest.mark.smoke
async def test_smoke_builder_can_build_simple_chat_agent() -> None:
agent = await _build_agent("smoke-builder")
assert agent.name == "smoke-builder"


@pytest.mark.asyncio
@pytest.mark.smoke
async def test_smoke_context_assemble_contains_prompt() -> None:
agent = await _build_agent("smoke-context")
assembled = agent.context.assemble()
assert assembled.sys_prompt is not None
assert "smoke prompt" in assembled.sys_prompt.content


@pytest.mark.smoke
def test_smoke_prompt_construction() -> None:
prompt = _base_prompt()
assert prompt.role == "system"
assert prompt.content.startswith("smoke")