Skip to content

Commit 4ac4940

Browse files
committed
Improve Python version detection with smart three-tier system in CI workflow
1 parent 5533962 commit 4ac4940

File tree

4 files changed

+166
-68
lines changed

4 files changed

+166
-68
lines changed

.github/workflows/python-test.yml

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
- name: Detect Versions to Test
3636
id: detect
3737
run: |
38-
echo "=== Detecting Python Versions to Test ==="
38+
echo "=== Smart Version Detection for Pull Request Testing ==="
3939
4040
# Initialize versions array
4141
VERSIONS="[]"
@@ -51,56 +51,61 @@ jobs:
5151
exit 0
5252
fi
5353
54-
# For pull requests, detect versions from pre-release files
54+
# For pull requests, use smart detection
5555
if [ "${{ github.event_name }}" = "pull_request" ]; then
56-
echo "Pull request detected, checking for pre-release files..."
56+
echo "Pull request detected - using smart version detection"
57+
echo ""
5758
5859
# Get changed files in the PR
5960
CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
60-
echo "Changed files:"
61+
echo "Changed files in PR:"
6162
echo "$CHANGED_FILES"
63+
echo ""
6264
63-
# Look for pre-release files (e.g., bearsampp-python-3.13.5-2025.8.21.7z)
64-
PRERELEASE_FILES=$(echo "$CHANGED_FILES" | grep -E 'bearsampp-python-[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?(-[a-z0-9]+)?-[0-9]+\.[0-9]+\.[0-9]+\.7z' || true)
65+
# PRIMARY METHOD: Extract versions from /bin directory changes
66+
echo "🔍 Primary Method: Checking /bin directory for version changes..."
67+
BIN_CHANGES=$(echo "$CHANGED_FILES" | grep -E '^bin/python[0-9]+\.[0-9]+\.[0-9]+' || true)
6568
66-
if [ -n "$PRERELEASE_FILES" ]; then
67-
echo "✅ Found pre-release files:"
68-
echo "$PRERELEASE_FILES"
69+
if [ -n "$BIN_CHANGES" ]; then
70+
echo "✅ Found changes in /bin directory:"
71+
echo "$BIN_CHANGES"
72+
echo ""
6973
70-
# Extract version numbers from pre-release filenames
74+
# Extract version numbers from bin directory names (e.g., bin/python3.19.1/ -> 3.19.1)
7175
DETECTED_VERSIONS=""
7276
while IFS= read -r file; do
73-
# Extract version from filename (e.g., bearsampp-python-3.13.5-2025.8.21.7z -> 3.13.5)
74-
VERSION=$(echo "$file" | grep -oE 'python-[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?(-[a-z0-9]+)?' | sed 's/python-//')
77+
VERSION=$(echo "$file" | grep -oE 'python[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?' | sed 's/python//')
7578
if [ -n "$VERSION" ]; then
76-
echo " Detected version: $VERSION from $file"
79+
echo " 📦 Detected version: $VERSION from $file"
7780
DETECTED_VERSIONS="$DETECTED_VERSIONS $VERSION"
7881
fi
79-
done <<< "$PRERELEASE_FILES"
82+
done <<< "$BIN_CHANGES"
8083
81-
# Verify these versions exist in releases.properties
84+
# Remove duplicates and verify versions exist in releases.properties
8285
VALID_VERSIONS=""
83-
for version in $DETECTED_VERSIONS; do
84-
if grep -q "^${version}" releases.properties; then
85-
echo "✅ Version $version exists in releases.properties"
86+
for version in $(echo "$DETECTED_VERSIONS" | tr ' ' '\n' | sort -u); do
87+
if [ -n "$version" ] && grep -q "^${version}" releases.properties; then
88+
echo " ✅ Version $version confirmed in releases.properties"
8689
VALID_VERSIONS="$VALID_VERSIONS $version"
8790
HAS_CHANGES="true"
8891
else
89-
echo "⚠️ Version $version not found in releases.properties"
92+
echo " ⚠️ Version $version not found in releases.properties (will skip)"
9093
fi
9194
done
9295
9396
if [ -n "$VALID_VERSIONS" ]; then
9497
VERSIONS=$(echo "$VALID_VERSIONS" | tr ' ' '\n' | grep -v '^$' | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))')
95-
echo "Valid versions to test from pre-release files: $VERSIONS"
98+
echo ""
99+
echo "✅ Primary method successful - versions to test: $VERSIONS"
96100
fi
97101
else
98-
echo "ℹ️ No pre-release files found in PR"
102+
echo "ℹ️ No changes detected in /bin directory"
99103
fi
100104
101-
# Fallback: Check PR title for version numbers if no pre-release files found
105+
# FALLBACK METHOD: Check PR title for version numbers
102106
if [ "$HAS_CHANGES" = "false" ]; then
103-
echo "Checking PR title for version numbers as fallback..."
107+
echo ""
108+
echo "🔍 Fallback Method: Checking PR title for version numbers..."
104109
PR_TITLE="${{ github.event.pull_request.title }}"
105110
echo "PR Title: $PR_TITLE"
106111
@@ -114,24 +119,42 @@ jobs:
114119
VALID_VERSIONS=""
115120
for version in $TITLE_VERSIONS; do
116121
if grep -q "^${version}" releases.properties; then
117-
echo "✅ Version $version exists in releases.properties"
122+
echo " ✅ Version $version confirmed in releases.properties"
118123
VALID_VERSIONS="$VALID_VERSIONS $version"
119124
HAS_CHANGES="true"
120125
else
121-
echo "⚠️ Version $version not found in releases.properties"
126+
echo " ⚠️ Version $version not found in releases.properties"
122127
fi
123128
done
124129
125130
if [ -n "$VALID_VERSIONS" ]; then
126131
VERSIONS=$(echo "$VALID_VERSIONS" | tr ' ' '\n' | grep -v '^$' | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))')
127-
echo "Valid versions to test from PR title: $VERSIONS"
132+
echo ""
133+
echo "✅ Fallback method successful - versions to test: $VERSIONS"
128134
fi
129135
else
130-
echo "ℹ️ No version numbers found in PR title"
136+
echo "ℹ️ No version numbers found in PR title"
137+
fi
138+
fi
139+
140+
# FINAL FALLBACK: Test latest 5 versions if no versions detected
141+
if [ "$HAS_CHANGES" = "false" ]; then
142+
echo ""
143+
echo "🔍 Final Fallback: No versions detected, testing latest 5 versions..."
144+
LATEST_VERSIONS=$(grep -E "^[0-9]" releases.properties | cut -d'=' -f1 | tr -d ' ' | head -n 5)
145+
146+
if [ -n "$LATEST_VERSIONS" ]; then
147+
VERSIONS=$(echo "$LATEST_VERSIONS" | jq -R -s -c 'split("\n") | map(select(length > 0))')
148+
HAS_CHANGES="true"
149+
echo "✅ Testing latest 5 versions: $VERSIONS"
150+
else
151+
echo "⚠️ No versions found in releases.properties"
152+
VERSIONS="[]"
153+
HAS_CHANGES="false"
131154
fi
132155
fi
133156
else
134-
# For push events, test only the latest version (first line in releases.properties)
157+
# For push events, test only the latest version
135158
echo "Push event detected, testing latest version only"
136159
HAS_CHANGES="true"
137160
LATEST_VERSION=$(grep -E "^[0-9]" releases.properties | cut -d'=' -f1 | tr -d ' ' | head -n 1)
@@ -145,8 +168,11 @@ jobs:
145168
fi
146169
fi
147170
171+
echo ""
172+
echo "=========================================="
148173
echo "Final versions to test: $VERSIONS"
149174
echo "Has changes: $HAS_CHANGES"
175+
echo "=========================================="
150176
151177
echo "versions=$VERSIONS" >> $GITHUB_OUTPUT
152178
echo "has-changes=$HAS_CHANGES" >> $GITHUB_OUTPUT
@@ -542,16 +568,18 @@ jobs:
542568
if [ "$TEST_STATUS" = "skipped" ] || [ "$VERSIONS" = "[]" ]; then
543569
echo "**Status:** ⏭️ Tests skipped - no versions to test" >> comment.md
544570
echo "" >> comment.md
545-
echo "ℹ️ **Why were tests skipped?**" >> comment.md
571+
echo "ℹ️ **Smart Version Detection**" >> comment.md
572+
echo "" >> comment.md
573+
echo "This workflow uses intelligent three-tier detection:" >> comment.md
546574
echo "" >> comment.md
547-
echo "Tests are only run when:" >> comment.md
548-
echo "- PR includes pre-release files (e.g., \`bearsampp-python-3.13.5-2025.8.21.7z\`), OR" >> comment.md
549-
echo "- PR title contains version numbers (e.g., \"3.13.5\", \"3.12.9\") as fallback" >> comment.md
575+
echo "1. **Primary Method**: Detects versions from \`/bin/pythonX.X.X/\` directory changes" >> comment.md
576+
echo "2. **Fallback Method**: Extracts versions from PR title (e.g., \"3.13.5\", \"3.12.9\")" >> comment.md
577+
echo "3. **Final Fallback**: Tests latest 5 versions if no versions detected" >> comment.md
550578
echo "" >> comment.md
551579
echo "**To trigger tests:**" >> comment.md
552-
echo "1. Add pre-release .7z files to your PR, OR" >> comment.md
553-
echo "2. Add version numbers to your PR title (e.g., \"Update Python 3.13.5\"), OR" >> comment.md
554-
echo "3. Manually trigger the workflow from the Actions tab" >> comment.md
580+
echo "- Add changes to \`/bin/pythonX.X.X/\` directories, OR" >> comment.md
581+
echo "- Add version numbers to your PR title (e.g., \"Update Python 3.13.5\"), OR" >> comment.md
582+
echo "- Manually trigger the workflow from the Actions tab" >> comment.md
555583
elif [ "$TEST_STATUS" = "success" ]; then
556584
echo "**Status:** ✅ All tests passed" >> comment.md
557585
elif [ "$TEST_STATUS" = "failure" ]; then

