@@ -3,180 +3,170 @@ name: Build, test, release
33on :
44 push :
55 branches :
6- - ' * '
6+ - " * "
77 tags :
8- - ' [0-9]+.[0-9]+.[0-9]+'
9- - ' [0-9]+.[0-9]+.[0-9]+.dev[0-9]+'
10-
11- env :
12- PY_VERSIONS_STR : >-
13- ["3.8", "3.9", "3.10", "3.11", "3.12"]
14- VERSIONS_LINUX_STR : >-
15- ["manylinux2014", "manylinux_2_28"]
16- VERSIONS_MACOS_STR : >-
17- ["macos-11", "macos-12"]
18- VERSIONS_WINDOWS_STR : >-
19- ["windows-2022"]
20-
8+ - " [0-9]+.[0-9]+.[0-9]+"
9+ - " [0-9]+.[0-9]+.[0-9]+.dev[0-9]+"
2110
2211jobs :
23- pass-env :
24- runs-on : ubuntu-latest
25- outputs :
26- py-versions-str : ${{ steps.set-env.outputs.py_versions_str }}
27- versions-linux-str : ${{ steps.set-env.outputs.versions_linux_str }}
28- versions-macos-str : ${{ steps.set-env.outputs.versions_macos_str }}
29- versions-windows-str : ${{ steps.set-env.outputs.versions_windows_str }}
30- is-from-tag-str : ${{ steps.set-env.outputs.is_from_tag_str }}
31- is-for-release-str : ${{ steps.set-env.outputs.is_for_release_str }}
32- steps :
33- - id : set-env
34- run : |
35- echo "py_versions_str=${{ toJSON(env.PY_VERSIONS_STR) }}" >> "$GITHUB_OUTPUT"
36- echo "versions_linux_str=${{ toJSON(env.VERSIONS_LINUX_STR) }}" >> "$GITHUB_OUTPUT"
37- echo "versions_macos_str=${{ toJSON(env.VERSIONS_MACOS_STR) }}" >> "$GITHUB_OUTPUT"
38- echo "versions_windows_str=${{ toJSON(env.VERSIONS_WINDOWS_STR) }}" >> "$GITHUB_OUTPUT"
39- echo "is_from_tag_str=${{ toJSON(github.ref_type == 'tag') }}" >> "$GITHUB_OUTPUT"
40- echo "is_for_release_str=${{ toJSON(!contains(github.ref_name, 'dev')) }}" >> "$GITHUB_OUTPUT"
41- build-linux :
42- needs : pass-env
43- strategy :
44- fail-fast : false
45- matrix :
46- image-name : ${{ fromJSON(needs.pass-env.outputs.versions-linux-str) }}
47- image-arch :
48- - x86_64
49- py-version : ${{ fromJSON(needs.pass-env.outputs.py-versions-str) }}
50- runs-on : ubuntu-latest
51- container :
52- image : quay.io/pypa/${{ matrix.image-name }}_${{ matrix.image-arch }}
53- steps :
54- - uses : actions/checkout@v3
55- with :
56- submodules : true
57- - uses : ./.github/actions/setup-poetry
58- with :
59- key-base : ${{ matrix.image-name }}_${{ matrix.image-arch }}-py${{ matrix.py-version }}
60- use-pipx : true
61- use-specific-python-version : true
62- specific-python-version : ${{ matrix.py-version }}
63- - run : make test
64- - uses : ./.github/actions/upload-artifacts
65- with :
66- make-binary : true
67- repair-manylinux : true
68- manylinux-target : ${{ matrix.image-name}}_${{ matrix.image-arch }}
69- if : ${{ fromJSON(needs.pass-env.outputs.is-from-tag-str) }}
70- build-macos :
71- needs : pass-env
72- strategy :
73- fail-fast : false
74- matrix :
75- arch : ${{ fromJSON(needs.pass-env.outputs.versions-macos-str) }}
76- py-version : ${{ fromJSON(needs.pass-env.outputs.py-versions-str) }}
77- runs-on : ${{ matrix.arch }}
78- steps :
79- - uses : actions/checkout@v3
80- with :
81- submodules : true
82- - uses : actions/setup-python@v3
83- with :
84- python-version : ${{ matrix.py-version }}
85- - uses : ./.github/actions/setup-poetry
86- with :
87- key-base : ${{ matrix.arch }}-py${{ matrix.py-version }}
88- use-pipx : false
89- use-specific-python-version : false
90- - run : make test
91- - uses : ./.github/actions/upload-artifacts
92- with :
93- make-binary : true
94- if : ${{ fromJSON(needs.pass-env.outputs.is-from-tag-str) }}
95- build-windows :
96- needs : pass-env
12+ build :
9713 strategy :
9814 fail-fast : false
9915 matrix :
100- arch : ${{ fromJSON(needs.pass-env.outputs.versions-windows-str) }}
101- py-version : ${{ fromJSON(needs.pass-env.outputs.py-versions-str) }}
102- runs-on : ${{ matrix.arch }}
16+ python-version : ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
17+ os : [ubuntu-latest, macos-13, macos-14, macos-15, windows-2022]
18+ manylinux : [null, "manylinux_2_28_x86_64", "manylinux_2_28_aarch64"]
19+ exclude :
20+ # Exclude manylinux for non-Linux platforms
21+ - os : macos-13
22+ manylinux : " manylinux_2_28_x86_64"
23+ - os : macos-13
24+ manylinux : " manylinux_2_28_aarch64"
25+ - os : macos-14
26+ manylinux : " manylinux_2_28_x86_64"
27+ - os : macos-14
28+ manylinux : " manylinux_2_28_aarch64"
29+ - os : macos-15
30+ manylinux : " manylinux_2_28_x86_64"
31+ - os : macos-15
32+ manylinux : " manylinux_2_28_aarch64"
33+ - os : windows-2022
34+ manylinux : " manylinux_2_28_x86_64"
35+ - os : windows-2022
36+ manylinux : " manylinux_2_28_aarch64"
37+ # Exclude null manylinux for Linux
38+ - os : ubuntu-latest
39+ manylinux : null
40+
41+ runs-on : ${{ matrix.os }}
42+ container : ${{ matrix.manylinux != 'manylinux_2_28_aarch64' && matrix.manylinux && format('quay.io/pypa/{0}', matrix.manylinux) || null }}
43+
10344 steps :
104- - uses : actions/checkout@v3
45+ # Set up QEMU for aarch64 emulation
46+ - name : Set up QEMU
47+ uses : docker/setup-qemu-action@v3
48+ if : matrix.manylinux == 'manylinux_2_28_aarch64'
49+
50+ - uses : actions/checkout@v4
10551 with :
10652 submodules : true
53+
54+ # Install libffi-devel for manylinux_2_28 and Python 3.13
55+ - name : Install system dependencies
56+ if : matrix.manylinux == 'manylinux_2_28_x86_64' && matrix.python-version == '3.13'
57+ run : |
58+ yum install -y libffi-devel
59+ shell : bash
60+
61+ # Windows specific setup
10762 - uses : ./.github/actions/setup-mingw
63+ if : runner.os == 'Windows'
10864 with :
109- key-base : ${{ matrix.arch }}-py${{ matrix.py-version }}
110- - uses : actions/setup-python@v3
65+ key-base : ${{ matrix.os }}-py${{ matrix.python-version }}
66+
67+ # Setup Python (not for Linux containers)
68+ - uses : actions/setup-python@v4
69+ if : runner.os != 'Linux' || !matrix.manylinux
11170 with :
112- python-version : ${{ matrix.py-version }}
71+ python-version : ${{ matrix.python-version }}
72+
11373 - uses : ./.github/actions/setup-poetry
74+ if : matrix.manylinux != 'manylinux_2_28_aarch64'
11475 with :
115- key-base : ${{ matrix.arch }}-py${{ matrix.py-version }}
116- use-pipx : false
117- use-specific-python-version : false
76+ key-base : ${{ matrix.os }}-${{ matrix.manylinux || 'native' }}-py${{ matrix.python-version }}
77+ use-pipx : ${{ matrix.manylinux && 'true' || 'false' }}
78+ use-specific-python-version : ${{ matrix.manylinux && 'true' || 'false' }}
79+ specific-python-version : ${{ matrix.python-version }}
80+
81+ # Run tests for aarch64 in Docker
82+ - name : Run tests in aarch64 container
83+ if : matrix.manylinux == 'manylinux_2_28_aarch64'
84+ run : |
85+ docker run --rm -v ${{ github.workspace }}:/work -w /work \
86+ --platform linux/arm64 \
87+ quay.io/pypa/manylinux_2_28_aarch64 \
88+ bash -c "
89+ # Install Python if needed
90+ if ! command -v python${{ matrix.python-version }} &> /dev/null; then
91+ PYTHON_VERSION=\"${{ matrix.python-version }}\"
92+ yum install -y python\${PYTHON_VERSION//./-} python\${PYTHON_VERSION//./-}-devel
93+ fi
94+
95+ # Install pipx and poetry
96+ python${{ matrix.python-version }} -m pip install pipx
97+ python${{ matrix.python-version }} -m pipx install poetry
98+ export PATH=\"\$HOME/.local/bin:\$PATH\"
99+
100+ # Configure poetry
101+ poetry config --local virtualenvs.in-project true
102+ poetry env use python${{ matrix.python-version }}
103+ poetry install
104+
105+ # Run tests
106+ make test
107+ "
108+
109+ # Run tests
118110 - run : make test
111+ if : matrix.manylinux != 'manylinux_2_28_aarch64'
112+
113+ # Upload artifacts for tagged builds
119114 - uses : ./.github/actions/upload-artifacts
120115 with :
121116 make-binary : true
122- if : ${{ fromJSON(needs.pass-env.outputs.is-from-tag-str) }}
117+ repair-manylinux : ${{ matrix.manylinux && 'true' || 'false' }}
118+ manylinux-target : ${{ matrix.manylinux }}
119+ if : github.ref_type == 'tag'
120+
123121 package-source :
124- needs :
125- - pass-env
126- - build-linux
127- - build-macos
128- - build-windows
122+ needs : build
129123 runs-on : ubuntu-latest
130- if : ${{ fromJSON(needs.pass-env.outputs.is-from-tag-str) }}
124+ if : github.ref_type == 'tag'
131125 steps :
132- - uses : actions/checkout@v3
126+ - uses : actions/checkout@v4
133127 with :
134128 submodules : true
135- - uses : actions/setup-python@v3
129+ - uses : actions/setup-python@v4
136130 with :
137- python-version : ${{ fromJSON(needs.pass-env.outputs.py-versions-str)[0] }}
131+ python-version : " 3.8 "
138132 - uses : ./.github/actions/setup-poetry
139133 with :
140- key-base : source_linux-py${{ fromJSON(needs.pass-env.outputs.py-versions-str)[0] }}
134+ key-base : source_linux-py3.8
141135 use-pipx : false
142136 use-specific-python-version : false
143137 - uses : ./.github/actions/upload-artifacts
144138 with :
145139 make-binary : false
140+
146141 upload-pypi :
147- needs :
148- - pass-env
149- - build-linux
150- - build-macos
151- - build-windows
152- - package-source
142+ needs : [build, package-source]
153143 runs-on : ubuntu-latest
154- if : ${{ fromJSON(needs.pass-env.outputs.is-from-tag-str) }}
144+ if : github.ref_type == 'tag'
155145 steps :
156- - uses : actions/checkout@v3
146+ - uses : actions/checkout@v4
157147 with :
158148 submodules : true
159- - uses : actions/setup-python@v3
149+ - uses : actions/setup-python@v4
160150 with :
161- python-version : ${{ fromJSON(needs.pass-env.outputs.py-versions-str)[0] }}
162- - uses : actions/download-artifact@v2
151+ python-version : " 3.8 "
152+ - uses : actions/download-artifact@v3
163153 with :
164154 path : dist
165155 - uses : ./.github/actions/setup-poetry
166156 with :
167- key-base : source_linux-py${{ fromJSON(needs.pass-env.outputs.py-versions-str)[0] }}
157+ key-base : source_linux-py3.8
168158 use-pipx : false
169159 use-specific-python-version : false
170160 - uses : pypa/gh-action-pypi-publish@release/v1
171161 with :
172162 user : __token__
173163 password : ${{ secrets.PYPI_API_TOKEN }}
174164 packages_dir : dist/artifact/
175- if : ${{ fromJSON(needs.pass-env.outputs.is-for-release-str ) }}
165+ if : ${{ !contains(github.ref_name, 'dev' ) }}
176166 - uses : pypa/gh-action-pypi-publish@release/v1
177167 with :
178168 user : __token__
179169 password : ${{ secrets.TESTPYPI_API_TOKEN }}
180170 packages_dir : dist/artifact/
181171 repository_url : https://test.pypi.org/legacy/
182- if : ${{ !fromJSON(needs.pass-env.outputs.is-for-release-str ) }}
172+ if : ${{ contains(github.ref_name, 'dev' ) }}
0 commit comments