Skip to content

Commit ed5d30d

Browse files
authored
Refactor piwheels ARM32 verification workflow
1 parent e8910f4 commit ed5d30d

1 file changed

Lines changed: 110 additions & 97 deletions

File tree

.github/workflows/piwheels-arm32-verification.yml

Lines changed: 110 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,22 @@ jobs:
1717
verify-piwheels:
1818
name: Verify ARM32 on piwheels
1919
runs-on: ubuntu-latest
20-
20+
2121
steps:
2222
- name: Checkout
2323
uses: actions/checkout@v4
24-
24+
2525
- name: Set up Python
2626
uses: actions/setup-python@v5
2727
with:
2828
python-version: '3.11'
29-
29+
3030
- name: Wait for piwheels (if triggered by release)
3131
if: github.event_name == 'release'
3232
run: |
3333
echo "⏳ Waiting 24 hours for piwheels to build ARM32 wheels..."
34-
sleep 86400 # 24 hours
35-
34+
sleep 86400
35+
3636
- name: Get latest version
3737
id: version
3838
run: |
@@ -44,158 +44,174 @@ jobs:
4444
else
4545
VERSION=$(curl -s https://pypi.org/pypi/omnipkg/json | python3 -c "import sys, json; print(json.load(sys.stdin)['info']['version'])")
4646
fi
47-
4847
echo "version=$VERSION" >> $GITHUB_OUTPUT
4948
echo "Checking version: $VERSION"
50-
51-
- name: Scrape piwheels data
49+
50+
- name: Scrape piwheels simple index
5251
id: scrape
5352
run: |
5453
VERSION="${{ steps.version.outputs.version }}"
55-
56-
echo "🔍 Scraping piwheels for omnipkg $VERSION..."
57-
58-
# Fetch the project page
59-
RESPONSE=$(curl -s "https://www.piwheels.org/project/omnipkg/")
60-
61-
# Check if version exists
62-
if ! echo "$RESPONSE" | grep -q "$VERSION"; then
63-
echo "❌ Version $VERSION not found on piwheels yet"
54+
echo "🔍 Checking piwheels simple index for omnipkg $VERSION..."
55+
56+
# Use the simple index — same source pip uses, plain HTML, reliable
57+
SIMPLE_HTML=$(curl -s "https://www.piwheels.org/simple/omnipkg/")
58+
59+
if [ -z "$SIMPLE_HTML" ]; then
60+
echo "❌ Could not fetch piwheels simple index"
6461
echo "builds_found=false" >> $GITHUB_OUTPUT
6562
exit 0
6663
fi
67-
68-
echo "✅ Version $VERSION found on piwheels"
69-
70-
# Extract wheel filename (should be omnipkg-X.X.X-py3-none-any.whl)
71-
WHEEL_FILE=$(echo "$RESPONSE" | grep -oP "omnipkg-${VERSION}-py3-none-any\.whl" | head -1)
72-
73-
if [ -n "$WHEEL_FILE" ]; then
74-
WHEEL_URL="https://www.piwheels.org/simple/omnipkg/${WHEEL_FILE}"
75-
echo "✅ ARM32 wheel found: $WHEEL_URL"
76-
echo "builds_found=true" >> $GITHUB_OUTPUT
77-
echo "wheel_url=$WHEEL_URL" >> $GITHUB_OUTPUT
78-
echo "wheel_file=$WHEEL_FILE" >> $GITHUB_OUTPUT
79-
80-
# Extract supported Python versions from the releases table
81-
PYTHON_VERSIONS=""
82-
83-
# Check for Bullseye (Python 3.9)
84-
if echo "$RESPONSE" | grep -A 10 "$VERSION" | grep -q "Bullseye Python 3.9"; then
85-
PYTHON_VERSIONS="${PYTHON_VERSIONS}3.9, "
86-
fi
87-
88-
# Check for Bookworm (Python 3.11)
89-
if echo "$RESPONSE" | grep -A 10 "$VERSION" | grep -q "Bookworm Python 3.11"; then
90-
PYTHON_VERSIONS="${PYTHON_VERSIONS}3.11, "
91-
fi
92-
93-
# Check for Trixie (Python 3.13)
94-
if echo "$RESPONSE" | grep -A 10 "$VERSION" | grep -q "Trixie Python 3.13"; then
95-
PYTHON_VERSIONS="${PYTHON_VERSIONS}3.13, "
96-
fi
97-
98-
# Remove trailing comma and space
99-
PYTHON_VERSIONS=$(echo "$PYTHON_VERSIONS" | sed 's/, $//')
100-
101-
echo "python_versions=$PYTHON_VERSIONS" >> $GITHUB_OUTPUT
102-
echo "🐍 Python versions: $PYTHON_VERSIONS"
103-
104-
# Extract install command
105-
INSTALL_CMD="pip3 install omnipkg==${VERSION}"
106-
echo "install_command=$INSTALL_CMD" >> $GITHUB_OUTPUT
107-
else
108-
echo "❌ ARM32 wheel not found for version $VERSION"
64+
65+
# Extract all wheel filenames for this version from the simple index.
66+
# piwheels wheels are tagged like:
67+
# omnipkg-2.5.0-cp311-cp311-linux_armv6l.whl
68+
# omnipkg-2.5.0-cp313-cp313-linux_armv7l.whl
69+
# omnipkg-2.5.0-py3-none-any.whl (pure Python fallback, rare)
70+
# We want any wheel matching the version, on any cpython, on any armv* arch.
71+
WHEELS=$(echo "$SIMPLE_HTML" | grep -oP "omnipkg-${VERSION}-[^\"']+\.whl" | sort -u)
72+
73+
if [ -z "$WHEELS" ]; then
74+
echo "❌ No wheels found for version $VERSION on piwheels"
10975
echo "builds_found=false" >> $GITHUB_OUTPUT
76+
exit 0
11077
fi
111-
78+
79+
echo "Found wheels:"
80+
echo "$WHEELS"
81+
echo "builds_found=true" >> $GITHUB_OUTPUT
82+
83+
# --- Detect which Python versions have a successful build ---
84+
# Map CPython ABI tags to Debian release / Python version labels.
85+
# piwheels uses cp39 for Bullseye, cp311 for Bookworm, cp313 for Trixie.
86+
HAS_39=false
87+
HAS_311=false
88+
HAS_313=false
89+
90+
echo "$WHEELS" | grep -q "cp39" && HAS_39=true
91+
echo "$WHEELS" | grep -q "cp311" && HAS_311=true
92+
echo "$WHEELS" | grep -q "cp313" && HAS_313=true
93+
94+
# Build a human-readable list of confirmed Python versions
95+
PYTHON_VERSIONS=""
96+
$HAS_39 && PYTHON_VERSIONS="${PYTHON_VERSIONS}3.9 (Bullseye), "
97+
$HAS_311 && PYTHON_VERSIONS="${PYTHON_VERSIONS}3.11 (Bookworm), "
98+
$HAS_313 && PYTHON_VERSIONS="${PYTHON_VERSIONS}3.13 (Trixie), "
99+
PYTHON_VERSIONS="${PYTHON_VERSIONS%, }" # strip trailing ", "
100+
101+
echo "python_versions=$PYTHON_VERSIONS" >> $GITHUB_OUTPUT
102+
echo "has_cp39=$HAS_39" >> $GITHUB_OUTPUT
103+
echo "has_cp311=$HAS_311" >> $GITHUB_OUTPUT
104+
echo "has_cp313=$HAS_313" >> $GITHUB_OUTPUT
105+
echo "🐍 Python versions with ARM32 wheels: $PYTHON_VERSIONS"
106+
107+
# Pick a representative wheel URL for the README badge
108+
# Prefer armv7l > armv6l, prefer cp311 as most common Pi target
109+
BEST_WHEEL=""
110+
for ABI in cp311 cp313 cp39; do
111+
CANDIDATE=$(echo "$WHEELS" | grep "${ABI}-${ABI}-linux_armv7l" | head -1)
112+
if [ -z "$CANDIDATE" ]; then
113+
CANDIDATE=$(echo "$WHEELS" | grep "${ABI}-${ABI}-linux_armv6l" | head -1)
114+
fi
115+
if [ -n "$CANDIDATE" ]; then
116+
BEST_WHEEL="$CANDIDATE"
117+
break
118+
fi
119+
done
120+
# Fall back to whatever we found if the above loop found nothing
121+
[ -z "$BEST_WHEEL" ] && BEST_WHEEL=$(echo "$WHEELS" | head -1)
122+
123+
WHEEL_URL="https://www.piwheels.org/simple/omnipkg/${BEST_WHEEL}"
124+
echo "wheel_file=$BEST_WHEEL" >> $GITHUB_OUTPUT
125+
echo "wheel_url=$WHEEL_URL" >> $GITHUB_OUTPUT
126+
echo "install_command=pip3 install omnipkg==${VERSION}" >> $GITHUB_OUTPUT
127+
echo "✅ Representative wheel: $WHEEL_URL"
128+
112129
- name: Update README badges section
113130
if: steps.scrape.outputs.builds_found == 'true'
114131
run: |
115132
VERSION="${{ steps.version.outputs.version }}"
116133
PYTHON_VERS="${{ steps.scrape.outputs.python_versions }}"
117134
INSTALL_CMD="${{ steps.scrape.outputs.install_command }}"
118135
WHEEL_URL="${{ steps.scrape.outputs.wheel_url }}"
119-
120-
# Create the auto-update block for README
136+
121137
cat > .github/piwheels-stats.md <<'PIWHEELS_BLOCK'
122138
<!-- PIWHEELS_STATS_START -->
123139
## 🥧 ARM32 Support (Raspberry Pi)
124-
140+
125141
[![piwheels](https://img.shields.io/badge/piwheels-ARM32%20verified-97BF0D?logo=raspberrypi&logoColor=white)](https://www.piwheels.org/project/omnipkg/)
126-
142+
127143
**Latest Version:** `VERSION_PLACEHOLDER` | **Python:** PYTHON_VERS_PLACEHOLDER | [View on piwheels](https://www.piwheels.org/project/omnipkg/)
128-
144+
129145
```bash
130146
# Install on Raspberry Pi (ARM32)
131147
INSTALL_CMD_PLACEHOLDER
132148
```
133-
149+
134150
**Verified Platforms:**
135151
- 🍓 Raspberry Pi (armv6/armv7) - Bullseye (Debian 11), Bookworm (Debian 12), Trixie (Debian 13)
136152
- 📦 Wheel: [`WHEEL_URL_PLACEHOLDER`](WHEEL_URL_PLACEHOLDER)
137-
153+
138154
<!-- PIWHEELS_STATS_END -->
139155
PIWHEELS_BLOCK
140-
141-
# Replace placeholders
142-
sed -i "s|VERSION_PLACEHOLDER|${VERSION}|g" .github/piwheels-stats.md
156+
157+
sed -i "s|VERSION_PLACEHOLDER|${VERSION}|g" .github/piwheels-stats.md
143158
sed -i "s|PYTHON_VERS_PLACEHOLDER|${PYTHON_VERS}|g" .github/piwheels-stats.md
144159
sed -i "s|INSTALL_CMD_PLACEHOLDER|${INSTALL_CMD}|g" .github/piwheels-stats.md
145-
sed -i "s|WHEEL_URL_PLACEHOLDER|${WHEEL_URL}|g" .github/piwheels-stats.md
146-
147-
# Update README.md if the markers exist
160+
sed -i "s|WHEEL_URL_PLACEHOLDER|${WHEEL_URL}|g" .github/piwheels-stats.md
161+
148162
if grep -q "<!-- PIWHEELS_STATS_START -->" README.md; then
149-
# Use perl for cross-platform in-place editing
150163
perl -i -p0e 's/<!-- PIWHEELS_STATS_START -->.*?<!-- PIWHEELS_STATS_END -->//gs' README.md
151-
152-
# Insert new content after installation section
153164
sed -i '/#### 🥧 piwheels (for Raspberry Pi)/r .github/piwheels-stats.md' README.md
154165
fi
155-
166+
156167
- name: Generate platform support matrix
157168
if: steps.scrape.outputs.builds_found == 'true'
158169
run: |
159-
# This will be used to build the comprehensive platform table
160170
cat > .github/platform-matrix.json <<MATRIX_JSON
161171
{
162172
"arm32": {
163173
"verified": true,
164174
"version": "${{ steps.version.outputs.version }}",
165175
"python_versions": "${{ steps.scrape.outputs.python_versions }}",
176+
"cp39_bullseye": ${{ steps.scrape.outputs.has_cp39 }},
177+
"cp311_bookworm": ${{ steps.scrape.outputs.has_cp311 }},
178+
"cp313_trixie": ${{ steps.scrape.outputs.has_cp313 }},
166179
"install_command": "${{ steps.scrape.outputs.install_command }}",
167180
"platforms": ["Raspberry Pi", "Raspbian Bullseye", "Raspbian Bookworm", "Raspbian Trixie"]
168181
}
169182
}
170183
MATRIX_JSON
171-
172184
echo "✅ Platform matrix generated"
173-
185+
174186
- name: Commit changes
175187
if: steps.scrape.outputs.builds_found == 'true'
176188
run: |
177189
git config user.name "github-actions[bot]"
178190
git config user.email "github-actions[bot]@users.noreply.github.com"
179-
180191
git add README.md .github/piwheels-stats.md .github/platform-matrix.json || true
181-
182192
if ! git diff --staged --quiet; then
183193
git commit -m "Auto-update piwheels ARM32 stats for v${{ steps.version.outputs.version }} [skip ci]"
184194
git pull --rebase origin main
185195
git push
186196
else
187197
echo "No changes to commit"
188198
fi
189-
199+
190200
- name: Create verification summary
191201
if: steps.scrape.outputs.builds_found == 'true'
192202
run: |
203+
HAS_39="${{ steps.scrape.outputs.has_cp39 }}"
204+
HAS_311="${{ steps.scrape.outputs.has_cp311 }}"
205+
HAS_313="${{ steps.scrape.outputs.has_cp313 }}"
206+
tick() { [ "$1" == "true" ] && echo "✅" || echo "❌"; }
193207
{
194-
echo "## ✅ ARM32 Support Verified"
195-
echo ""
196-
echo "**Version:** \`${{ steps.version.outputs.version }}\`"
208+
echo "## ARM32 Wheel Check — v${{ steps.version.outputs.version }}"
197209
echo ""
198-
echo "**Architecture:** ARM32 (armv6/armv7) - Raspberry Pi compatible"
210+
echo "| Distro | Python | ARM32 wheel |"
211+
echo "|--------|--------|-------------|"
212+
echo "| Bullseye (Debian 11) | 3.9 | $(tick $HAS_39) |"
213+
echo "| Bookworm (Debian 12) | 3.11 | $(tick $HAS_311) |"
214+
echo "| Trixie (Debian 13) | 3.13 | $(tick $HAS_313) |"
199215
echo ""
200216
echo "**Python Versions:** ${{ steps.scrape.outputs.python_versions }}"
201217
echo ""
@@ -204,14 +220,11 @@ jobs:
204220
echo "${{ steps.scrape.outputs.install_command }}"
205221
echo "\`\`\`"
206222
echo ""
207-
echo "**Wheel URL:** [${{ steps.scrape.outputs.wheel_file }}](${{ steps.scrape.outputs.wheel_url }})"
208-
echo ""
209-
echo "**Verified on:**"
210-
echo "- 🍓 Bullseye (Debian 11) - Python 3.9"
211-
echo "- 🍓 Bookworm (Debian 12) - Python 3.11"
212-
echo "- 🍓 Trixie (Debian 13) - Python 3.13"
213-
echo ""
214-
echo "---"
215-
echo ""
216-
echo "This wheel is built and tested by [piwheels.org](https://www.piwheels.org/project/omnipkg/) on real Raspberry Pi hardware."
223+
echo "**Representative wheel:** [${{ steps.scrape.outputs.wheel_file }}](${{ steps.scrape.outputs.wheel_url }})"
217224
} >> $GITHUB_STEP_SUMMARY
225+
226+
- name: Fail if NO wheels exist at all
227+
if: steps.scrape.outputs.builds_found == 'false'
228+
run: |
229+
echo "❌ No ARM32 wheels found for omnipkg ${{ steps.version.outputs.version }} on piwheels"
230+
exit 1

0 commit comments

Comments
 (0)