Skip to content

Caveman 2.0.0 β€” engine, proxy, SDKs, unified CLI #2

Caveman 2.0.0 β€” engine, proxy, SDKs, unified CLI

Caveman 2.0.0 β€” engine, proxy, SDKs, unified CLI #2

name: provider-catalog-contract
on:
pull_request:
paths:
- "shared/provider-catalog/catalog/**"
permissions:
contents: read
concurrency:
group: provider-catalog-contract-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
catalog:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.13"
- name: Reject mixed changes and rewritten snapshots
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
if ! git cat-file -e "$BASE_SHA:shared/provider-catalog/catalog/current.yaml" 2>/dev/null; then
echo "catalog absent at base (initial import); skipping lane-scope gate"
exit 0
fi
current_touched=false
new_snapshot=false
git diff --name-only "$BASE_SHA" "$HEAD_SHA" > /tmp/changed-files
while IFS= read -r file; do
case "$file" in
shared/provider-catalog/catalog/current.yaml)
current_touched=true
;;
shared/provider-catalog/catalog/????-??-??.yaml)
if git cat-file -e "$BASE_SHA:$file" 2>/dev/null; then
echo "dated catalog snapshots are immutable: $file"
exit 1
fi
new_snapshot=true
;;
*)
echo "catalog lane rejects out-of-scope path: $file"
exit 1
;;
esac
done < /tmp/changed-files
if [[ "$current_touched" != "true" || "$new_snapshot" != "true" ]]; then
echo "catalog PR requires current.yaml plus one new dated snapshot"
exit 1
fi
- name: Install pinned validator dependency
run: python -m pip install -r shared/provider-catalog/requirements-dev.txt
- name: Validate catalog
run: python shared/provider-catalog/validate_catalog.py
- name: Test validator failure modes
run: python -m unittest discover -s shared/provider-catalog/tests -p 'test_*.py'