1
+ name : Build Wheels (Docker Multi-Arch)
2
+
3
+ on :
4
+ # Build wheels on feature branches and PRs (test only)
5
+ push :
6
+ branches : ["**"]
7
+ pull_request :
8
+ branches : [master]
9
+
10
+ # Publish to GitHub Releases when merged to master
11
+ # Publish to PyPI when tagged
12
+ workflow_dispatch :
13
+
14
+ env :
15
+ # Registry for caching build images
16
+ REGISTRY : ghcr.io
17
+ IMAGE_NAME : ${{ github.repository }}/wheel-builder
18
+
19
+ jobs :
20
+ build-wheels :
21
+ name : Build wheels (${{ matrix.target.name }})
22
+ runs-on : ubuntu-latest
23
+ container : ${{ matrix.target.base_image }}
24
+
25
+ strategy :
26
+ fail-fast : false
27
+ matrix :
28
+ target :
29
+ # Debian 12 (your preference) - AMD64 only for now
30
+ - name : " debian12-amd64"
31
+ base_image : " debian:12"
32
+
33
+ # Rocky Linux 9 (customer requirement) - AMD64 only for now
34
+ - name : " rocky9-amd64"
35
+ base_image : " rockylinux:9"
36
+
37
+ # Ubuntu 24.04 (dev environment) - AMD64 only for now
38
+ - name : " ubuntu2404-amd64"
39
+ base_image : " ubuntu:24.04"
40
+
41
+ # ARM64 builds can be added later with QEMU setup
42
+ # GitHub Actions container: syntax doesn't support ARM64 QEMU easily
43
+
44
+ steps :
45
+ - name : Checkout code
46
+ uses : actions/checkout@v4
47
+
48
+ - name : Install system dependencies
49
+ run : |
50
+ if command -v apt-get >/dev/null 2>&1; then
51
+ # Debian/Ubuntu systems
52
+ apt-get update
53
+ apt-get install -y --no-install-recommends \
54
+ ca-certificates \
55
+ curl \
56
+ build-essential \
57
+ pkg-config \
58
+ libssl-dev \
59
+ libffi-dev \
60
+ zlib1g-dev \
61
+ libbz2-dev \
62
+ libreadline-dev \
63
+ libsqlite3-dev \
64
+ libncurses5-dev \
65
+ libsnappy-dev \
66
+ git \
67
+ file
68
+ elif command -v dnf >/dev/null 2>&1; then
69
+ # Rocky Linux/RHEL systems
70
+ dnf update -y
71
+ dnf groupinstall -y "Development Tools"
72
+ # Handle curl-minimal conflict in Rocky Linux
73
+ dnf install -y --allowerasing \
74
+ ca-certificates \
75
+ curl \
76
+ pkgconfig \
77
+ openssl-devel \
78
+ libffi-devel \
79
+ zlib-devel \
80
+ bzip2-devel \
81
+ readline-devel \
82
+ sqlite-devel \
83
+ ncurses-devel \
84
+ snappy-devel \
85
+ git \
86
+ file
87
+ fi
88
+
89
+ - name : Install Python
90
+ run : |
91
+ if command -v apt-get >/dev/null 2>&1; then
92
+ apt-get install -y --no-install-recommends python3 python3-pip python3-venv
93
+ elif command -v dnf >/dev/null 2>&1; then
94
+ dnf install -y python3 python3-pip
95
+ fi
96
+
97
+ - name : Install Just
98
+ run : |
99
+ curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
100
+ just --version
101
+
102
+ - name : Install uv
103
+ run : |
104
+ curl -LsSf https://astral.sh/uv/install.sh | sh
105
+ echo "/root/.cargo/bin" >> $GITHUB_PATH
106
+
107
+ - name : Install Rust
108
+ run : |
109
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
110
+ echo "/root/.cargo/bin" >> $GITHUB_PATH
111
+
112
+ - name : Verify toolchain
113
+ run : |
114
+ export PATH="/root/.cargo/bin:$PATH"
115
+ echo "==> Build environment summary:"
116
+ echo "Container: ${{ matrix.target.base_image }}"
117
+ echo "Just: $(just --version)"
118
+ echo "uv: $(uv --version)"
119
+ echo "Rust: $(rustc --version)"
120
+ echo "Python: $(python3 --version)"
121
+ echo "GCC: $(gcc --version | head -1)"
122
+ echo "glibc: $(ldd --version 2>/dev/null | head -1 || echo 'N/A')"
123
+
124
+ - name : Build wheels
125
+ run : |
126
+ export PATH="/root/.cargo/bin:$PATH"
127
+ just build-all
128
+
129
+ - name : Generate build metadata
130
+ run : |
131
+ mkdir -p dist/
132
+ cat > dist/build-info.txt << EOF
133
+ Build Information for ${{ matrix.target.name }}
134
+ =============================================
135
+
136
+ Build Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
137
+ Container: ${{ matrix.target.base_image }}
138
+ Platform: AMD64
139
+ Build Method: GitHub Actions + Docker Container
140
+
141
+ System Information:
142
+ - OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)
143
+ - Kernel: $(uname -r)
144
+ - glibc: $(ldd --version 2>/dev/null | head -1 || echo 'N/A')
145
+
146
+ Build Tools:
147
+ - Just: $(just --version)
148
+ - uv: $(uv --version)
149
+ - Rust: $(rustc --version)
150
+ - Python: $(python3 --version)
151
+ - GCC: $(gcc --version | head -1)
152
+ EOF
153
+
154
+ - name : List built artifacts
155
+ run : |
156
+ echo "==> Built artifacts for ${{ matrix.target.name }}:"
157
+ ls -la dist/ 2>/dev/null || echo "No dist/ directory found"
158
+
159
+ echo ""
160
+ echo "==> Build metadata:"
161
+ cat dist/build-info.txt 2>/dev/null || echo "No build info found"
162
+
163
+ echo ""
164
+ echo "==> Wheel inventory:"
165
+ find dist/ -name "*.whl" -exec basename {} \; 2>/dev/null | sort || echo "No wheels found"
166
+
167
+ - name : Upload wheel artifacts
168
+ uses : actions/upload-artifact@v4
169
+ with :
170
+ name : wheels-${{ matrix.target.name }}
171
+ path : |
172
+ dist/*.whl
173
+ dist/*.tar.gz
174
+ retention-days : 30
175
+
176
+ - name : Upload build metadata
177
+ uses : actions/upload-artifact@v4
178
+ if : always()
179
+ with :
180
+ name : build-info-${{ matrix.target.name }}
181
+ path : dist/build-info.txt
182
+ retention-days : 7
183
+ if-no-files-found : ignore
184
+
185
+ publish-github-releases :
186
+ name : Publish to GitHub Releases
187
+ needs : build-wheels
188
+ runs-on : ubuntu-latest
189
+ if : github.ref == 'refs/heads/master' && github.event_name == 'push'
190
+
191
+ steps :
192
+ - name : Download all wheel artifacts
193
+ uses : actions/download-artifact@v4
194
+ with :
195
+ pattern : wheels-*
196
+ merge-multiple : true
197
+ path : dist/
198
+
199
+ - name : Download build metadata
200
+ uses : actions/download-artifact@v4
201
+ with :
202
+ pattern : build-info-*
203
+ path : build-info/
204
+
205
+ - name : Analyze wheel inventory
206
+ id : inventory
207
+ run : |
208
+ echo "==> Complete wheel inventory:"
209
+ find dist/ -name "*.whl" | sort
210
+
211
+ echo ""
212
+ echo "==> Wheels by platform:"
213
+ for platform in debian12 rocky9 ubuntu2404; do
214
+ for arch in amd64 arm64; do
215
+ count=$(find dist/ -name "*${platform}*${arch}*.whl" | wc -l)
216
+ echo " $platform-$arch: $count wheels"
217
+ done
218
+ done
219
+
220
+ echo ""
221
+ echo "==> Total wheel count:"
222
+ WHEEL_COUNT=$(find dist/ -name "*.whl" | wc -l)
223
+ echo "wheels_total=$WHEEL_COUNT" >> $GITHUB_OUTPUT
224
+
225
+ echo ""
226
+ echo "==> Source distributions:"
227
+ find dist/ -name "*.tar.gz" | wc -l
228
+
229
+ - name : Create GitHub Release
230
+ env :
231
+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
232
+ run : |
233
+ # Generate release tag based on timestamp and commit
234
+ RELEASE_TAG="wheels-docker-$(date +'%Y%m%d')-${GITHUB_SHA::8}"
235
+
236
+ # Create comprehensive release notes
237
+ cat > release_notes.md << 'EOF'
238
+ # Multi-Architecture Python Wheels
239
+
240
+ Built using Docker QEMU emulation for precise ABI control and broad compatibility.
241
+
242
+ ## Target Environments
243
+
244
+ | Distribution | glibc Version | Architecture | Use Case |
245
+ |--------------|---------------|--------------|----------|
246
+ | **Debian 12** | 2.36 | AMD64, ARM64 | Modern Linux systems |
247
+ | **Rocky Linux 9** | 2.34 | AMD64, ARM64 | Enterprise RHEL environments |
248
+ | **Ubuntu 24.04** | 2.39 | AMD64, ARM64 | Latest Ubuntu LTS |
249
+
250
+ ## Python Support
251
+
252
+ - **CPython**: 3.11, 3.12, 3.13, 3.14
253
+ - **PyPy**: 3.11
254
+ - **Extensions**: Native CFFI modules included
255
+
256
+ ## Installation
257
+
258
+ ### Option 1: Auto-detect (pip will choose best wheel)
259
+ ```bash
260
+ pip install autobahn[all]
261
+ ```
262
+
263
+ ### Option 2: Specific wheel download
264
+ ```bash
265
+ # Download the wheel for your platform
266
+ wget https://github.com/crossbario/autobahn-python/releases/download/${RELEASE_TAG}/autobahn-*-linux_*.whl
267
+ pip install autobahn-*-linux_*.whl
268
+ ```
269
+
270
+ ## Build Information
271
+
272
+ - **Build Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
273
+ - **Commit**: ${GITHUB_SHA::8}
274
+ - **Total Wheels**: ${{ steps.inventory.outputs.wheels_total }}
275
+ - **Build Method**: Docker + QEMU emulation
276
+ - **ABI**: Precise glibc targeting per distribution
277
+
278
+ EOF
279
+
280
+ # Create release
281
+ gh release create "$RELEASE_TAG" \
282
+ --repo "$GITHUB_REPOSITORY" \
283
+ --title "Multi-Arch Wheels - $(date +'%Y-%m-%d')" \
284
+ --notes-file release_notes.md \
285
+ dist/*.whl dist/*.tar.gz
286
+
287
+ publish-pypi :
288
+ name : Publish to PyPI
289
+ needs : build-wheels
290
+ runs-on : ubuntu-latest
291
+ if : startsWith(github.ref, 'refs/tags/')
292
+ environment :
293
+ name : pypi
294
+ url : https://pypi.org/p/autobahn
295
+ permissions :
296
+ id-token : write # For trusted publishing
297
+
298
+ steps :
299
+ - name : Download all wheel artifacts
300
+ uses : actions/download-artifact@v4
301
+ with :
302
+ pattern : wheels-*
303
+ merge-multiple : true
304
+ path : dist/
305
+
306
+ - name : Prepare PyPI upload
307
+ run : |
308
+ echo "==> Preparing PyPI upload..."
309
+
310
+ # Remove duplicate source distributions (keep only one)
311
+ find dist/ -name "*.tar.gz" | sort | tail -n +2 | xargs rm -f || true
312
+
313
+ echo "==> Final PyPI artifact list:"
314
+ ls -la dist/
315
+
316
+ echo ""
317
+ echo "==> Upload summary:"
318
+ echo "Wheels: $(find dist/ -name "*.whl" | wc -l)"
319
+ echo "Source: $(find dist/ -name "*.tar.gz" | wc -l)"
320
+
321
+ - name : Publish to PyPI
322
+ uses : pypa/gh-action-pypi-publish@release/v1
323
+ with :
324
+ verbose : true
0 commit comments