Skip to content

Commit 85fa659

Browse files
committed
fix(ci): avoid Metal wheel artifact collisions
Build one py3-none Metal wheel and download its artifact by name so two macOS jobs cannot write different wheels to the same release path. Verify the wheel ZIP before artifact upload and before release. Assisted-by: OpenAI Codex Signed-off-by: Haozhe Jiang <162801044+provoke210@users.noreply.github.com>
1 parent 1652066 commit 85fa659

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

‎.github/workflows/build-wheels-metal.yaml‎

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ permissions:
77

88
jobs:
99
build_wheels:
10-
name: Build wheels on ${{ matrix.os }}
11-
runs-on: ${{ matrix.os }}
12-
strategy:
13-
matrix:
14-
os: [macos-14, macos-15]
10+
# Two runners produced the same py3-none wheel filename, which collided
11+
# when their artifacts were downloaded into one release directory.
12+
name: Build wheels on macos-14
13+
runs-on: macos-14
1514

1615
steps:
1716
- uses: actions/checkout@v6
@@ -38,14 +37,18 @@ jobs:
3837
CIBW_REPAIR_WHEEL_COMMAND: ""
3938
CIBW_ARCHS: "arm64"
4039
CIBW_ENVIRONMENT: CMAKE_ARGS="-DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_APPLE_SILICON_PROCESSOR=arm64 -DGGML_METAL=on -DCMAKE_CROSSCOMPILING=ON"
41-
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-*"
40+
# wheel.py-api = py3 produces one wheel for all supported Python versions.
41+
CIBW_BUILD: "cp39-*"
4242
with:
4343
package-dir: .
4444
output-dir: wheelhouse2
4545

46+
- name: Verify wheel archives
47+
run: python3 scripts/verify-wheel-archives.py --expected-count 1 wheelhouse2/*.whl
48+
4649
- uses: actions/upload-artifact@v7
4750
with:
48-
name: wheels-mac_${{ matrix.os }}
51+
name: wheels-mac_macos-14
4952
path: ./wheelhouse2/*.whl
5053

5154
release:
@@ -54,11 +57,20 @@ jobs:
5457
runs-on: ubuntu-latest
5558

5659
steps:
60+
- uses: actions/checkout@v6
61+
62+
- uses: actions/setup-python@v6
63+
with:
64+
python-version: "3.12"
65+
5766
- uses: actions/download-artifact@v8
5867
with:
59-
merge-multiple: true
68+
name: wheels-mac_macos-14
6069
path: dist2
6170

71+
- name: Verify release wheel archives
72+
run: python3 scripts/verify-wheel-archives.py --expected-count 1 dist2/*.whl
73+
6274
- uses: softprops/action-gh-release@v3
6375
with:
6476
files: dist2/*

‎scripts/verify-wheel-archives.py‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Reject damaged wheel archives before uploading or publishing them."""
2+
3+
import argparse
4+
import sys
5+
import zipfile
6+
from pathlib import Path
7+
8+
9+
def main() -> int:
10+
parser = argparse.ArgumentParser(description=__doc__)
11+
parser.add_argument("--expected-count", type=int)
12+
parser.add_argument("wheels", nargs="+")
13+
args = parser.parse_args()
14+
15+
if args.expected_count is not None and len(args.wheels) != args.expected_count:
16+
print(
17+
f"Expected {args.expected_count} wheel archive(s), found {len(args.wheels)}",
18+
file=sys.stderr,
19+
)
20+
return 1
21+
22+
failed = False
23+
for name in args.wheels:
24+
path = Path(name)
25+
try:
26+
with zipfile.ZipFile(path) as archive:
27+
bad_file = archive.testzip()
28+
if bad_file is not None:
29+
raise zipfile.BadZipFile(f"bad CRC in {bad_file}")
30+
except (OSError, zipfile.BadZipFile) as exc:
31+
print(f"Invalid wheel archive {path}: {exc}", file=sys.stderr)
32+
failed = True
33+
else:
34+
print(f"Valid wheel archive: {path}")
35+
36+
return 1 if failed else 0
37+
38+
39+
if __name__ == "__main__":
40+
sys.exit(main())

0 commit comments

Comments
 (0)