validate_extension_api.sh 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. exit 1
  10. fi
  11. api_validation_dir="$( dirname -- "$( dirname -- "${BASH_SOURCE[0]//\.\//}" )" )/extension_api_validation/"
  12. has_problems=0
  13. warn_extra=0
  14. reference_tag=""
  15. expected_errors=""
  16. make_annotation()
  17. {
  18. local title=$1
  19. local body=$2
  20. local type=$3
  21. local file=$4
  22. if [[ "$GITHUB_OUTPUT" == "" ]]; then
  23. echo "$title"
  24. echo "$body"
  25. else
  26. body="$(awk 1 ORS='%0A' - <<<"$body")"
  27. echo "::$type file=$file,title=$title ::$body"
  28. fi
  29. }
  30. get_expected_output()
  31. {
  32. local parts=()
  33. IFS='_' read -ra parts <<< "$(basename "$1")"
  34. if [[ "${#parts[@]}" == "2" ]]; then
  35. while read -r file; do
  36. cat "$file" >> "$expected_errors"
  37. done <<< "$(find "$1" -type f -name "*.txt")"
  38. next="$(find "$api_validation_dir" -type d -name "${parts[1]}*")"
  39. if [[ "$next" != "" ]]; then
  40. get_expected_output "$next"
  41. fi
  42. reference_tag="${parts[0]}"
  43. warn_extra=0
  44. else
  45. while read -r file; do
  46. cat "$file" >> "$expected_errors"
  47. done <<< "$(find "$1" -type f -name "*.txt")"
  48. reference_tag="${parts[0]}"
  49. warn_extra=1
  50. fi
  51. }
  52. while read -r dir; do
  53. reference_file="$(mktemp)"
  54. validate="$(mktemp)"
  55. validation_output="$(mktemp)"
  56. allowed_errors="$(mktemp)"
  57. expected_errors="$(mktemp)"
  58. get_expected_output "$dir"
  59. # Download the reference extension_api.json
  60. 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
  61. # Validate the current API against the reference
  62. "$1" --headless --validate-extension-api "$reference_file" 2>&1 | tee "$validate" | awk '!/^Validate extension JSON:/' - || true
  63. # Collect the expected and actual validation errors
  64. awk '/^Validate extension JSON:/' - < "$validate" | sort > "$validation_output"
  65. awk '/^Validate extension JSON:/' - < "$expected_errors" | sort > "$allowed_errors"
  66. # Differences between the expected and actual errors
  67. new_validation_error="$(comm -23 "$validation_output" "$allowed_errors")"
  68. obsolete_validation_error="$(comm -13 "$validation_output" "$allowed_errors")"
  69. if [ -n "$obsolete_validation_error" ] && [ "$warn_extra" = "1" ]; then
  70. #make_annotation "The following validation errors no longer occur (compared to $reference_tag):" "$obsolete_validation_error" warning "$file"
  71. echo "The following validation errors no longer occur (compared to $reference_tag):"
  72. echo "$obsolete_validation_error"
  73. fi
  74. if [ -n "$new_validation_error" ]; then
  75. make_annotation "Compatibility to $reference_tag is broken in the following ways:" "$new_validation_error" error "$file"
  76. has_problems=1
  77. fi
  78. rm -f "$reference_file" "$validate" "$validation_output" "$allowed_errors" "$expected_errors"
  79. done <<< "$(find "$api_validation_dir" -type d -mindepth 1 -maxdepth 1)"
  80. exit $has_problems