.settings/org.eclipse.core.resources.prefs

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 103 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ This directory contains GitHub Actions workflows for automated testing.
66

77
### python-test.yml
88

9-
Automated testing workflow for Python modules that:
9+
Automated testing workflow for Python modules with **Smart Version Detection** that:
1010

11-
1. **Detects versions to test** based on:
12-
- Pre-release files in PR (e.g., `bearsampp-python-3.13.5-2025.8.21.7z`)
13-
- Version numbers in PR titles (fallback)
14-
- Manual workflow dispatch with specific version
11+
1. **Intelligently detects versions to test** using a three-tier approach:
12+
- **Primary Method**: Extracts version numbers from changed files in `/bin` directory (e.g., `bin/python3.19.1/`)
13+
- **Fallback Method**: Extracts version numbers from PR title if no `/bin` changes detected
14+
- **Final Fallback**: Tests the latest 5 versions if no versions detected by either method
1515

1616
2. **Tests each Python version** through multiple phases:
1717
- **Phase 1.1**: Download and extract Python module
@@ -23,16 +23,99 @@ Automated testing workflow for Python modules that:
2323
- Comments on pull requests
2424
- Uploads test artifacts
2525

26+
## Smart Version Detection
27+
28+
The workflow uses an intelligent three-tier detection system to identify which Python versions need testing:
29+
30+
### How It Works
31+
32+
When a PR is created from a pre-release branch (e.g., "November") to main:
33+
34+
1. **New versions are created** and added to a pre-release (tagged with date, e.g., "2025.11.23")
35+
2. **Version directories are created** in `/bin` (e.g., `bin/python3.19.1/`, `bin/python3.25.0/`)
36+
3. **The releases.properties file is updated** via the releases.properties workflow
37+
4. **A PR is created** from the release branch to main
38+
5. **This workflow detects changed files** in `/bin` and extracts version numbers from directory names
39+
6. **Tests are run** against the version(s) found in releases.properties from that PR branch
40+
41+
### Typical Workflow Process
42+
43+
Here's how the smart detection works in a typical release workflow:
44+
45+
1. **Pre-release Creation**: New Python versions (e.g., 3.19.1, 3.25.0) are added to a pre-release tagged with the date (e.g., "2025.11.23")
46+
47+
2. **Directory Structure**: Version directories are created in `/bin`:
48+
```
49+
bin/
50+
├── python3.19.1/
51+
│ └── (version files)
52+
└── python3.25.0/
53+
└── (version files)
54+
```
55+
56+
3. **Properties Update**: The `releases.properties` file is updated via the update-releases-properties workflow
57+
58+
4. **PR Creation**: A PR is created from a release branch (e.g., "November") to main
59+
60+
5. **Smart Detection**: The workflow automatically:
61+
- Scans changed files in the PR
62+
- Detects `bin/python3.19.1/` and `bin/python3.25.0/`
63+
- Extracts versions: `3.19.1` and `3.25.0`
64+
- Verifies these versions exist in `releases.properties`
65+
- Runs tests only for these 2 versions (not all versions)
66+
67+
6. **Efficiency**: Instead of testing 20+ versions, only the 2 new versions are tested, reducing CI time from 30+ minutes to ~10-20 minutes
68+
69+
### Detection Methods
70+
71+
#### 🥇 Primary Method: /bin Directory Detection
72+
73+
The workflow scans for changes in the `/bin` directory and extracts version numbers from directory names:
74+
75+
```
76+
bin/python3.19.1/some-file.txt → Detects version: 3.19.1
77+
bin/python3.25.0/another.txt → Detects version: 3.25.0
78+
```
79+
80+
**Advantages:**
81+
- Most accurate - directly tied to actual version changes
82+
- Reduces CI runtime by testing only relevant versions
83+
- Automatically handles multiple versions in a single PR
84+
85+
#### 🥈 Fallback Method: PR Title Detection
86+
87+
If no `/bin` changes are detected, the workflow extracts version numbers from the PR title:
88+
89+
```
90+
"Add Python 3.13.5 support" → Detects version: 3.13.5
91+
"Update 3.12.9 and 3.13.3" → Detects versions: 3.12.9, 3.13.3
92+
```
93+
94+
**Use cases:**
95+
- Documentation updates mentioning specific versions
96+
- Configuration changes for specific versions
97+
- Manual testing requests
98+
99+
#### 🥉 Final Fallback: Latest 5 Versions
100+
101+
If no versions are detected by either method, the workflow tests the latest 5 versions from releases.properties:
102+
103+
**Use cases:**
104+
- General infrastructure changes
105+
- Workflow updates
106+
- Changes that might affect all versions
107+
26108
## Triggering Tests
27109

