Every workflow was written for GitHub-hosted runners (ubuntu-latest,
macos-latest, macos-13, windows-latest, ubuntu-24.04-arm). This fleet's
Forgejo runners register different labels — `linux`, `linux-arm64`,
`macos`, `windows` — so as written, enabling Actions would queue every
job against a label no runner answers, and they would hang forever.
Mapping applied:
ubuntu-latest / ubuntu-24.04-arm -> linux / linux-arm64
macos-latest -> macos windows-latest -> windows
macos-13 (Intel Mac) -> dropped: the fleet has no Intel-Mac runner, and
by the matrices' own stated logic it adds no arch coverage (x86_64 is
held by linux + windows, arm64 by linux-arm64 + the macos reference).
Also: the macOS runner is a `host` executor launched from launchd, whose
PATH omits ~/.cargo/bin, so a raw `rustup` call is not found. wai-conformance
uses raw rustup across the matrix, so it now prepends ~/.cargo/bin to
$GITHUB_PATH first — a no-op on the platforms where cargo is already found.
All 10 jobs across 7 workflows parse and resolve to fleet labels. Note:
this makes the workflows *dispatchable*; the per-job conformance logic
(ONNX fixtures, cross-arch byte goldens) is what the first real runs verify.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
157 lines
5.4 KiB
YAML
157 lines
5.4 KiB
YAML
name: smart-byte conformance gate
|
|
|
|
on:
|
|
pull_request:
|
|
paths:
|
|
- 'smart-byte/spec/**'
|
|
- 'smart-byte/conformance/**'
|
|
- '.github/workflows/conformance.yml'
|
|
push:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'smart-byte/spec/**'
|
|
- 'smart-byte/conformance/**'
|
|
- '.github/workflows/conformance.yml'
|
|
|
|
jobs:
|
|
validate-json:
|
|
name: Validate conformance JSON files
|
|
runs-on: linux
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Ensure jq is available
|
|
run: jq --version
|
|
|
|
- name: Validate every JSON file under smart-byte/conformance/v*
|
|
run: |
|
|
set -euo pipefail
|
|
found=0
|
|
fail=0
|
|
while IFS= read -r -d '' f; do
|
|
found=$((found+1))
|
|
if ! jq empty "$f" >/dev/null 2>&1; then
|
|
echo "::error file=$f::invalid JSON"
|
|
fail=$((fail+1))
|
|
else
|
|
echo "ok: $f"
|
|
fi
|
|
done < <(find smart-byte/conformance -type f -name '*.json' -print0)
|
|
if [ "$found" -eq 0 ]; then
|
|
echo "::error::no JSON files found under smart-byte/conformance/v*"
|
|
exit 1
|
|
fi
|
|
if [ "$fail" -ne 0 ]; then
|
|
echo "::error::$fail JSON file(s) failed validation"
|
|
exit 1
|
|
fi
|
|
echo "validated $found JSON file(s)"
|
|
|
|
- name: Validate vector schema (top-level array, name field present)
|
|
run: |
|
|
set -euo pipefail
|
|
fail=0
|
|
while IFS= read -r -d '' f; do
|
|
if ! jq -e 'type == "array"' "$f" >/dev/null; then
|
|
echo "::error file=$f::top-level value must be a JSON array"
|
|
fail=$((fail+1))
|
|
continue
|
|
fi
|
|
if ! jq -e 'all(.[]; has("name") and has("description"))' "$f" >/dev/null; then
|
|
echo "::error file=$f::every vector must have name and description fields"
|
|
fail=$((fail+1))
|
|
fi
|
|
done < <(find smart-byte/conformance -type f -name '*_vectors.json' -print0)
|
|
if [ "$fail" -ne 0 ]; then
|
|
echo "::error::$fail vector file(s) failed schema validation"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Validate vector names are unique within each file
|
|
run: |
|
|
set -euo pipefail
|
|
fail=0
|
|
while IFS= read -r -d '' f; do
|
|
dupes=$(jq -r '[.[].name] | group_by(.) | map(select(length>1)) | .[][0] // empty' "$f")
|
|
if [ -n "$dupes" ]; then
|
|
echo "::error file=$f::duplicate vector name(s): $dupes"
|
|
fail=$((fail+1))
|
|
fi
|
|
done < <(find smart-byte/conformance -type f -name '*_vectors.json' -print0)
|
|
if [ "$fail" -ne 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
spec-vector-coupling:
|
|
name: Spec changes require vector-pack updates
|
|
runs-on: linux
|
|
if: github.event_name == 'pull_request'
|
|
steps:
|
|
- name: Checkout (with full history for diff)
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Determine the PR base
|
|
id: base
|
|
run: |
|
|
base="${{ github.event.pull_request.base.sha }}"
|
|
if [ -z "$base" ]; then
|
|
base="origin/main"
|
|
fi
|
|
echo "base=$base" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Enforce coupling between spec and conformance changes
|
|
run: |
|
|
set -euo pipefail
|
|
base="${{ steps.base.outputs.base }}"
|
|
head="${{ github.event.pull_request.head.sha }}"
|
|
if [ -z "$head" ]; then
|
|
head="HEAD"
|
|
fi
|
|
changed=$(git diff --name-only "$base" "$head")
|
|
echo "Files changed in this PR:"
|
|
echo "$changed"
|
|
spec_touched=0
|
|
conformance_touched=0
|
|
if echo "$changed" | grep -qE '^smart-byte/spec/'; then
|
|
spec_touched=1
|
|
fi
|
|
if echo "$changed" | grep -qE '^smart-byte/conformance/'; then
|
|
conformance_touched=1
|
|
fi
|
|
if [ "$spec_touched" -eq 1 ] && [ "$conformance_touched" -eq 0 ]; then
|
|
echo "::error::This PR modifies smart-byte/spec/ without modifying smart-byte/conformance/."
|
|
echo "::error::Per the conformance social contract, every spec change must be accompanied by a vector-pack update."
|
|
echo "::error::If the spec change is editorial and the wire format is unchanged, record the editorial reason in smart-byte/conformance/v<N>/regeneration.md and include that file in the PR."
|
|
exit 1
|
|
fi
|
|
echo "coupling check passed (spec_touched=$spec_touched, conformance_touched=$conformance_touched)"
|
|
|
|
versions-present:
|
|
name: VERSIONS.md and README.md must exist
|
|
runs-on: linux
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
- name: Required pack metadata files
|
|
run: |
|
|
set -euo pipefail
|
|
missing=0
|
|
for f in smart-byte/conformance/README.md smart-byte/conformance/VERSIONS.md; do
|
|
if [ ! -f "$f" ]; then
|
|
echo "::error file=$f::missing required pack metadata file"
|
|
missing=$((missing+1))
|
|
fi
|
|
done
|
|
for d in smart-byte/conformance/v*/ ; do
|
|
if [ ! -f "$d/regeneration.md" ]; then
|
|
echo "::error file=$d/regeneration.md::missing regeneration.md for $d"
|
|
missing=$((missing+1))
|
|
fi
|
|
done
|
|
if [ "$missing" -ne 0 ]; then
|
|
exit 1
|
|
fi
|