Skip to content

feat(hitl): add createHITLRequest — paired SDK release for ADK plugin v1 #56

feat(hitl): add createHITLRequest — paired SDK release for ADK plugin v1

feat(hitl): add createHITLRequest — paired SDK release for ADK plugin v1 #56

name: Wire-Shape Contract
# QF-14 Java arm: blocks drift between Java @JsonProperty-annotated
# classes and the OpenAPI specs that are the authoritative wire
# contract. Runs on every PR and push to main. Drift NOT covered by
# the baseline fails the check.
#
# Specs are fetched from the getaxonflow/axonflow community mirror at
# the SHA recorded in tests/fixtures/wire-shape-baseline.json so the
# gate is deterministic. A 'spec-pin-bump' label is required on PRs
# that change the SHA, preserving review integrity (a PR that both
# moved the SHA and the Java classes could otherwise silence drift).
#
# To regenerate the baseline:
# python3 scripts/wire_shape/refresh.py <specs_dir>
on:
pull_request:
branches: [main]
paths:
- 'src/main/java/**/*.java'
- 'tests/fixtures/wire-shape-baseline.json'
- 'scripts/wire_shape/**'
- '.github/workflows/wire-shape-contract.yml'
push:
branches: [main]
paths:
- 'src/main/java/**/*.java'
- 'tests/fixtures/wire-shape-baseline.json'
- 'scripts/wire_shape/**'
- '.github/workflows/wire-shape-contract.yml'
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
wire-shape:
name: Validate Wire Shape
runs-on: ubuntu-latest
env:
AXONFLOW_TELEMETRY: 'off'
steps:
- name: Checkout SDK (full history for SHA-bump guard)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Read pinned OpenAPI specs SHA from baseline
id: specs_sha
run: |
python3 - <<'PY' >> "$GITHUB_OUTPUT"
import json
import sys
path = "tests/fixtures/wire-shape-baseline.json"
data = json.load(open(path))
sha = (data.get("openapi_specs_sha", "") or "").strip()
if not sha:
print(
f"::error::{path} is missing openapi_specs_sha. "
"Regenerate via scripts/wire_shape/refresh.py.",
file=sys.stderr,
)
sys.exit(1)
print(f"sha={sha}")
PY
- name: Guard against unauthorized OpenAPI specs SHA bump
if: github.event_name == 'pull_request'
env:
PR_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
BASE_REF: ${{ github.base_ref }}
PR_SHA: ${{ steps.specs_sha.outputs.sha }}
run: |
set -e
BASE_FILE=$(mktemp)
if git show "origin/${BASE_REF}:tests/fixtures/wire-shape-baseline.json" > "$BASE_FILE" 2>/dev/null; then
# File exists on the base branch. It MUST parse — a malformed
# baseline file would otherwise let `BASE_SHA` come back empty
# and route this PR through the "first pin introduction"
# bypass below, silently authorizing a SHA bump.
BASE_SHA=$(python3 -c "import json, sys; print(json.load(open(sys.argv[1])).get('openapi_specs_sha','') or '')" "$BASE_FILE")
else
# File genuinely absent on the base branch (first-time
# introduction). Distinguishing this from "file present but
# unparseable" is what guards the bypass.
BASE_SHA=""
fi
rm -f "$BASE_FILE"
if [ -z "$BASE_SHA" ]; then
if git cat-file -e "origin/${BASE_REF}:tests/fixtures/wire-shape-baseline.json" 2>/dev/null; then
echo "::error::tests/fixtures/wire-shape-baseline.json on origin/${BASE_REF} parsed with empty openapi_specs_sha."
echo "::error::This is unrecoverable from inside the gate. Re-run scripts/wire_shape/refresh.py on main."
exit 1
fi
echo "::notice::Base branch has no wire-shape-baseline.json yet; treating this PR as first pin introduction."
exit 0
fi
if [ "$BASE_SHA" = "$PR_SHA" ]; then
echo "openapi_specs_sha unchanged (${PR_SHA})."
exit 0
fi
echo "SHA change detected: ${BASE_SHA} -> ${PR_SHA}"
HAS_LABEL=$(printf '%s' "$PR_LABELS" | python3 -c "import json, sys; print('spec-pin-bump' in json.load(sys.stdin))")
if [ "$HAS_LABEL" = "True" ]; then
echo "::notice::'spec-pin-bump' label present — SHA bump authorized."
exit 0
fi
echo "::error::openapi_specs_sha changed from ${BASE_SHA} to ${PR_SHA}."
echo "::error::The wire-shape contract's spec revision is pinned to preserve"
echo "::error::review integrity: a SHA change in the same PR as SDK changes"
echo "::error::can silence drift by retargeting the contract to a friendlier"
echo "::error::revision. Either split into a dedicated SHA-bump PR, or"
echo "::error::apply the 'spec-pin-bump' label to this PR."
exit 1
- name: Checkout OpenAPI specs (pinned to baseline SHA)
uses: actions/checkout@v4
with:
repository: getaxonflow/axonflow
ref: ${{ steps.specs_sha.outputs.sha }}
path: axonflow-community
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install PyYAML
run: pip install 'pyyaml>=6,<7'
- name: Run wire-shape contract validator
env:
AXONFLOW_OPENAPI_SPECS_DIR: ${{ github.workspace }}/axonflow-community/docs/api
run: python3 scripts/wire_shape/validate.py