Skip to content

Commit b465ee3

Browse files
[MRG] Add M1 mac builds and fix nightly build (#513)
* Add cross-compile helper from scikit * Fix lint * Try cibuildwheel * Add CIBW_BUILD env var * Use CIBW_BEFORE_BUILD * Skip 32-bit on windows * Swap '>' to '|' for yaml * Use '>' and '&&' * Add CIBW_BEFORE_TEST * Reinstall deps before testing * Cleanup * Use PYTHON_CROSSENV for mac builds * Skip musl builds * Fix format step? * Fix README check * Customize job names * Remove 'Python' from job names * Move 'make version' to CIBW_BEFORE_ALL * Update nightly to use cibuildwheel * Fix which versions we build * Don't use DEPENDENCIES env var * Skip musllinux builds * Use batch for windows * Try all caps? * Single percent * Try quotes? * Use pip instead of python -m * Back to 2 percents * Just try a bash script * Add slack notifications back * Remove architecture from slack message * Update whats new
1 parent 4869c43 commit b465ee3

File tree

5 files changed

+86
-197
lines changed

5 files changed

+86
-197
lines changed

.github/utils/build_and_test_aarch64.sh

-34
This file was deleted.

.github/workflows/build_and_deploy.yml

+43-96
Original file line numberDiff line numberDiff line change
@@ -18,79 +18,76 @@ concurrency:
1818

1919
jobs:
2020
build-and-deploy:
21-
name: Build and Deploy
2221
strategy:
2322
matrix:
24-
os: [windows-latest, macos-latest]
25-
python-version: ['3.7', '3.8', '3.9', '3.10']
23+
python3-minor-version: [7, 8, 9, 10]
24+
os: [macos-latest, ubuntu-latest, windows-latest]
2625
defaults:
2726
run:
2827
shell: bash
28+
env:
29+
PYTHON_VERSION: ${{ format('3.{0}', matrix.python3-minor-version) }}
30+
PYTHON_EXECUTABLE: ${{ format('cp3{0}', matrix.python3-minor-version) }}
2931

3032
runs-on: ${{ matrix.os }}
33+
name: Build and Deploy (${{ matrix.os }}, 3.${{ matrix.python3-minor-version }})
3134

3235
steps:
3336
# This LOOKS like it is checking out 'master', but it is using the 'master' version of the checkout action
3437
# It is actually checking out the most recent version on this branch
3538
- name: Checkout
3639
uses: actions/checkout@master
3740

41+
# Python interpreter used by cibuildwheel, but it uses a different one internally
3842
- name: Setting up Python
39-
uses: actions/setup-python@v2
40-
with:
41-
python-version: ${{ matrix.python-version }}
42-
43-
# https://github.com/actions/cache/blob/master/examples.md#multiple-oss-in-a-workflow
44-
- name: Checking for cached pip dependencies (macOS)
45-
if: startsWith(runner.os, 'macOS')
46-
uses: actions/cache@v1
43+
uses: actions/setup-python@v3
4744
with:
48-
path: ~/Library/Caches/pip
49-
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
45+
python-version: ${{ env.PYTHON_VERSION }}
5046

51-
- name: Checking for cached pip dependencies (Windows)
52-
if: startsWith(runner.os, 'Windows')
53-
uses: actions/cache@v1
47+
- name: Set up QEMU
48+
if: runner.os == 'Linux'
49+
uses: docker/setup-qemu-action@v1
5450
with:
55-
path: ~\AppData\Local\pip\Cache
56-
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
57-
58-
- name: Updating pip
59-
run: python -m pip install --upgrade pip
60-
61-
- name: Installing requirements
62-
run: |
63-
pip install -r build_tools/build_requirements.txt
64-
pip install -r requirements.txt
51+
platforms: all
6552

6653
# We build the source archive separately because of this: https://github.com/alkaline-ml/pmdarima/pull/136#discussion_r279781731
6754
# We build it first because of this: https://github.com/alkaline-ml/pmdarima/issues/448
6855
- name: Building source distribution
6956
run: make version sdist
7057

71-
- name: Building wheel
72-
run: make version bdist_wheel
73-
74-
- name: Installing generated wheel
75-
run: pip install --pre --no-index --find-links dist/ pmdarima
76-
77-
- name: Running unit tests
78-
run: |
79-
if [ "${{ matrix.os }}" == "macos-latest" ]; then
80-
export PMD_MPL_BACKEND=TkAgg
81-
fi
82-
pytest --showlocals --durations=20 --pyargs pmdarima
58+
- name: Install cibuildwheel
59+
run: python -m pip install cibuildwheel==2.9.0 # TODO: Do we want this pinned?
8360

84-
- name: Checking for numpy regression
85-
run: |
86-
pip install --upgrade numpy
87-
if [ "${{ matrix.os }}" == "macos-latest" ]; then
88-
export PMD_MPL_BACKEND=TkAgg
89-
fi
90-
pytest --showlocals --durations=20 --pyargs pmdarima
61+
- name: Building and testing wheels
62+
run: python -m cibuildwheel --output-dir dist
63+
env:
64+
# TODO: Move Linux x86_64 builds to GHA?
65+
CIBW_ARCHS_LINUX: "aarch64"
66+
CIBW_ARCHS_MACOS: "x86_64 arm64"
67+
CIBW_ARCHS_WINDOWS: "AMD64"
68+
CIBW_BEFORE_ALL: make version
69+
CIBW_BEFORE_BUILD: >
70+
pip install -r build_tools/build_requirements.txt &&
71+
pip install -r requirements.txt
72+
# Tests are run in a separate virtual env, so we need to re-install deps
73+
CIBW_BEFORE_TEST: >
74+
pip install -r build_tools/build_requirements.txt &&
75+
pip install -r requirements.txt
76+
CIBW_BUILD: "${{ env.PYTHON_EXECUTABLE }}-*"
77+
CIBW_ENVIRONMENT_MACOS: PMD_MPL_BACKEND=TkAgg PYTHON_CROSSENV=true
78+
# No support for pypy or musl
79+
CIBW_SKIP: "pp* *-musllinux_*"
80+
# Runs tests and checks for a numpy regression by upgrading numpy and running tests again
81+
CIBW_TEST_COMMAND: >
82+
pytest --showlocals --durations=20 --pyargs pmdarima &&
83+
pip install --upgrade numpy &&
84+
pytest --showlocals --durations=20 --pyargs pmdarima
85+
# Avoid testing on emulated architectures
86+
CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x} *-macosx_arm64"
9187

