82 lines
4.2 KiB
YAML
82 lines
4.2 KiB
YAML
# Canonical CI config for hanzoai/openapi — read by the hanzoai/ci reusable
|
|
# (.github/workflows/cicd.yml) and platform.hanzo.ai.
|
|
#
|
|
# Publishes the agent-skills catalog (/.well-known/agent-skills, skills.py
|
|
# --no-services) as a versioned immutable image whose rootfs is /catalog.
|
|
# hanzo-inc/cloud consumes it via `FROM ... AS skills` + `COPY --from=skills
|
|
# /catalog/`, so it never re-runs skills.py inside a cloud release. hanzoai/ci
|
|
# pushes to `repo:` (GHCR) and auto-mirrors to oci.hanzo.ai.
|
|
images:
|
|
- name: agent-skills
|
|
context: .
|
|
dockerfile: Dockerfile.skills
|
|
repo: ghcr.io/hanzoai/agent-skills
|
|
|
|
test:
|
|
- name: spec
|
|
# hanzo.yaml is the single input to SEVEN language SDKs, the doc site and the
|
|
# agent-skills catalog, so a defect merged here is a defect merged into all
|
|
# of them at once, discovered separately in each.
|
|
#
|
|
# test_publish.py is the offline half of the artifact gate: it reads the
|
|
# COMMITTED hanzo.yaml and asserts the properties publish.py promises —
|
|
# every operation generatable, operationIds unique to a GENERATOR and not
|
|
# merely as strings, a security scheme a client can authenticate with, every
|
|
# capability grouped exactly once, and no `<svc>/openapi.yaml` back on disk.
|
|
# It needs no network and no hanzo-inc/cloud checkout.
|
|
#
|
|
# The half that needs a hanzo-inc/cloud checkout is `publish.py --check` in the
|
|
# `spec sync` workflow, which re-derives from the pinned ref and diffs. That
|
|
# is what catches a hand edit that happens to be well-formed — the one this
|
|
# repo exists to make impossible now that hanzo.yaml is output rather than
|
|
# input. The `served` gate below asks the weaker version of that question
|
|
# with no checkout at all, which is why it is HERE and runs on every build.
|
|
#
|
|
# test_flows.py asserts every operationId flows.yaml names still exists in
|
|
# hanzo.yaml, so a route that stops being served breaks one gate here instead
|
|
# of six SDKs' examples quietly and separately.
|
|
#
|
|
# uv rather than a bare python3 — the runner image promises no interpreter,
|
|
# let alone one with PyYAML.
|
|
run: |
|
|
set -e
|
|
if command -v uv >/dev/null 2>&1; then UV=uv; else
|
|
curl -fsSL https://astral.sh/uv/install.sh | sh
|
|
UV="$HOME/.local/bin/uv"
|
|
fi
|
|
"$UV" run --no-project --python 3.12 --with pyyaml --with pytest \
|
|
python -m pytest test_publish.py test_flows.py test_skills.py test_tools.py -q
|
|
|
|
- name: served
|
|
# Every operation this repo PUBLISHES must be one api.hanzo.ai answers for.
|
|
#
|
|
# The gate that was supposed to hold that line — `publish.py --check` —
|
|
# needs a hanzo-inc/cloud checkout, so it can only run where a credential
|
|
# for a private repo in another org exists, and HANZO_GIT_TOKEN is not
|
|
# sealed here yet. So it never ran, and while it did
|
|
# not: the pin went 81 hanzo-inc/cloud commits stale, hanzo.yaml was hand-
|
|
# edited to delete a route (which is the one thing a generated file must
|
|
# never receive), and it shipped 19 operations to every SDK that nothing
|
|
# serves — including `POST /v1/admin/credits`, a money mint hanzo-inc/cloud
|
|
# had deleted. Measured, not supposed: those 19 are what this gate printed
|
|
# the first time it was pointed at the committed artifact.
|
|
#
|
|
# So this asks the weaker question that needs NOTHING — no checkout, no
|
|
# token, no ref — and therefore actually runs. Cloud serves its own emission
|
|
# unauthenticated at /v1/openapi.json, from the binary that is running, and
|
|
# a route absent from it is refuted by the deployment itself. One direction
|
|
# only: served-and-unpublished means the pin is behind, which is not a lie
|
|
# about the API and is `--current`'s question.
|
|
#
|
|
# NEVER FAILS ON AN UNREACHABLE API — same rule as hanzo.ai's
|
|
# scripts/audit-catalog.mjs, which gates the same document the same way. A
|
|
# gate that goes red for somebody else's outage gets switched off, and then
|
|
# it gates nothing.
|
|
run: |
|
|
set -e
|
|
if command -v uv >/dev/null 2>&1; then UV=uv; else
|
|
curl -fsSL https://astral.sh/uv/install.sh | sh
|
|
UV="$HOME/.local/bin/uv"
|
|
fi
|
|
"$UV" run --no-project --python 3.12 --with pyyaml python publish.py --served
|