|
| 1 | +#!/bin/bash |
| 2 | +# How to use: |
| 3 | +# sudo bash compatibility_matrix.sh 3 |
| 4 | +# The above command will run the compatibility tests with a maximum of 3 parallel jobs. |
| 5 | + |
| 6 | +# Check for command-line argument; default to 1 if not provided |
| 7 | +max_parallel_jobs=${1:-1} |
| 8 | + |
| 9 | + |
| 10 | +# Ensure jq is installed |
| 11 | +if ! command -v jq &> /dev/null; then |
| 12 | + echo "jq could not be found. Please install jq to run this script." |
| 13 | + exit 1 |
| 14 | +fi |
| 15 | + |
| 16 | +echo "Running compatibility tests with a maximum of $max_parallel_jobs parallel jobs..." |
| 17 | + |
| 18 | +# Tests and store results in JSON |
| 19 | +run_tests() { |
| 20 | + local dj_ver_key=$1 |
| 21 | + local dj_ver="${dj_ver_key//d_/}" # Convert key to version |
| 22 | + dj_ver="${dj_ver//_/.}" |
| 23 | + shift |
| 24 | + local python_versions=("$@") |
| 25 | + |
| 26 | + # Define a counter for running jobs |
| 27 | + local -i jobs=0 |
| 28 | + |
| 29 | + for py_ver in "${python_versions[@]}"; do |
| 30 | + ( |
| 31 | + echo "Testing with Python ${py_ver} and Django ${dj_ver}" |
| 32 | + local individual_result_file="${result_dir}/${dj_ver}_${py_ver}.json" |
| 33 | + if docker build -f Dockerfile.test --build-arg PYTHON_VERSION="${py_ver}" --build-arg DJANGO_VERSION="${dj_ver}" -t django_appointment_test:"${py_ver}_${dj_ver}" . && \ |
| 34 | + docker run --rm django_appointment_test:"${py_ver}_${dj_ver}"; then |
| 35 | + echo "{\"result\": \"PASS\"}" > "$individual_result_file" |
| 36 | + echo "Test passed for Python ${py_ver} and Django ${dj_ver}" |
| 37 | + else |
| 38 | + echo "{\"result\": \"FAIL\"}" > "$individual_result_file" |
| 39 | + echo "Test failed for Python ${py_ver} and Django ${dj_ver}" |
| 40 | + fi |
| 41 | + ) & |
| 42 | + |
| 43 | + # Increment the job counter |
| 44 | + ((jobs++)) |
| 45 | + |
| 46 | + # If we've reached the max parallel jobs, wait for one to finish |
| 47 | + if ((jobs >= max_parallel_jobs)); then |
| 48 | + wait -n # Wait for any job to finish |
| 49 | + ((jobs--)) # Decrement the job counter |
| 50 | + fi |
| 51 | + done |
| 52 | + |
| 53 | + wait # Wait for the remaining jobs to finish |
| 54 | +} |
| 55 | + |
| 56 | +# Generate Markdown table from JSON results |
| 57 | +generate_markdown_table() { |
| 58 | + # Initialize Markdown file with the compatibility matrix header |
| 59 | + echo "# Compatibility Matrix" > compatibility_matrix.md |
| 60 | + # shellcheck disable=SC2129 |
| 61 | + echo "" >> compatibility_matrix.md |
| 62 | + echo "| Django \\ Python | 3.6 | 3.7 | 3.8 | 3.9 | 3.10 | 3.11 | 3.12 |" >> compatibility_matrix.md |
| 63 | + echo "|------------------|-----|-----|-----|-----|------|------|------|" >> compatibility_matrix.md |
| 64 | + |
| 65 | + for dj_ver_key in "${DJANGO_VERSIONS[@]}"; do |
| 66 | + local dj_ver="${dj_ver_key//d_/}" # Convert from d_x_y to x.y format |
| 67 | + dj_ver="${dj_ver//_/.}" |
| 68 | + echo -n "| $dj_ver " >> compatibility_matrix.md |
| 69 | + |
| 70 | + for py_ver in "${PYTHON_VERSIONS[@]}"; do |
| 71 | + local combined_key="${dj_ver}_${py_ver}" |
| 72 | + # shellcheck disable=SC2155 |
| 73 | + local result=$(jq -r --arg key "$combined_key" '.[$key]' "$result_file") |
| 74 | + [[ "$result" == "null" ]] && result="-" |
| 75 | + echo -n "| $result " >> compatibility_matrix.md |
| 76 | + done |
| 77 | + echo "|" >> compatibility_matrix.md |
| 78 | + done |
| 79 | + |
| 80 | + # shellcheck disable=SC2129 |
| 81 | + echo "" >> compatibility_matrix.md |
| 82 | + echo "## Test Results Explanation" >> compatibility_matrix.md |
| 83 | + echo "" >> compatibility_matrix.md |
| 84 | + echo "The compatibility matrix above demonstrates which combinations of Django and Python versions the package is compatible with based on the conducted tests. A 'PASS' indicates a successful compatibility test, whereas a 'FAIL' denotes an incompatibility or an issue encountered during testing. Versions marked with '-' were not tested due to known incompatibilities of django with python or other constraints." >> compatibility_matrix.md |
| 85 | + echo "" >> compatibility_matrix.md |
| 86 | + echo "See [django's official documentation about supported python versions](https://docs.djangoproject.com/en/5.0/faq/install/#what-python-version-can-i-use-with-django) for more details." >> compatibility_matrix.md |
| 87 | + echo "" >> compatibility_matrix.md |
| 88 | + echo "It's important to ensure that your environment matches these compatible combinations to avoid potential issues. If a specific combination you're interested in is marked as 'FAIL', it's recommended to check the corresponding test logs for details and consider alternative versions or addressing the identified issues." >> compatibility_matrix.md |
| 89 | +} |
| 90 | + |
| 91 | +generate_badge_json() { |
| 92 | + local python_compatible=() |
| 93 | + local django_compatible=() |
| 94 | + |
| 95 | + for py_ver in "${PYTHON_VERSIONS[@]}"; do |
| 96 | + for dj_ver_key in "${DJANGO_VERSIONS[@]}"; do |
| 97 | + local dj_ver="${dj_ver_key//d_/}" |
| 98 | + dj_ver="${dj_ver//_/.}" |
| 99 | + local combined_key="${dj_ver}_${py_ver}" |
| 100 | + # shellcheck disable=SC2155 |
| 101 | + local result=$(jq -r --arg key "$combined_key" '.[$key]' "$result_file") |
| 102 | + echo "Checking result for $combined_key: $result" |
| 103 | + if [[ "$result" == "PASS" ]]; then |
| 104 | + python_compatible+=("$py_ver") |
| 105 | + django_compatible+=("$dj_ver") |
| 106 | + fi |
| 107 | + done |
| 108 | + done |
| 109 | + |
| 110 | + echo "Python compatible versions: ${python_compatible[*]}" |
| 111 | + echo "Django compatible versions: ${django_compatible[*]}" |
| 112 | + |
| 113 | + echo "{ |
| 114 | + \"schemaVersion\": 1, |
| 115 | + \"label\": \"python\", |
| 116 | + \"message\": \"$(IFS=, ; echo "${python_compatible[*]}")\", |
| 117 | + \"color\": \"blue\" |
| 118 | + }" > "python_compatible.json" |
| 119 | + |
| 120 | + echo "{ |
| 121 | + \"schemaVersion\": 1, |
| 122 | + \"label\": \"django\", |
| 123 | + \"message\": \"$(IFS=, ; echo "${django_compatible[*]}")\", |
| 124 | + \"color\": \"blue\" |
| 125 | + }" > "django_compatible.json" |
| 126 | +} |
| 127 | + |
| 128 | +post_cleanup() { |
| 129 | + echo "Cleaning up temporary files..." |
| 130 | + rm -rf "$result_dir" |
| 131 | + |
| 132 | + echo "Removing docker images..." |
| 133 | + # shellcheck disable=SC2155 |
| 134 | + local dangling_images=$(docker images -q --filter "dangling=true") |
| 135 | + if [ -n "$dangling_images" ]; then |
| 136 | + docker rmi "$dangling_images" |
| 137 | + fi |
| 138 | + |
| 139 | + echo "Cleanup complete." |
| 140 | +} |
| 141 | + |
| 142 | +# Define directories and files |
| 143 | +result_dir="test_results" |
| 144 | +result_file="${result_dir}/results.json" |
| 145 | + |
| 146 | +# Compatible Python versions for each Django version with prefixed keys |
| 147 | +declare -A DJANGO_COMPATIBILITY=( |
| 148 | + ["d_3_2"]="3.6 3.7 3.8 3.9 3.10" |
| 149 | + ["d_4_0"]="3.8 3.9 3.10" |
| 150 | + ["d_4_1"]="3.8 3.9 3.10 3.11" |
| 151 | + ["d_4_2"]="3.8 3.9 3.10 3.11 3.12" |
| 152 | + ["d_5_0"]="3.10 3.11 3.12" |
| 153 | +) |
| 154 | + |
| 155 | +# Django and Python versions |
| 156 | +DJANGO_VERSIONS=("d_3_2" "d_4_0" "d_4_1" "d_4_2" "d_5_0") |
| 157 | +PYTHON_VERSIONS=("3.6" "3.7" "3.8" "3.9" "3.10" "3.11" "3.12") |
| 158 | + |
| 159 | + |
| 160 | +# Setup |
| 161 | +mkdir -p "$result_dir" |
| 162 | +echo "{}" > "$result_file" |
| 163 | + |
| 164 | +# Run tests for each Django/Python version combination |
| 165 | +for dj_ver_key in "${DJANGO_VERSIONS[@]}"; do |
| 166 | + IFS=' ' read -r -a python_versions <<< "${DJANGO_COMPATIBILITY[$dj_ver_key]}" |
| 167 | + run_tests "$dj_ver_key" "${python_versions[@]}" |
| 168 | +done |
| 169 | + |
| 170 | +wait # Wait for all tests to complete |
| 171 | + |
| 172 | +# Aggregate individual results into the final JSON file |
| 173 | +echo "{}" > "$result_file" # Reinitialize to ensure it's empty |
| 174 | +for file in "${result_dir}"/*.json; do |
| 175 | + dj_ver_py=$(basename "$file" .json) |
| 176 | + result=$(jq -r '.result' "$file") |
| 177 | + jq --arg dj_ver_py "$dj_ver_py" --arg result "$result" \ |
| 178 | + '.[$dj_ver_py] = $result' "$result_file" > "${result_file}.tmp" && mv "${result_file}.tmp" "$result_file" |
| 179 | +done |
| 180 | + |
| 181 | +# Generate the Markdown table after all tests are run |
| 182 | +generate_markdown_table |
| 183 | + |
| 184 | +echo "Compatibility matrix has been generated: compatibility_matrix.md" |
| 185 | +echo "Generating compatibility badges..." |
| 186 | +generate_badge_json |
| 187 | +echo "Cleaning up..." |
| 188 | +post_cleanup |
0 commit comments