Skip to content

[Feat]: Align CI with pyproject extras, skill tests, and manifest dependencies #151

@rosspeili

Description

@rosspeili

Feature Description

GitHub Actions CI (.github/workflows/ci.yml) has drifted from how Skillware is packaged and tested today. It still carries a stale “no setup.py yet” comment, redundant manual pip install lines, and only runs pytest tests/ — while docs/TESTING.md tells contributors to also run pytest skills/.

Recent skill PRs (e.g. #150) had to hardcode a skill test path and add web3 manually to CI. That pattern does not scale as the registry grows.

Goal: one maintainable CI layout that:

  1. Installs dependencies from pyproject.toml (single source of truth), not ad hoc pip pins per PR
  2. Runs framework tests and skill co-located tests in clear separate steps (or jobs)
  3. Ensures skills with manifest.yaml requirements can be loaded and tested in CI without editing the workflow for each new skill
  4. Stays simple and reliable — no flaky PR CI, no over-engineering

Current state (baseline)

Area Today
CI install pip install flake8 pytest pytest-mock + requirements.txt (-e ".[dev,all]") + manual pymupdf anthropic requests
CI tests pytest tests/ only
Docs TESTING.md step 5: pytest skills/
Co-located skill tests skills/compliance/tos_evaluator/test_skill.py, skills/dev_tools/issue_resolver/test_skill.py, skills/data_engineering/novelty_extractor/test_skill.pynot run in CI
Framework skill tests tests/skills/** — run in CI via tests/
Manifest deps not in [all] e.g. fastembed, numpy (novelty_extractor); future web3 (defi)
Issuer/manifest checks tests/test_skill_issuer.py in tests/ — already in CI

Problems to fix

  • Per-PR edits to CI for each new skill dependency or test path
  • Redundant installs (pymupdf, anthropic already in [all])
  • Skill co-located tests invisible to CI unless duplicated under tests/
  • manifest.yaml requirements and pyproject.toml optional extras can disagree
  • requirements.txt duplicates/confuses the story (dev pointer vs CI truth)

Proposed direction (keep it simple)

A. Dependency install (one step, no per-skill pip lines)

  • CI should use pip install -e ".[dev,all]" explicitly (or keep requirements.txt only if it remains a thin pointer to that — not a second dependency list)
  • Extend [project.optional-dependencies] so [all] (or a new [ci] extra) includes all registry skill deps needed for CI today:
    • Existing: rich, SDKs, pymupdf, …
    • Missing today: fastembed, numpy, and future groups like web3>=6.0.0 under [defi] merged into [all] or [ci]
  • Convention: when a skill adds requirements: in manifest, the same packages must appear in pyproject optional extras (document in CONTRIBUTING)
  • Remove stale CI comment about missing setup.py; update comment to point at pyproject.toml

Avoid unless necessary: a dynamic “read all manifests and pip install” script in CI (nice later; not required for v1 if [all]/[ci] is kept current)

B. Two test steps (no hardcoded skill paths)

Step 1 — Framework / universal tests

pytest tests/

Covers loader, CLI, issuer rules, tests/skills/** integration tests. No per-skill paths.

Step 2 — Skill co-located tests

pytest skills/ --ignore=skills/**/__pycache__

Or equivalent glob: discovers every skills/**/test_skill.py automatically. No skills/defi/evm_tx_handler/test_skill.py hardcoding.

Optional: skip step 2 if no test_skill.py files exist (unlikely long term).

C. Env vars for CI

Keep dummy keys where skills expect them (ANTHROPIC_API_KEY, ETHERSCAN_API_KEY). Add placeholders for new skills as needed (e.g. AGENT_WALLET_PRIVATE_KEY for defi mocked tests) — generic dummy values in workflow env, not per-skill branches.

D. Docs sync

Update docs/TESTING.md and CONTRIBUTING CI section to match the two-step model. Clarify:

  • Framework tests → tests/
  • Skill bundle tests → skills/<category>/<name>/test_skill.py
  • Adding a skill with external deps → update pyproject extras + manifest requirements

E. Out of scope (this issue)

  • uv / lockfiles (separate RFC)
  • Black in CI (optional follow-up; flake8-only is fine for now)
  • Running every example script under examples/
  • Live RPC / mainnet smoke tests

Acceptance criteria

  • CI installs deps from pyproject only (no redundant manual package list except build tools if needed)
  • [all] or [ci] includes deps for all skills that have co-located tests or manifest requirements not covered by core
  • CI runs pytest tests/ and pytest skills/ as separate steps
  • No hardcoded skill test paths in .github/workflows/ci.yml
  • Co-located tests for existing skills (tos_evaluator, issue_resolver, novelty_extractor) pass in CI
  • tests/test_skill_issuer.py still passes (manifest/issuer contract)
  • TESTING.md / CONTRIBUTING updated to match
  • New skill PRs do not need CI workflow edits for standard test + dep patterns

Related

Rationale

CI is the contract between contributors and maintainers. Right now it passes for framework work but under-tests skills and invites per-PR workflow hacks. That creates review friction (every skill PR debates CI lines) and false confidence — docs say run pytest skills/, CI does not.

Centralizing deps in pyproject.toml and using pytest skills/ as a glob keeps CI stable as the registry grows, without the complexity of a custom dependency resolver or multi-job matrices per category.

We want this before or alongside merging large skills (e.g. #142 / #150) so contributors are not blocked on workflow edits.

Implementation Idea

Phase 1 — pyproject

Add optional groups and extend [all]:

[project.optional-dependencies]
defi = ["web3>=6.0.0"]
skills-embeddings = ["fastembed", "numpy"]  # or fold into all
ci = [...]  # optional alias: everything needed for pytest tests/ + pytest skills/
all = [..., "web3>=6.0.0", "fastembed", "numpy"]

Document in CONTRIBUTING: new skill with requirements: → update [all] (or relevant extra).

Phase 2 — ci.yml

- name: Install package and CI deps
  run: pip install -e ".[dev,all]"

- name: Framework tests
  run: pytest tests/
  env: { ... dummy keys ... }

- name: Skill co-located tests
  run: pytest skills/
  env: { ... same dummy keys ... }

Remove manual pip install pymupdf anthropic requests ... block and stale comment.

Phase 3 — verify locally

pip install -e ".[dev,all]"
pytest tests/
pytest skills/
flake8 .

Phase 4 — docs

One paragraph in TESTING.md + CONTRIBUTING linking manifest requirements ↔ pyproject extras ↔ CI.

Optional later: small script scripts/collect_manifest_requirements.py to fail CI if manifest deps are missing from [all] — only if manual [all] upkeep becomes painful.

Metadata

Metadata

Assignees

Labels

core frameworkChanges to loader, env, or base classes.enhancementNew feature or requesthelp wantedExtra attention is needed
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions