Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Test

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
pytest:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: uv sync
- name: Run tests
run: uv run pytest -v
61 changes: 55 additions & 6 deletions generate_models.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,48 @@ if ! command -v git &> /dev/null; then
exit 1
fi

# UCP Version to use (if provided, use release/$1 branch; otherwise, use main)
if [ -z "$1" ]; then
BRANCH="main"
# UCP source selection — three modes:
# ./generate_models.sh # main branch
# ./generate_models.sh 2026-04-08 # release/2026-04-08 branch
# ./generate_models.sh --ref <sha|ref> # arbitrary commit/branch/tag
#
# Identity-linking, info_code, and warning_code schemas merged after the
# 2026-04-08 release branch was cut, so consumers needing those must pin
# an explicit ref via --ref.
REF_MODE=""
REF_VALUE=""
if [ "$1" = "--ref" ]; then
if [ -z "$2" ]; then
echo "Error: --ref requires a commit SHA, branch, or tag." >&2
exit 1
fi
REF_MODE="ref"
REF_VALUE="$2"
echo "Cloning ucp at ref $REF_VALUE..."
elif [ -z "$1" ]; then
REF_MODE="branch"
REF_VALUE="main"
echo "No version specified, cloning main branch..."
else
BRANCH="release/$1"
echo "Cloning version $1 (branch: $BRANCH)..."
REF_MODE="branch"
REF_VALUE="release/$1"
echo "Cloning version $1 (branch: $REF_VALUE)..."
fi

# Ensure ucp directory is clean before cloning
rm -rf ucp
git clone -b "$BRANCH" --depth 1 https://github.com/Universal-Commerce-Protocol/ucp ucp
if [ "$REF_MODE" = "ref" ]; then
# Arbitrary ref may not be reachable via shallow clone of a branch;
# do a full clone then check out the ref.
git clone https://github.com/Universal-Commerce-Protocol/ucp ucp
(cd ucp && git checkout "$REF_VALUE")
else
git clone -b "$REF_VALUE" --depth 1 https://github.com/Universal-Commerce-Protocol/ucp ucp
fi

# Resolve the actual commit SHA we ended up on (for provenance manifest below)
UCP_SCHEMA_REF="$(cd ucp && git rev-parse HEAD)"
echo "ucp HEAD: $UCP_SCHEMA_REF"

# Output directory
OUTPUT_DIR="src/ucp_sdk/models/schemas"
Expand Down Expand Up @@ -78,4 +108,23 @@ uv run ruff format
uv run ruff check --fix "$OUTPUT_DIR"


# Record the source ref that produced this generated tree, so downstream
# consumers can verify provenance after upstream main moves.
GEN_CMD="$0 $*"
if [ -z "$*" ]; then
GEN_CMD="$0"
fi
cat > "src/ucp_sdk/_schema_ref.py" <<EOF
# Auto-generated by generate_models.sh. Do not edit by hand.
"""Provenance metadata for the generated schema models."""

UCP_SCHEMA_REF = "$UCP_SCHEMA_REF"
"""Commit SHA on Universal-Commerce-Protocol/ucp the models were generated from."""

GENERATE_COMMAND = "$GEN_CMD"
"""The generate_models.sh invocation that produced the current tree."""
EOF
echo "Wrote provenance to src/ucp_sdk/_schema_ref.py: $UCP_SCHEMA_REF"


echo "Done. Models generated in $OUTPUT_DIR"
1 change: 1 addition & 0 deletions preprocess_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ def normalize_metadata_schemas(schemas, target_dir):
"response_checkout_schema",
"response_order_schema",
"response_cart_schema",
"response_catalog_schema",
]
]

Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ dependencies = [
[dependency-groups]
dev = [
"datamodel-code-generator[http,ruff]>=0.50.0",
"pytest>=8.0",
]

[tool.pytest.ini_options]
testpaths = ["tests"]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Expand Down
8 changes: 8 additions & 0 deletions src/ucp_sdk/_schema_ref.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Auto-generated by generate_models.sh. Do not edit by hand.
"""Provenance metadata for the generated schema models."""

UCP_SCHEMA_REF = "c5c61396ebf9a5afb9c4169bfa3af1409daa6fd6"
"""Commit SHA on Universal-Commerce-Protocol/ucp the models were generated from."""

GENERATE_COMMAND = "generate_models.sh --ref c5c61396ebf9a5afb9c4169bfa3af1409daa6fd6"
"""The generate_models.sh invocation that produced the current tree."""
1 change: 1 addition & 0 deletions src/ucp_sdk/models/schemas/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
# generated by datamodel-codegen
# pylint: disable=all
# pyformat: disable

132 changes: 116 additions & 16 deletions src/ucp_sdk/models/schemas/capability.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,114 @@ class UcpCapability(RootModel[Any]):
"""


class Extends(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends1Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends1(RootModel[list[Extends1Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends1Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends2(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends3Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends3(RootModel[list[Extends3Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends3Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends4(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends5Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends5(RootModel[list[Extends5Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends5Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends6(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Extends7Item(RootModel[str]):
model_config = ConfigDict(
frozen=True,
)
root: str = Field(..., pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$")


class Extends7(RootModel[list[Extends7Item]]):
model_config = ConfigDict(
frozen=True,
)
root: list[Extends7Item] = Field(..., min_length=1)
"""
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


class Version(RootModel[Any]):
model_config = ConfigDict(
frozen=True,
Expand Down Expand Up @@ -64,11 +172,9 @@ class Base(BaseModel):
"""
Entity-specific configuration. Structure defined by each entity's schema.
"""
extends: str | None = Field(
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
)
extends: Extends | Extends1 | None = None
"""
Parent capability this extends. Present for extensions, absent for root capabilities.
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


Expand Down Expand Up @@ -100,11 +206,9 @@ class PlatformSchema(BaseModel):
"""
Entity-specific configuration. Structure defined by each entity's schema.
"""
extends: str | None = Field(
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
)
extends: Extends2 | Extends3 | None = None
"""
Parent capability this extends. Present for extensions, absent for root capabilities.
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


Expand Down Expand Up @@ -136,11 +240,9 @@ class BusinessSchema(BaseModel):
"""
Entity-specific configuration. Structure defined by each entity's schema.
"""
extends: str | None = Field(
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
)
extends: Extends4 | Extends5 | None = None
"""
Parent capability this extends. Present for extensions, absent for root capabilities.
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""


Expand Down Expand Up @@ -172,9 +274,7 @@ class ResponseSchema(BaseModel):
"""
Entity-specific configuration. Structure defined by each entity's schema.
"""
extends: str | None = Field(
None, pattern="^[a-z][a-z0-9]*(?:\\.[a-z][a-z0-9_]*)+$"
)
extends: Extends6 | Extends7 | None = None
"""
Parent capability this extends. Present for extensions, absent for root capabilities.
Parent capability(s) this extends. Present for extensions, absent for root capabilities. Use array for multi-parent extensions.
"""
18 changes: 18 additions & 0 deletions src/ucp_sdk/models/schemas/common/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 UCP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# generated by datamodel-codegen
# pylint: disable=all
# pyformat: disable

Loading