Skip to content

Repo cleanup: restore sponsio refresh, edge-runtime SDK, docs/config sync #430

Repo cleanup: restore sponsio refresh, edge-runtime SDK, docs/config sync

Repo cleanup: restore sponsio refresh, edge-runtime SDK, docs/config sync #430

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: ${{ matrix.python-version }}
cache: pip
- name: Install core package
run: pip install -e .
- name: Install test + integration dependencies
run: |
pip install pytest pytest-cov langgraph langchain-core fastapi pydantic uvicorn python-multipart httpx opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
pip install claude-agent-sdk vercel-ai-sdk || echo "Optional SDK install failed (platform-specific), tests will skip"
# Build the canonical OpenClaw plugin TS so the
# ``test_openclaw_artifact_sync`` invariant test (compares
# ``plugins/sponsio-openclaw/dist/`` byte-for-byte against the
# wheel-bundled ``sponsio/plugin/openclaw_artifact/dist/``) has
# both copies on disk. ``npm ci`` pins to the exact lockfile
# versions that produced the committed bundled artifact, so
# bytes match.
- name: Set up Node.js (for OpenClaw plugin build)
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
- name: Build OpenClaw plugin TS artifact
working-directory: plugins/sponsio-openclaw
run: npm ci && npm run build
- name: Run tests
run: pytest --cov=sponsio --cov-report=term-missing -v
build-smoke-test:
name: Build wheel + install smoke test
runs-on: ubuntu-latest
# Stand-in for the TestPyPI gate we used to keep in publish.yml.
# `twine check` catches the same metadata regressions PyPI rejects on
# upload (long-description content-type, classifier validity, etc.);
# the install + `sponsio --version`/--help run catches packaging
# errors (missing modules, broken entry point) that would brick the
# wheel before we burn an immutable PyPI version number.
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: pip
- name: Build sdist + wheel
run: |
pip install build twine
python -m build
python -m twine check dist/*
- name: Install built wheel + verify CLI
# Install the freshly-built wheel into a clean venv (not editable)
# so this catches packaging issues that `pip install -e .` skips —
# e.g. missing files in `tool.setuptools.package-data`.
run: |
python -m venv /tmp/smoke-venv
/tmp/smoke-venv/bin/pip install dist/*.whl
/tmp/smoke-venv/bin/sponsio --version
/tmp/smoke-venv/bin/sponsio --help
# --version/--help are click-level and don't import yaml, so
# they missed #61 (pyyaml mis-filed as optional). Assert the
# core deps resolve, then run a command that actually reads the
# bundled YAML so a missing core dependency fails the build.
/tmp/smoke-venv/bin/python -c "import yaml"
/tmp/smoke-venv/bin/sponsio packs
test-typescript:
name: Test (TypeScript — native)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
- name: Install + Build TS workspace
working-directory: ts
# Use the root ``build`` script (which already passes
# ``--if-present`` to ``npm run build --workspaces``) so the
# example packages — which intentionally have no ``build``
# script — don't fail the matrix.
run: npm install && npm run build
- name: Run cross-language tests
working-directory: ts/packages/sdk
run: node dist/__tests__/core.test.js
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.12"
cache: pip
- name: Install ruff and dependencies
# Ruff `format` rules change between minor versions; pin to the
# same version pyproject.toml's `dev` extra declares so CI and
# local always agree.
run: pip install -e ".[dev]"
- name: Check formatting
run: ruff format --check sponsio/ tests/ scripts/
- name: Check linting
run: ruff check sponsio/ tests/ scripts/
- name: Check README/QUICKSTART command sync
run: |
# Canonical user-journey commands that must appear in user-facing
# docs. Prevents CLI renames/drift from silently desyncing the
# onboarding paths. README.md (the 60-second version) covers
# install + entry point; QUICKSTART.md (the full walkthrough)
# additionally covers report and the observe→enforce flip.
readme_required=(
"pip install sponsio"
"sponsio init"
)
quickstart_required=(
"pip install sponsio"
"sponsio init"
"sponsio report"
"SPONSIO_MODE=enforce"
)
exit_code=0
for cmd in "${readme_required[@]}"; do
if ! grep -qF "$cmd" README.md; then
echo "::error file=README.md::Canonical command missing: $cmd"
exit_code=1
fi
done
for cmd in "${quickstart_required[@]}"; do
if ! grep -qF "$cmd" QUICKSTART.md; then
echo "::error file=QUICKSTART.md::Canonical command missing: $cmd"
exit_code=1
fi
done
exit $exit_code
- name: Check README header assets intact
run: |
# WYSIWYG markdown editors strip key README assets:
# - banner image markdown at top
# - architecture diagram reference in "How Sponsio works"
# - <p align="center"> wrappers around badges + paste-prompt buttons
# Catch any of these going missing before push hits main.
fail=0
# Banner image markdown reference at top of README. Accepts both
# the relative path (works on GitHub) and the absolute raw.gh
# URL (also needed for PyPI README rendering, since PyPI does not
# resolve relative paths).
if ! grep -qE '!\[Sponsio\]\((assets/|https://raw\.githubusercontent\.com/[^)]+/assets/)readme-banner\.png\)' README.md; then
echo "::error file=README.md::Banner image markdown missing. Re-add at the top of the file (relative 'assets/readme-banner.png' or absolute 'https://raw.githubusercontent.com/.../assets/readme-banner.png')."
fail=1
fi
# Architecture diagram reference (anywhere in README)
if ! grep -qE 'assets/sponsio-architecture\.png' README.md; then
echo "::error file=README.md::Architecture diagram reference missing - 'assets/sponsio-architecture.png' was stripped. Re-add inside the 'How Sponsio works' section."
fail=1
fi
# Centered HTML wrappers (utility badges + social badges + architecture diagram + paste-prompt buttons → 3 minimum)
centered=$(grep -c '^<p align="center">' README.md || echo 0)
min_centered=3
if [ "$centered" -lt "$min_centered" ]; then
echo "::error file=README.md::Expected at least ${min_centered} <p align=\"center\"> blocks, found ${centered}. WYSIWYG editor likely stripped them."
fail=1
fi
# Asset files actually exist in the repo
for f in assets/readme-banner.png assets/sponsio-architecture.png; do
if [ ! -f "$f" ]; then
echo "::error file=${f}::Image asset missing from repo."
fail=1
fi
done
[ "$fail" -eq 0 ]