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
1 change: 1 addition & 0 deletions .github/workflows/plugin-api-v3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
- name: Verify Fitbit v3 composition
env:
AKASHIC_AGENT_ROOT: .akashic-core
AKASHIC_PLUGIN_FIXTURE_PYTHON: ${{ github.workspace }}/.venv/bin/python
PYTHONPATH: .akashic-core
run: .venv/bin/python -m pytest -q tests/
- uses: actions/setup-node@v4
Expand Down
6 changes: 3 additions & 3 deletions plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
MobileUiNavigation,
ServiceKey,
)
from src.content_adapter import (
from .src.content_adapter import (
BoundContentSource,
FitbitContentRuntime,
FitbitMonitorClient,
)
from src.mobile_reader import mobile_ui_query
from src.sleep_context import FitbitAdapterStore, SleepContextAppender
from .src.mobile_reader import mobile_ui_query
from .src.sleep_context import FitbitAdapterStore, SleepContextAppender


class ContentSourceServices(Protocol):
Expand Down
2 changes: 1 addition & 1 deletion src/content_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from agent.control.timer import TimerHandle, TimerStatus
from agent.plugin_composition import Context, HealthHandle, PluginTimers
from src.sleep_context import FitbitAdapterStore
from .sleep_context import FitbitAdapterStore


class BoundContentSource(Protocol):
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import os
import sys
from pathlib import Path
from types import ModuleType


repo_root = Path(__file__).resolve().parents[1]
Expand All @@ -13,3 +14,8 @@
for path in (repo_root, agent_root):
if str(path) not in sys.path:
sys.path.insert(0, str(path))

package = ModuleType("fitbit_test_plugin")
package.__path__ = [str(repo_root)]
package.__package__ = "fitbit_test_plugin"
sys.modules["fitbit_test_plugin"] = package
48 changes: 42 additions & 6 deletions tests/test_manager_integration.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import hashlib
import os
import shutil
import sys
from pathlib import Path

import pytest
Expand All @@ -26,8 +26,9 @@ def _tree_digest(root: Path) -> str:


def _stage_plugin(tmp_path: Path) -> Path:
"""复制可执行 artifact,并复用当前测试解释器的依赖环境。"""
"""复制可执行 artifact,并挂载调用方明确选择的依赖环境。"""

fixture_python = Path(os.environ["AKASHIC_PLUGIN_FIXTURE_PYTHON"])
source = tmp_path / "plugins" / "fitbit"
shutil.copytree(
ROOT,
Expand All @@ -41,16 +42,51 @@ def _stage_plugin(tmp_path: Path) -> Path:
"node_modules",
),
)
(source / ".venv").symlink_to(
Path(sys.executable).parent.parent,
target_is_directory=True,
)
(source / ".venv").symlink_to(fixture_python.parent.parent, target_is_directory=True)
content_source = Path(content_plugin.__file__).resolve().parent
content_target = source.parent / "content"
shutil.copytree(content_source, content_target)
return source


def test_stage_plugin_uses_explicit_fixture_python(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
artifact_python = tmp_path / "artifact" / ".venv" / "bin" / "python"
monkeypatch.setenv("AKASHIC_PLUGIN_FIXTURE_PYTHON", str(artifact_python))

plugin_root = _stage_plugin(tmp_path / "stage")

assert (plugin_root / ".venv").readlink() == artifact_python.parent.parent


def test_stage_plugin_requires_explicit_fixture_python(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.delenv("AKASHIC_PLUGIN_FIXTURE_PYTHON", raising=False)

with pytest.raises(KeyError, match="AKASHIC_PLUGIN_FIXTURE_PYTHON"):
_stage_plugin(tmp_path)

assert not (tmp_path / "plugins").exists()


def test_ci_creates_and_exports_absolute_fixture_python_before_pytest() -> None:
workflow = (ROOT / ".github/workflows/plugin-api-v3.yml").read_text(
encoding="utf-8"
)

create_runtime = workflow.index("python -m venv .venv")
export_runtime = workflow.index(
"AKASHIC_PLUGIN_FIXTURE_PYTHON: ${{ github.workspace }}/.venv/bin/python"
)
run_pytest = workflow.index("run: .venv/bin/python -m pytest -q tests/")

assert create_runtime < export_runtime < run_pytest


@pytest.mark.asyncio
async def test_manager_rebuilds_fitbit_runtime_on_exact_formal_root(
tmp_path: Path,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
from agent.plugins.static_manifest import load_static_plugin_manifest
from plugins.content import plugin as content_plugin

import plugin as plugin_module
from plugin import FitbitConfig
from fitbit_test_plugin import plugin as plugin_module # pyright: ignore[reportMissingImports]
from fitbit_test_plugin.plugin import FitbitConfig # pyright: ignore[reportMissingImports]
from src import mobile_reader
from src.mobile_reader import mobile_ui_query

Expand Down
Loading