28110
### Automatic Triggers
29111

30112
Tests run automatically when:
31113

32114
- **Push to main**: Tests latest version only
33-
- **Pull Request with pre-release files**: Tests versions detected from `.7z` filenames
34-
- **Pull Request with version in title**: Tests versions mentioned in PR title (fallback)
35-
- **Manual workflow dispatch**: Tests specified version or all versions
115+
- **Pull Request with /bin changes**: Tests versions detected from `/bin/pythonX.X.X/` directory names (Primary Method)
116+
- **Pull Request with version in title**: Tests versions mentioned in PR title (Fallback Method)
117+
- **Pull Request with other changes**: Tests latest 5 versions (Final Fallback)
118+
- **Manual workflow dispatch**: Tests specified version
36119

37120
### Manual Trigger
38121

@@ -41,16 +124,24 @@ You can manually trigger tests:
41124
1. Go to the Actions tab
42125
2. Select "Python Module Tests"
43126
3. Click "Run workflow"
44-
4. Optionally specify a version to test
127+
4. Optionally specify a version to test (e.g., `3.13.5`)
45128

46-
### PR Title Format
129+
### PR Title Format (Fallback Method)
47130

48-
To test specific versions in a PR, include version numbers in the title:
131+
If your PR doesn't include `/bin` directory changes, you can trigger tests by including version numbers in the PR title:
49132

50133
-`Add Python 3.13.5 support`
51134
-`Update docs for 3.12.9`
52135
-`Fix issue with Python 3.13.3 and 3.12.6.0`
53-
-`Update documentation` (no version, won't trigger tests unless releases.properties changed)
136+
-`Documentation update` (will test latest 5 versions as final fallback)
137+
138+
### Efficiency Benefits
139+
140+
The smart detection system significantly reduces CI runtime:
141+
142+
- **Before**: All versions tested on every PR (~30+ minutes)
143+
- **After**: Only relevant versions tested (~5-10 minutes per version)
144+
- **Example**: PR with 2 new versions = ~10-20 minutes instead of 30+ minutes
54145

55146
## Test Phases
56147

module-python.RELEASE.launch

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)