99 lines
2.8 KiB
Bash
99 lines
2.8 KiB
Bash
#!/usr/bin/env sh
|
|
set -eu
|
|
|
|
# Check OpenAPI contract levels for multi-module layout.
|
|
# - For PRs targeting main: require provider contract level >= L2.
|
|
# - Always require info.x-contract-level exists and is L0-L3.
|
|
#
|
|
# Expected locations:
|
|
# - spec/<module>/openapi.provider.yaml
|
|
# - spec/<module>/openapi.deps.yaml (optional)
|
|
|
|
require_provider_l2="${REQUIRE_PROVIDER_L2:-0}"
|
|
|
|
die() {
|
|
echo "ERROR: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
level_rank() {
|
|
case "$1" in
|
|
L0) echo 0;;
|
|
L1) echo 1;;
|
|
L2) echo 2;;
|
|
L3) echo 3;;
|
|
*) echo -1;;
|
|
esac
|
|
}
|
|
|
|
extract_level() {
|
|
# Extracts the first occurrence of info.x-contract-level: L?
|
|
# Accepts patterns like:
|
|
# x-contract-level: L2
|
|
# x-contract-level: "L2"
|
|
# under info:
|
|
file="$1"
|
|
|
|
awk '
|
|
BEGIN{in_info=0; level=""}
|
|
{
|
|
# detect "info:" at any indentation
|
|
if ($0 ~ /^[[:space:]]*info:[[:space:]]*$/) { in_info=1; info_indent=match($0,/[^ ]/)-1; next }
|
|
if (in_info==1) {
|
|
# if indentation decreases or new top-level key begins, leave info block
|
|
cur_indent=match($0,/[^ ]/)-1;
|
|
if (cur_indent <= info_indent && $0 ~ /^[^[:space:]]/ ) { in_info=0 }
|
|
}
|
|
if (in_info==1 && level=="" && $0 ~ /^[[:space:]]*x-contract-level:[[:space:]]*/) {
|
|
line=$0
|
|
sub(/^[[:space:]]*x-contract-level:[[:space:]]*/,"",line)
|
|
gsub(/"|\047/,"",line)
|
|
# strip comments
|
|
sub(/[[:space:]]*#.*/,"",line)
|
|
gsub(/[[:space:]]+/,"",line)
|
|
level=line
|
|
}
|
|
}
|
|
END{print level}
|
|
' "$file"
|
|
}
|
|
|
|
check_file_level() {
|
|
file="$1"
|
|
kind="$2" # provider|deps
|
|
|
|
[ -f "$file" ] || die "Missing OpenAPI file: $file"
|
|
|
|
level="$(extract_level "$file" | tr -d '\r')"
|
|
[ -n "$level" ] || die "$file: missing info.x-contract-level (expected under info: x-contract-level: L0|L1|L2|L3)"
|
|
|
|
rank="$(level_rank "$level")"
|
|
[ "$rank" -ge 0 ] || die "$file: invalid x-contract-level '$level' (expected L0|L1|L2|L3)"
|
|
|
|
if [ "$kind" = "provider" ] && [ "$require_provider_l2" = "1" ]; then
|
|
if [ "$rank" -lt 2 ]; then
|
|
die "$file: provider contract-level must be >= L2 for merge-to-main (current: $level)"
|
|
fi
|
|
fi
|
|
|
|
echo "OK: $file level=$level"
|
|
}
|
|
|
|
# Find all provider openapi files under spec/*
|
|
provider_files="$(find spec -mindepth 2 -maxdepth 2 -type f -name 'openapi.provider.yaml' 2>/dev/null || true)"
|
|
[ -n "$provider_files" ] || die "No provider OpenAPI found. Expected at least one spec/<module>/openapi.provider.yaml"
|
|
|
|
# Provider files always must have a valid level; for main merges, require >= L2
|
|
for f in $provider_files; do
|
|
check_file_level "$f" provider
|
|
|
|
done
|
|
|
|
# Deps files are optional, but if present must have valid level
|
|
for d in $(find spec -mindepth 2 -maxdepth 2 -type f -name 'openapi.deps.yaml' 2>/dev/null || true); do
|
|
check_file_level "$d" deps
|
|
|
|
done
|
|
|
|
echo "All OpenAPI contract level checks passed."
|