Skip to content

Commit df822c8

Browse files
authored
Merge pull request #133 from adamspd/feature/compatibility-check
Compatibility matrix
2 parents 4c242d1 + 4ac1a80 commit df822c8

File tree

7 files changed

+280
-0
lines changed

7 files changed

+280
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Compatibility Check Workflow
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
branch:
7+
description: 'Branch to run the workflow on'
8+
required: true
9+
default: 'main'
10+
schedule:
11+
# Schedule to run at 00:00 on the 1st of every month
12+
- cron: '0 0 1 * *'
13+
14+
jobs:
15+
compatibility-check:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@v4
20+
with:
21+
ref: ${{ github.event.inputs.branch }}
22+
23+
- name: Install jq
24+
run: sudo apt-get update && sudo apt-get install jq -y
25+
26+
- name: Run Compatibility Matrix Script
27+
run: sudo bash compatibility_matrix.sh 3
28+
29+
- name: Commit and Push if not on main branch
30+
if: github.ref_name != 'main'
31+
run: |
32+
git config --global user.email "[email protected]"
33+
git config --global user.name "GitHub Actions"
34+
git add .
35+
git commit -m "Update compatibility matrix and badges"
36+
git push
37+
env:
38+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Dockerfile.test

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM python:3.10-slim
2+
3+
# Set the working directory in the container
4+
WORKDIR /app
5+
6+
# Copy the current directory contents into the container at /app
7+
COPY . /app
8+
9+
# Install any needed packages specified in requirements.txt
10+
ARG DJANGO_VERSION=5.0.3
11+
RUN pip install --no-cache-dir -r requirements-test.txt Django==${DJANGO_VERSION}
12+
13+
# Make port 8000 available to the world outside this container
14+
EXPOSE 8000
15+
16+
CMD ["python", "manage.py", "test"]

compatibility_matrix.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Compatibility Matrix
2+
3+
| Django \ Python | 3.6 | 3.7 | 3.8 | 3.9 | 3.10 | 3.11 | 3.12 |
4+
|------------------|-----|-----|-----|-----|------|------|------|
5+
| 3.2 | PASS | PASS | PASS | PASS | PASS | - | - |
6+
| 4.0 | - | - | PASS | PASS | PASS | - | - |
7+
| 4.1 | - | - | PASS | PASS | PASS | PASS | - |
8+
| 4.2 | - | - | PASS | PASS | PASS | PASS | FAIL |
9+
| 5.0 | - | - | - | - | PASS | PASS | PASS |
10+
11+
## Test Results Explanation
12+
13+
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.
14+
15+
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.
16+
17+
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.sh

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
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

django_compatible.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"schemaVersion": 1,
3+
"label": "django",
4+
"message": "3.2,3.2,3.2,4.0,4.1,4.2,3.2,4.0,4.1,4.2,3.2,4.0,4.1,4.2,5.0,4.1,4.2,5.0,5.0",
5+
"color": "blue"
6+
}

python_compatible.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"schemaVersion": 1,
3+
"label": "python",
4+
"message": "3.6,3.7,3.8,3.8,3.8,3.8,3.9,3.9,3.9,3.9,3.10,3.10,3.10,3.10,3.10,3.11,3.11,3.11,3.12",
5+
"color": "blue"
6+
}

requirements-test.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
Pillow==10.2.0
2+
phonenumbers==8.13.32
3+
django-phonenumber-field==7.3.0
4+
babel==2.14.0
5+
setuptools==69.2.0
6+
pytz~=2024.1
7+
requests~=2.31.0
8+
django-q2==1.6.2
9+
python-dotenv==1.0.1

0 commit comments

Comments
 (0)