validate_extension_api.sh 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #!/bin/bash
  2. set -o pipefail
  3. if [ ! -f "version.py" ]; then
  4. echo "Warning: This script is intended to be run from the root of the Godot repository."
  5. echo "Some of the paths checks may not work as intended from a different folder."
  6. fi
  7. if [ $# != 1 ]; then
  8. echo "Usage: @0 <path-to-godot-executable>"
  9. fi
  10. api_validation_dir="$( dirname -- "$( dirname -- "${BASH_SOURCE[0]//\.\//}" )" )/extension_api_validation/"
  11. has_problems=0
  12. warn_extra=0
  13. reference_tag=""
  14. expected_errors=""
  15. make_annotation()
  16. {
  17. local title=$1
  18. local body=$2
  19. local type=$3
  20. local file=$4
  21. if [[ "$GITHUB_OUTPUT" == "" ]]; then
  22. echo "$title"
  23. echo "$body"
  24. else
  25. body="$(awk 1 ORS='%0A' - <<<"$body")"
  26. echo "::$type file=$file,title=$title ::$body"
  27. fi
  28. }
  29. get_expected_output()
  30. {
  31. local parts=()
  32. IFS='_' read -ra parts <<< "$(basename -s .expected "$1")"
  33. if [[ "${#parts[@]}" == "2" ]]; then
  34. cat "$1" >> "$expected_errors"
  35. get_expected_output "$(find "$api_validation_dir" -name "${parts[1]}*.expected")"
  36. reference_tag="${parts[0]}"
  37. warn_extra=0
  38. else
  39. cat "$1" >> "$expected_errors"
  40. reference_tag="${parts[0]}"
  41. warn_extra=1
  42. fi
  43. }
  44. while read -r file; do
  45. reference_file="$(mktemp)"
  46. validate="$(mktemp)"
  47. validation_output="$(mktemp)"
  48. allowed_errors="$(mktemp)"
  49. expected_errors="$(mktemp)"
  50. get_expected_output "$file"
  51. # Download the reference extension_api.json
  52. wget -nv --retry-on-http-error=503 --tries=5 --timeout=60 -cO "$reference_file" "https://raw.githubusercontent.com/godotengine/godot-cpp/godot-$reference_tag/gdextension/extension_api.json" || has_problems=1
  53. # Validate the current API against the reference
  54. "$1" --headless --validate-extension-api "$reference_file" 2>&1 | tee "$validate" | awk '!/^Validate extension JSON:/' - || true
  55. # Collect the expected and actual validation errors
  56. awk '/^Validate extension JSON:/' - < "$validate" | sort > "$validation_output"
  57. awk '/^Validate extension JSON:/' - < "$expected_errors" | sort > "$allowed_errors"
  58. # Differences between the expected and actual errors
  59. new_validation_error="$(comm -23 "$validation_output" "$allowed_errors")"
  60. obsolete_validation_error="$(comm -13 "$validation_output" "$allowed_errors")"
  61. if [ -n "$obsolete_validation_error" ] && [ "$warn_extra" = "1" ]; then
  62. make_annotation "The following validation errors no longer occur (compared to $reference_tag):" "$obsolete_validation_error" warning "$file"
  63. fi
  64. if [ -n "$new_validation_error" ]; then
  65. make_annotation "Compatibility to $reference_tag is broken in the following ways:" "$new_validation_error" error "$file"
  66. has_problems=1
  67. fi
  68. rm -f "$reference_file" "$validate" "$validation_output" "$allowed_errors" "$expected_errors"
  69. done <<< "$(find "$api_validation_dir" -name "*.expected")"
  70. exit $has_problems