SDK 1.1.0-rc2 #48
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # PR / push checks for the generated SDK: it installs, imports with the expected | |
| # config, and builds. Runs on the factory's proposal PRs so a broken generation | |
| # is caught before merge (and therefore before release). Skips cleanly on a bare | |
| # major branch that has no SDK yet (before the first proposal lands). | |
| name: ci | |
| on: | |
| pull_request: # covers proposal PRs (sdk/* → vN) | |
| push: | |
| branches: ["v*"] # post-merge validation on each major line (v2, v3, …) | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Detect package | |
| id: detect | |
| run: | | |
| if [ -f pyproject.toml ]; then | |
| echo "has_pkg=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "has_pkg=false" >> "$GITHUB_OUTPUT" | |
| echo "No SDK on this branch yet — skipping build (bootstrap branch)." | |
| fi | |
| - uses: actions/setup-python@v6 | |
| if: steps.detect.outputs.has_pkg == 'true' | |
| with: | |
| python-version: "3.14" | |
| - name: Install | |
| if: steps.detect.outputs.has_pkg == 'true' | |
| run: pip install . | |
| - name: Import + config smoke | |
| if: steps.detect.outputs.has_pkg == 'true' | |
| run: | | |
| python - <<'PY' | |
| from everos_cloud import ( | |
| ApiClient, Configuration, EverOS, KnowledgeApi, MemoryApi, StorageApi, TasksApi, | |
| ) | |
| cfg = Configuration(access_token="sk-test") | |
| assert cfg.host == "https://api.evermind.ai", cfg.host | |
| assert cfg.auth_settings()["BearerAuth"]["value"] == "Bearer sk-test" | |
| MemoryApi(ApiClient(cfg)) | |
| # generated method names — these are the operationIds, NOT the facade's | |
| for m in ("add_memory", "search_memory", "get_memory", "delete_memory", "edit_profile", | |
| "bind_tags", "unbind_tags", "replace_tags"): | |
| assert hasattr(MemoryApi, m), m | |
| for m in ("create_knowledge_base", "search_knowledge", "create_document", | |
| "replace_document", "list_documents"): | |
| assert hasattr(KnowledgeApi, m), m | |
| for m in ("list_tasks", "get_task_status", "get_task_stats"): | |
| assert hasattr(TasksApi, m), m | |
| # ergonomic facade is exported at the top level | |
| for m in ("add", "search", "get", "flush", "edit", "delete", "upload", "close", | |
| "tag_bind", "tag_unbind", "tag_replace", | |
| "kb_create", "kb_list", "kb_get", "kb_update", "kb_delete", "kb_search", | |
| "doc_ingest", "doc_list", "doc_get", | |
| "doc_update", "doc_delete", | |
| "task_get", "task_list", "task_wait"): | |
| assert hasattr(EverOS, m), m | |
| # the facade's names must stay disjoint from the generated ones, so a reader | |
| # never has to work out which layer a call went through | |
| generated = set() | |
| for cls in (KnowledgeApi, MemoryApi, StorageApi, TasksApi): | |
| generated |= {m for m in dir(cls) if not m.startswith("_") | |
| and not m.endswith(("_with_http_info", "_without_preload_content"))} | |
| facade = {m for m in dir(EverOS) if not m.startswith("_")} | |
| assert not (facade & generated), sorted(facade & generated) | |
| # every generated client is reachable through the facade (regression: the | |
| # knowledge / tasks handles were missing, so those surfaces were unusable) | |
| client = EverOS("sk-test") | |
| for attr, cls in (("memory", MemoryApi), ("storage", StorageApi), | |
| ("knowledge", KnowledgeApi), ("tasks", TasksApi)): | |
| assert isinstance(getattr(client, attr), cls), attr | |
| print("import + config OK") | |
| PY | |
| - name: Quickstart drift smoke | |
| # quickstart.md is hand-maintained (not generated), so it can drift from the | |
| # SDK when the API surface changes. This catches the common cases offline (no | |
| # live API): its code must still parse, and every model/method it references | |
| # must still exist in the installed SDK. | |
| if: steps.detect.outputs.has_pkg == 'true' && hashFiles('quickstart.md') != '' | |
| run: | | |
| python - <<'PY' | |
| import re | |
| import everos_cloud.models as models | |
| from everos_cloud import EverOS, KnowledgeApi, MemoryApi, StorageApi, TasksApi | |
| CLASSES = {"EverOS": EverOS, "MemoryApi": MemoryApi, "StorageApi": StorageApi, | |
| "KnowledgeApi": KnowledgeApi, "TasksApi": TasksApi} | |
| text = open("quickstart.md").read() | |
| blocks = re.findall(r"```python\n(.*?)```", text, re.S) | |
| assert blocks, "no python code blocks found in quickstart.md" | |
| code = "\n".join(blocks) | |
| # 1) every snippet must still be valid Python | |
| compile(code, "quickstart.md", "exec") | |
| # 2) every model imported from everos_cloud.models must still exist | |
| for paren, line in re.findall( | |
| r"from everos_cloud\.models import (?:\(([^)]*)\)|([^\n]+))", text | |
| ): | |
| for name in re.split(r"[,\s]+", paren or line): | |
| name = name.strip() | |
| if name: | |
| assert hasattr(models, name), f"quickstart drift: missing model {name!r}" | |
| # 3) every method called on an EverOS / MemoryApi / StorageApi instance | |
| # must still exist (maps each instance var to its class from assignment). | |
| var_class = {v: CLASSES[c] for v, c in | |
| re.findall(r"(\w+)\s*=\s*(" + "|".join(CLASSES) + r")\(", code)} | |
| for var, cls in var_class.items(): | |
| for meth in sorted(set(re.findall(rf"\b{re.escape(var)}\.(\w+)\(", code))): | |
| assert hasattr(cls, meth), f"quickstart drift: {cls.__name__} has no {meth!r}" | |
| print("quickstart drift smoke OK") | |
| PY | |
| - name: Wrapper unit tests | |
| # Offline tests for the hand-maintained ergonomic client (everos_cloud/client.py). | |
| if: steps.detect.outputs.has_pkg == 'true' && hashFiles('tests/test_client.py') != '' | |
| run: | | |
| pip install pytest | |
| pytest -q tests/ | |
| - name: Build sdist + wheel | |
| if: steps.detect.outputs.has_pkg == 'true' | |
| run: | | |
| python -m pip install --upgrade build | |
| python -m build |