9288
- name: Checking README compatibility
9389
run: |
90+
python -m pip install "twine>=1.13.0" readme_renderer
9491
if python -c "from twine.commands.check import check; check(['dist/*'])" | grep "warning"; then
9592
echo "README will not render properly on PyPI"
9693
exit 1
@@ -115,57 +112,7 @@ jobs:
115112
- name: Ensuring sdist can be installed
116113
run: pip install dist/$(ls dist | grep tar)
117114

118-
- name: Ensuring VERSION file existis
119-
id: version_check # Need this to refer to output below
120-
run: |
121-
if [ -f "${GITHUB_WORKSPACE}/pmdarima/VERSION" ]; then
122-
echo "VERSION file exists"
123-
echo "::set-output name=version_exists::true"
124-
else
125-
echo "VERSION file does not exist"
126-
echo "::set-output name=version_exists::false"
127-
fi
128-
129-
- name: Deploying to PyPI
130-
# Only deploy on tags and when VERSION file created
131-
if: startsWith(github.ref, 'refs/tags') && success() && steps.version_check.outputs.version_exists == 'true'
132-
run: |
133-
chmod +x build_tools/github/deploy.sh
134-
./build_tools/github/deploy.sh
135-
env:
136-
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
137-
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
138-
139-
build-and-deploy-aarch64:
140-
name: 'Build and Deploy (aarch64)'
141-
runs-on: ubuntu-latest
142-
strategy:
143-
matrix:
144-
python-version: [cp37-cp37m, cp38-cp38, cp39-cp39, cp310-cp310]
145-
env:
146-
python: /opt/python/${{ matrix.python-version }}/bin/python
147-
image: quay.io/pypa/manylinux_2_28_aarch64
148-
defaults:
149-
run:
150-
shell: bash
151-
152-
steps:
153-
- name: Checkout
154-
uses: actions/checkout@master
155-
156-
- name: Setup QEMU
157-
uses: docker/setup-qemu-action@v1
158-
159-
- name: Build and Test
160-
run: |
161-
chmod +x .github/utils/build_and_test_aarch64.sh
162-
docker run --rm \
163-
-v ${{ github.workspace }}:/workspace \
164-
--workdir=/workspace \
165-
${{ env.image }} \
166-
.github/utils/build_and_test_aarch64.sh ${{ env.python }}
167-
168-
- name: Ensuring VERSION file existis
115+
- name: Ensuring VERSION file exists
169116
id: version_check # Need this to refer to output below
170117
run: |
171118
if [ -f "${GITHUB_WORKSPACE}/pmdarima/VERSION" ]; then

