c42c877ce6
meta-ci-advisory / meta (advisory) (push) Successful in 5s
contracts-codegen-drift / codegen-drift (push) Successful in 10s
llm-registry-ssot-drift / llm-registry-ssot-drift (push) Successful in 9s
Test / skill-framework-cli (push) Successful in 15s
registry-ssot-drift / registry-ssot-drift (push) Successful in 12s
llm-registry-ssot-drift / llm-registry-ssot-conformance (push) Successful in 17s
contracts-codegen-drift / go-parity (push) Successful in 18s
contracts-codegen-drift / adapter-registry-conformance (push) Successful in 21s
contracts-codegen-drift / workspace-routes-manifest-conformance (push) Successful in 19s
contracts-codegen-drift / prompt-canonical-text-conformance (push) Successful in 20s
contracts-codegen-drift / platform-identity-gate-conformance (push) Successful in 20s
registry-ssot-drift / registry-ssot-conformance (push) Successful in 18s
contracts-codegen-drift / bindings-parity (push) Successful in 20s
contracts-codegen-drift / contract-conformance (push) Successful in 23s
contracts-codegen-drift / native-plugins-registry-conformance (push) Successful in 22s
contracts-codegen-drift / validate (push) Successful in 27s
contracts-codegen-drift / all-required (push) Successful in 2s
Test / package-smoke (push) Successful in 30s
Test / test (3.11) (push) Successful in 55s
Test / test (3.13) (push) Successful in 55s
Test / test (3.12) (push) Successful in 55s
Test / all-required (push) Successful in 1s
Reviewed-on: #153
171 lines
6.4 KiB
YAML
171 lines
6.4 KiB
YAML
name: Test
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
strategy:
|
|
matrix:
|
|
python-version: ['3.11', '3.12', '3.13']
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: ${{ matrix.python-version }}
|
|
|
|
- name: Install dependencies
|
|
run: pip install -e ".[test]"
|
|
|
|
- name: Run tests
|
|
run: python -m pytest tests/
|
|
|
|
- name: Lint
|
|
run: pip install ruff==0.15.21 && ruff check molecule_external_workspace/ molecule_plugin/
|
|
|
|
package-smoke:
|
|
name: package-smoke
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: '3.12'
|
|
|
|
- name: Build wheel and sdist
|
|
run: |
|
|
set -euo pipefail
|
|
python -m pip install --index-url https://pypi.org/simple build==1.3.0
|
|
python -m build
|
|
|
|
- name: Assert wheel contains every scaffold kind
|
|
run: |
|
|
set -euo pipefail
|
|
python - <<'PY'
|
|
import glob
|
|
import zipfile
|
|
|
|
[wheel] = glob.glob("dist/molecule_ai_sdk-*.whl")
|
|
with zipfile.ZipFile(wheel) as archive:
|
|
names = archive.namelist()
|
|
common = {".gitignore", ".gitea/workflows/ci.yml", "tests/test_scaffold.py"}
|
|
expected = {
|
|
"skill": common | {"plugin.yaml", "README.md", "skills/__PLUGIN_NAME__/SKILL.md", "adapters/claude_code.py", "adapters/codex.py"},
|
|
"mcp": common | {"plugin.yaml", "README.md", "server.py"},
|
|
"channel": common | {"plugin.yaml", "README.md", "bridge.py"},
|
|
"trigger": common | {"plugin.yaml", "README.md", "scheduler.py", "trigger_schedule.py", "schedules.yaml"},
|
|
"enterskill": common | {"plugin.yaml", "README.md", "skills/__PLUGIN_NAME__/SKILL.md"},
|
|
}
|
|
for kind, paths in expected.items():
|
|
prefix = f"molecule_plugin/templates/{kind}/"
|
|
missing = sorted(path for path in paths if prefix + path not in names)
|
|
if missing:
|
|
raise SystemExit(f"wheel missing {kind} scaffold files: {missing}")
|
|
print("wheel contains complete skill, mcp, and channel scaffolds")
|
|
PY
|
|
|
|
- name: Clean install with public dependencies and exercise CLI
|
|
run: |
|
|
set -euo pipefail
|
|
VENV_ROOT=$(mktemp -d)
|
|
python -m venv "$VENV_ROOT/venv"
|
|
PIP="$VENV_ROOT/venv/bin/pip"
|
|
PY="$VENV_ROOT/venv/bin/python"
|
|
CLI="$VENV_ROOT/venv/bin/molecule-plugin"
|
|
"$PIP" install --force-reinstall --no-cache-dir \
|
|
--index-url https://pypi.org/simple dist/*.whl
|
|
SMOKE=$(mktemp -d)
|
|
cd "$SMOKE"
|
|
for kind in skill mcp channel trigger enterskill; do
|
|
"$CLI" init "smoke-$kind" --kind "$kind"
|
|
"$CLI" validate plugin "smoke-$kind"
|
|
(cd "smoke-$kind" && "$PY" -m unittest discover -s tests -v)
|
|
done
|
|
"$CLI" channel-sdk check "smoke-channel"
|
|
"$CLI" channel-sdk check "smoke-trigger"
|
|
"$PY" - <<'PY'
|
|
from importlib.metadata import version
|
|
import molecule_external_workspace
|
|
import molecule_plugin
|
|
|
|
expected = version("molecule-ai-sdk")
|
|
assert molecule_plugin.__version__ == expected
|
|
assert molecule_external_workspace.__version__ == expected
|
|
print(f"clean wheel smoke OK: {expected}")
|
|
PY
|
|
|
|
skill-framework-cli:
|
|
# The enterskill CLI (tools/skill-framework/cli.mjs) is the official
|
|
# hard gate consumer skill repos run against the contracts/skill-framework
|
|
# family. Node-only by design (stdlib, no npm install): self-tests via the
|
|
# stdlib test runner, plus proof that the 2020-12 validator factored into
|
|
# tools/lib/jsonschema2020.mjs keeps the generator's gen/ output
|
|
# byte-identical (the codegen-drift workflow re-checks the same invariant
|
|
# across all generators).
|
|
name: skill-framework-cli
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
|
with:
|
|
node-version: '22'
|
|
|
|
- name: Self-test the enterskill CLI (stdlib node --test)
|
|
run: node --test "tools/skill-framework/*.test.mjs"
|
|
|
|
- name: "@enteros/brand — semantic token WCAG-AA contrast gate"
|
|
# Recomputes every gated pair of the brand semantic token contract
|
|
# with the exact formula of molecule-core's canvas a11y gate
|
|
# (canvas/src/app/__tests__/globals.a11y.test.ts); nonzero exit on
|
|
# any pair < 4.5:1. Stdlib node, no install (same posture as above).
|
|
run: node brand/scripts/validate-contrast.mjs
|
|
|
|
- name: Factored validator keeps skill-framework gen/ byte-identical
|
|
run: |
|
|
set -euo pipefail
|
|
node tools/gen-skill-framework.mjs
|
|
git diff --exit-code -- \
|
|
gen/ts/skill_framework_gen.ts \
|
|
gen/python/skill_framework_gen.py \
|
|
gen/go/molcontracts/skill_framework_gen.go
|
|
|
|
all-required:
|
|
name: all-required
|
|
needs: [test, package-smoke, skill-framework-cli]
|
|
if: ${{ always() }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Assert every required dependency succeeded
|
|
run: |
|
|
set -euo pipefail
|
|
results='${{ toJSON(needs) }}'
|
|
echo "$results"
|
|
echo "$results" | python3 -c '
|
|
import json, sys
|
|
ns = json.load(sys.stdin)
|
|
bad = [(k, v.get("result")) for k, v in ns.items()
|
|
if v.get("result") != "success"]
|
|
if bad:
|
|
print("FAIL: jobs not green:", file=sys.stderr)
|
|
for k, r in bad:
|
|
print(f" - {k}: {r}", file=sys.stderr)
|
|
sys.exit(1)
|
|
print(f"OK: all {len(ns)} required jobs succeeded")
|
|
'
|