Skip to content

Commit 9312b9d

Browse files
authored
Add musl/alpine support (#1634)
1 parent aa26c8d commit 9312b9d

7 files changed

Lines changed: 203 additions & 5 deletions

File tree

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Alpine package smoke test
2+
description: Install a local or published temporalio package in Alpine and run a minimal SDK workflow.
3+
inputs:
4+
wheel-dir:
5+
description: "Directory containing local wheel files to install"
6+
required: false
7+
default: ""
8+
version:
9+
description: "Published package version to install and verify"
10+
required: false
11+
default: ""
12+
index-url:
13+
description: "Primary package index URL for published package installs"
14+
required: false
15+
default: ""
16+
dependency-index-url:
17+
description: "Optional dependency package index URL for published package installs"
18+
required: false
19+
default: ""
20+
python-image:
21+
description: "Alpine Python Docker image"
22+
required: false
23+
default: "python:3.10-alpine"
24+
runs:
25+
using: composite
26+
steps:
27+
- name: Install package and run SDK smoke test
28+
shell: bash
29+
env:
30+
WHEEL_DIR: ${{ inputs.wheel-dir }}
31+
VERSION: ${{ inputs.version }}
32+
INDEX_URL: ${{ inputs.index-url }}
33+
DEPENDENCY_INDEX_URL: ${{ inputs.dependency-index-url }}
34+
PYTHON_IMAGE: ${{ inputs.python-image }}
35+
run: |
36+
set -euo pipefail
37+
38+
if [[ -z "$WHEEL_DIR" && ( -z "$VERSION" || -z "$INDEX_URL" ) ]]; then
39+
echo "Either wheel-dir or both version and index-url must be provided" >&2
40+
exit 1
41+
fi
42+
43+
docker run --rm -v "$(pwd):/workspace" -w /tmp \
44+
-e WHEEL_DIR="$WHEEL_DIR" \
45+
-e VERSION="$VERSION" \
46+
-e INDEX_URL="$INDEX_URL" \
47+
-e DEPENDENCY_INDEX_URL="$DEPENDENCY_INDEX_URL" \
48+
"$PYTHON_IMAGE" sh -c '
49+
set -eu
50+
python -m venv /tmp/alpine-smoke
51+
/tmp/alpine-smoke/bin/python -m pip install --upgrade pip
52+
53+
if [ -n "$WHEEL_DIR" ]; then
54+
/tmp/alpine-smoke/bin/python -m pip install --prefer-binary /workspace/$WHEEL_DIR/*.whl
55+
elif [ -n "$DEPENDENCY_INDEX_URL" ]; then
56+
/tmp/alpine-smoke/bin/python /workspace/.github/scripts/install_release_package.py \
57+
--version "$VERSION" \
58+
--index-url "$INDEX_URL" \
59+
--dependency-index-url "$DEPENDENCY_INDEX_URL"
60+
else
61+
/tmp/alpine-smoke/bin/python /workspace/.github/scripts/install_release_package.py \
62+
--version "$VERSION" \
63+
--index-url "$INDEX_URL"
64+
fi
65+
66+
if [ -z "$VERSION" ]; then
67+
VERSION=$(/tmp/alpine-smoke/bin/python -c "import importlib.metadata; print(importlib.metadata.version(\"temporalio\"))")
68+
export VERSION
69+
fi
70+
71+
/tmp/alpine-smoke/bin/python /workspace/.github/scripts/release_smoke_package.py
72+
'

.github/scripts/release_verify.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ def verify_dist(args: argparse.Namespace) -> None:
7575
expected_sdist = f"temporalio-{args.version}.tar.gz"
7676
if sdists != [expected_sdist]:
7777
raise RuntimeError(f"Expected only sdist {expected_sdist!r}, found {sdists!r}")
78-
if len(wheels) != 5:
78+
if len(wheels) != 7:
7979
raise RuntimeError(
80-
f"Expected 5 platform wheels, found {len(wheels)}: {wheels!r}"
80+
f"Expected 7 platform wheels, found {len(wheels)}: {wheels!r}"
8181
)
8282

8383
for name in files:
@@ -90,6 +90,8 @@ def verify_dist(args: argparse.Namespace) -> None:
9090
expected_platforms = {
9191
"linux-x86_64": lambda name: "manylinux" in name and "x86_64" in name,
9292
"linux-aarch64": lambda name: "manylinux" in name and "aarch64" in name,
93+
"linux-musl-x86_64": lambda name: "musllinux" in name and "x86_64" in name,
94+
"linux-musl-aarch64": lambda name: "musllinux" in name and "aarch64" in name,
9395
"macos-x86_64": lambda name: "macosx" in name and "x86_64" in name,
9496
"macos-arm64": lambda name: "macosx" in name and "arm64" in name,
9597
"windows-amd64": lambda name: "win_amd64" in name,

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,35 @@ jobs:
100100
npx doctoc README.md
101101
[[ -z $(git status --porcelain README.md) ]] || (git diff README.md; echo "README changed"; exit 1)
102102
103+
alpine-package-test:
104+
timeout-minutes: 60
105+
strategy:
106+
fail-fast: false
107+
matrix:
108+
include:
109+
- cibw-build: cp310-musllinux_x86_64
110+
runsOn: ubuntu-latest
111+
- cibw-build: cp310-musllinux_aarch64
112+
runsOn: ubuntu-24.04-arm64-2-core
113+
runs-on: ${{ matrix.runsOn }}
114+
steps:
115+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
116+
with:
117+
submodules: recursive
118+
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
119+
with:
120+
python-version: "3.14"
121+
- uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
122+
- run: uv sync --all-extras
123+
- name: Build Alpine wheel
124+
run: uv run cibuildwheel --output-dir dist
125+
env:
126+
CIBW_BUILD: ${{ matrix.cibw-build }}
127+
- name: Test Alpine wheel
128+
uses: ./.github/actions/alpine-package-smoke
129+
with:
130+
wheel-dir: dist
131+
103132
check-protos:
104133
timeout-minutes: 30
105134
runs-on: ubuntu-latest

.github/workflows/release-publish.yml

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,29 @@ jobs:
2020
include:
2121
- os: ubuntu-latest
2222
package-suffix: linux-amd64
23+
cibw-build: cp310-manylinux_x86_64
2324
- os: ubuntu-arm
2425
package-suffix: linux-aarch64
26+
cibw-build: cp310-manylinux_aarch64
27+
runsOn: ubuntu-24.04-arm64-2-core
28+
- os: ubuntu-latest
29+
package-suffix: linux-musl-amd64
30+
cibw-build: cp310-musllinux_x86_64
31+
- os: ubuntu-arm
32+
package-suffix: linux-musl-aarch64
33+
cibw-build: cp310-musllinux_aarch64
2534
runsOn: ubuntu-24.04-arm64-2-core
2635
- os: macos-intel
2736
package-suffix: macos-amd64
37+
cibw-build: cp310-macosx_x86_64
2838
runsOn: macos-15-intel
2939
- os: macos-arm
3040
package-suffix: macos-aarch64
41+
cibw-build: cp310-macosx_arm64
3142
runsOn: macos-14
3243
- os: windows-latest
3344
package-suffix: windows-amd64
45+
cibw-build: cp310-win_amd64
3446
runs-on: ${{ matrix.runsOn || matrix.os }}
3547
permissions:
3648
contents: read
@@ -63,9 +75,12 @@ jobs:
6375

6476
# Build the wheel
6577
- run: uv run cibuildwheel --output-dir dist
78+
env:
79+
CIBW_BUILD: ${{ matrix.cibw-build }}
6680

6781
# Install the wheel in a new venv and run a test
6882
- name: Test wheel
83+
if: ${{ !contains(matrix.package-suffix, 'musl') }}
6984
shell: bash
7085
run: |
7186
mkdir __test_wheel__
@@ -80,6 +95,12 @@ jobs:
8095
./.venv/$bindir/pip install --prefer-binary ../dist/*.whl
8196
./.venv/$bindir/python -m pytest -s tests/worker/test_workflow.py -k test_workflow_hello
8297
98+
- name: Test Alpine wheel
99+
if: ${{ contains(matrix.package-suffix, 'musl') }}
100+
uses: ./.github/actions/alpine-package-smoke
101+
with:
102+
wheel-dir: dist
103+
83104
# Upload dist
84105
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
85106
with:
@@ -200,11 +221,36 @@ jobs:
200221
index-url: https://test.pypi.org/simple/
201222
dependency-index-url: https://pypi.org/simple/
202223

224+
smoke_testpypi_alpine:
225+
name: Smoke test TestPyPI package on Alpine (${{ matrix.arch }})
226+
needs:
227+
- verify_artifacts
228+
- publish_testpypi
229+
strategy:
230+
fail-fast: false
231+
matrix:
232+
include:
233+
- arch: x64
234+
runsOn: ubuntu-latest
235+
- arch: arm64
236+
runsOn: ubuntu-24.04-arm64-2-core
237+
runs-on: ${{ matrix.runsOn }}
238+
timeout-minutes: 10
239+
steps:
240+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
241+
- name: Install and load package
242+
uses: ./.github/actions/alpine-package-smoke
243+
with:
244+
version: ${{ needs.verify_artifacts.outputs.version }}
245+
index-url: https://test.pypi.org/simple/
246+
dependency-index-url: https://pypi.org/simple/
247+
203248
publish_pypi:
204249
name: Publish to PyPI
205250
needs:
206251
- verify_artifacts
207252
- smoke_testpypi
253+
- smoke_testpypi_alpine
208254
runs-on: ubuntu-latest
209255
timeout-minutes: 10
210256
environment: pypi
@@ -247,11 +293,35 @@ jobs:
247293
version: ${{ needs.verify_artifacts.outputs.version }}
248294
index-url: https://pypi.org/simple/
249295

296+
smoke_pypi_alpine:
297+
name: Smoke test PyPI package on Alpine (${{ matrix.arch }})
298+
needs:
299+
- verify_artifacts
300+
- publish_pypi
301+
strategy:
302+
fail-fast: false
303+
matrix:
304+
include:
305+
- arch: x64
306+
runsOn: ubuntu-latest
307+
- arch: arm64
308+
runsOn: ubuntu-24.04-arm64-2-core
309+
runs-on: ${{ matrix.runsOn }}
310+
timeout-minutes: 10
311+
steps:
312+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
313+
- name: Install and load package
314+
uses: ./.github/actions/alpine-package-smoke
315+
with:
316+
version: ${{ needs.verify_artifacts.outputs.version }}
317+
index-url: https://pypi.org/simple/
318+
250319
create_draft_release:
251320
name: Create draft GitHub Release
252321
needs:
253322
- verify_artifacts
254323
- smoke_pypi
324+
- smoke_pypi_alpine
255325
runs-on: ubuntu-latest
256326
timeout-minutes: 5
257327
permissions:

pyproject.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,21 @@ filterwarnings = [
153153

154154
[tool.cibuildwheel]
155155
before-all = "pip install protoc-wheel-0"
156-
build = "cp310-win_amd64 cp310-manylinux_x86_64 cp310-manylinux_aarch64 cp310-macosx_x86_64 cp310-macosx_arm64"
156+
build = "cp310-win_amd64 cp310-manylinux_x86_64 cp310-manylinux_aarch64 cp310-musllinux_x86_64 cp310-musllinux_aarch64 cp310-macosx_x86_64 cp310-macosx_arm64"
157157
build-verbosity = 1
158158

159159
[tool.cibuildwheel.macos]
160160
environment = { MACOSX_DEPLOYMENT_TARGET = "10.12" }
161161

162162
[tool.cibuildwheel.linux]
163-
before-all = "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y && yum install -y openssl-devel"
164-
before-build = "pip install protoc-wheel-0"
163+
before-all = "sh scripts/cibuildwheel_before_all_linux.sh"
164+
before-build = "sh scripts/cibuildwheel_before_build_linux.sh"
165165
environment = { PATH = "$PATH:$HOME/.cargo/bin", CARGO_NET_GIT_FETCH_WITH_CLI = "true" }
166166

167+
[[tool.cibuildwheel.overrides]]
168+
select = "*musllinux*"
169+
environment = { PATH = "$PATH:$HOME/.cargo/bin", CARGO_NET_GIT_FETCH_WITH_CLI = "true", RUSTFLAGS = "-C target-feature=-crt-static" }
170+
167171
[tool.mypy]
168172
ignore_missing_imports = true
169173
exclude = [
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
if command -v apk >/dev/null 2>&1; then
5+
apk add --no-cache build-base curl openssl-dev protobuf-dev
6+
elif command -v yum >/dev/null 2>&1; then
7+
yum install -y openssl-devel
8+
else
9+
echo "Unsupported Linux image: expected apk or yum" >&2
10+
exit 1
11+
fi
12+
13+
curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
if command -v protoc >/dev/null 2>&1; then
5+
protoc --version
6+
else
7+
pip install protoc-wheel-0
8+
fi

0 commit comments

Comments
 (0)