.github/workflows/nightly_cron.yml

+31-63
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,11 @@ jobs:
2424
fail-fast: false
2525
matrix:
2626
os: [windows-latest, macos-latest, ubuntu-latest]
27-
python-version: ['3.9']
28-
architecture: ['x86', 'x64']
29-
exclude:
30-
# Don't build 32-bit on Mac or Linux
31-
- os: macos-latest
32-
architecture: x86
33-
34-
- os: ubuntu-latest
35-
architecture: x86
27+
python-version: ['3.10']
28+
python-executable: ['cp310']
29+
defaults:
30+
run:
31+
shell: bash
3632

3733
runs-on: ${{ matrix.os }}
3834

@@ -44,19 +40,13 @@ jobs:
4440
uses: actions/checkout@master
4541

4642
- name: Setting up Python
47-
uses: actions/setup-python@v2
43+
uses: actions/setup-python@v3
4844
with:
4945
python-version: ${{ matrix.python-version }}
50-
architecture: ${{ matrix.architecture }}
5146

5247
- name: Set Run ID
5348
id: definition # Needed to retrieve the output of this step later
5449
run: echo "::set-output name=run_id::$GITHUB_RUN_ID"
55-
shell: bash
56-
57-
- name: Updating pip
58-
run: python -m pip install --upgrade pip
59-
shell: bash
6050

6151
- name: Collecting naked dependencies
6252
id: dependencies # Needed to retrieve the output of this step later
@@ -65,60 +55,43 @@ jobs:
6555
echo "::set-output name=latest_dependencies::$dependencies"
6656
shell: bash
6757

68-
# https://github.com/actions/cache/blob/master/examples.md#using-pip-to-get-cache-location
69-
- name: Get pip cache dir
70-
id: pip-cache-dir-path
71-
run: echo "::set-output name=dir::$(pip cache dir)"
58+
- name: Install cibuildwheel
59+
run: python -m pip install cibuildwheel==2.9.0 # TODO: Do we want this pinned?
7260

73-
- name: Generating cache key file
61+
- name: Generating dependency table
7462
id: dependency-table # Needed to set output of job
7563
run: |
7664
pip install requests tabulate
7765
table=$(python .github/utils/get_dependency_releases.py $DEPENDENCIES)
78-
echo $table > dependencies_key.txt
7966
8067
# This is used in the next job (if necessary) rather than re-running the above
8168
echo "::set-output name=table::$table"
82-
shell: bash
8369
env:
8470
DEPENDENCIES: ${{ steps.dependencies.outputs.latest_dependencies }}
8571

86-
- name: Check for cache hit
87-
id: pip-cache
88-
uses: actions/cache@v2
89-
with:
90-
path: ${{ steps.pip-cache-dir-path.outputs.dir }}
91-
key: ${{ runner.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('**/dependencies_key.txt') }}
92-
93-
# We install one-by-one because some dependencies depend on others
94-
- name: Installing dependencies
95-
if: steps.pip-cache.outputs.cache-hit != 'true'
96-
run: |
97-
for dependency in $DEPENDENCIES; do
98-
python -m pip install $dependency
99-
done
100-
shell: bash
72+
- name: Building and testing wheel
73+
run: python -m cibuildwheel --output-dir dist
10174
env:
102-
DEPENDENCIES: ${{ steps.dependencies.outputs.latest_dependencies }}
103-
104-
- name: Building wheel
105-
if: steps.pip-cache.outputs.cache-hit != 'true'
106-
run: make bdist_wheel
107-
shell: bash
108-
109-
- name: Installing generated wheel
110-
if: steps.pip-cache.outputs.cache-hit != 'true'
111-
run: pip install --pre --no-index --find-links dist/ pmdarima
112-
shell: bash
113-
114-
- name: Running unit tests
115-
if: steps.pip-cache.outputs.cache-hit != 'true'
116-
run: |
117-
if [ "${{ matrix.os }}" == "macos-latest" ]; then
118-
export PMD_MPL_BACKEND=TkAgg
119-
fi
120-
pytest --showlocals --durations=20 --pyargs pmdarima
121-
shell: bash
75+
CIBW_ARCHS_LINUX: "x86_64"
76+
CIBW_ARCHS_MACOS: "x86_64"
77+
CIBW_ARCHS_WINDOWS: "AMD64"
78+
CIBW_BEFORE_BUILD: >
79+
for dependency in ${{ steps.dependencies.outputs.latest_dependencies }}; do
80+
pip install $dependency
81+
done
82+
# Windows runs a batch script that I couldn't get to work, so we just force it to run bash
83+
CIBW_BEFORE_BUILD_WINDOWS: bash -c 'for dependency in ${{ steps.dependencies.outputs.latest_dependencies }}; do pip install $dependency; done'
84+
# Tests are run in a separate virtual env, so we need to re-install deps
85+
CIBW_BEFORE_TEST: >
86+
for dependency in ${{ steps.dependencies.outputs.latest_dependencies }}; do
87+
pip install $dependency
88+
done
89+
CIBW_BEFORE_TEST_WINDOWS: bash -c 'for dependency in ${{ steps.dependencies.outputs.latest_dependencies }}; do pip install $dependency; done'
90+
CIBW_BUILD: "${{ matrix.python-executable }}-*"
91+
CIBW_ENVIRONMENT_MACOS: PMD_MPL_BACKEND=TkAGG
92+
# No support for pypy or musl
93+
CIBW_SKIP: "pp* *-musllinux_*"
94+
CIBW_TEST_COMMAND: pytest --showlocals --durations=20 --pyargs pmdarima
12295

12396
# https://github.com/marketplace/actions/action-slack#custom-notification
12497
- name: Posting to Slack
@@ -141,11 +114,6 @@ jobs:
141114
value: '${{ matrix.os }}',
142115
short: false
143116
},
144-
{
145-
title: 'Architecture',
146-
value: '${{ matrix.architecture }}',
147-
short: false
148-
},
149117
{
150118
title: 'Python Version',
151119
value: '${{ matrix.python-version }}',

doc/whats_new.rst

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ What's new in pmdarima
77
As new releases of pmdarima are pushed out, the following list (introduced in
88
v0.8.1) will document the latest features.
99

10+
`v2.0.1 <http://alkaline-ml.com/pmdarima/2.0.1>`_
11+
-------------------------------------------------
12+
13+
* Add support for macOS with M1 chip
14+
1015
`v2.0.0 <http://alkaline-ml.com/pmdarima/2.0.0>`_
1116
-------------------------------------------------
1217

pmdarima/_build_utils/pre_build_helpers.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ def compile_test_program(code, extra_preargs=[], extra_postargs=[]):
5050
extra_preargs=extra_preargs,
5151
extra_postargs=extra_postargs)
5252

53-
# Run test program
54-
# will raise a CalledProcessError if return code was non-zero
55-
output = subprocess.check_output('./test_program')
56-
output = output.decode(sys.stdout.encoding or 'utf-8').splitlines()
53+
if "PYTHON_CROSSENV" not in os.environ:
54+
# Run test program if not cross compiling
55+
# will raise a CalledProcessError if return code was non-zero
56+
output = subprocess.check_output('./test_program')
57+
output = output.decode(sys.stdout.encoding or 'utf-8').splitlines() # noqa
58+
else:
59+
output = []
5760
except Exception:
5861
raise
5962
finally:

0 commit comments

Comments
 (0)